From 211eab9f448f56cdf3856dc13f17810ec84834a9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Jan 2024 13:55:15 +0100 Subject: [PATCH] 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: {},