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,