diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d4e1cfb..3f0a2f8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -388,5 +388,9 @@ "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" + "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" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index b2a0705..e075a89 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -388,5 +388,9 @@ "deleteDnsRewrite": "Eliminar reescritura DNS", "deleteDnsRewriteMessage": "¿Estás seguro que deseas eliminar esta reescritura DNS? Esta acción no se puede deshacer.", "dnsRewriteRuleDeleted": "Reescritura DNS eliminada correctamente", - "dnsRewriteRuleNotDeleted": "La reescritura DNS no pudo ser eliminada" + "dnsRewriteRuleNotDeleted": "La reescritura DNS no pudo ser eliminada", + "addDnsRewrite": "Añadir reescritura DNS", + "addingRewrite": "Añadiend reescritura...", + "dnsRewriteRuleAdded": "Regla de reescritura DNS añadida correctamente", + "dnsRewriteRuleNotAdded": "La regla de reescritura DNS no ha podido ser añadida" } \ No newline at end of file diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart new file mode 100644 index 0000000..f928372 --- /dev/null +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -0,0 +1,164 @@ +import 'package:flutter/material.dart'; +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; + + const AddDnsRewriteModal({ + Key? key, + required this.onConfirm + }) : super(key: key); + + @override + State createState() => _AddDnsRewriteModalState(); +} + +class _AddDnsRewriteModalState extends State { + final TextEditingController domainController = TextEditingController(); + String? domainError; + final TextEditingController answerController = TextEditingController(); + + bool validData = false; + + void validateDomain(String value) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + if (domainRegex.hasMatch(value)) { + setState(() => domainError = null); + } + else { + setState(() => domainError = AppLocalizations.of(context)!.domainNotValid); + } + checkValidValues(); + } + + void checkValidValues() { + if ( + domainController.text != '' && + domainError == null && + answerController.text != '' + ) { + setState(() => validData = true); + } + else { + setState(() => validData = false); + } + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + height: 410, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor, + ), + child: Column( + children: [ + const Padding( + padding: EdgeInsets.only(top: 28), + child: Icon( + Icons.add, + size: 26, + ), + ), + const SizedBox(height: 20), + Text( + AppLocalizations.of(context)!.addDnsRewrite, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 24 + ), + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 28), + 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: 28), + 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, + ), + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only( + top: 20, + bottom: 20, + right: 28 + ), + 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).primaryColor + : Colors.grey + ), + ), + ), + ], + ), + ) + ], + ), + ) + ], + ), + ), + ); + } +} \ 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 90d4080..142a55b 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.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/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'; @@ -103,6 +104,40 @@ class _DnsRewritesWidgetState extends State { } } + void addDnsRewrite(RewriteRulesData rule) async { + 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 + }); + + processModal.close(); + + if (result['result'] == 'success') { + List data = serversProvider.rewriteRules.data!; + data.add(rule); + serversProvider.setRewriteRulesData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsRewriteRuleAdded, + color: Colors.green + ); + } + else { + appConfigProvider.addLog(result['log']); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsRewriteRuleNotAdded, + color: Colors.red + ); + } + } + Widget generateBody() { switch (serversProvider.rewriteRules.loadStatus) { case 0: @@ -241,6 +276,19 @@ class _DnsRewritesWidgetState extends State { title: Text(AppLocalizations.of(context)!.dnsRewrites), ), body: generateBody(), + floatingActionButton: FloatingActionButton( + onPressed: () => { + showModalBottomSheet( + context: context, + builder: (context) => AddDnsRewriteModal( + onConfirm: addDnsRewrite, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + }, + child: const Icon(Icons.add), + ), ); } } \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 7d2f9a9..430afb0 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1428,4 +1428,38 @@ Future deleteDnsRewriteRule({ 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; + } } \ No newline at end of file