From cca12d5664b118a8e5a75c06cdd04337c646e1e6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Oct 2022 23:09:44 +0200 Subject: [PATCH] Added check host --- lib/l10n/app_en.arb | 6 +- lib/l10n/app_es.arb | 6 +- lib/screens/filters/check_host_modal.dart | 222 ++++++++++++++++++++++ lib/screens/filters/filters.dart | 15 ++ lib/services/http_requests.dart | 36 ++++ 5 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 lib/screens/filters/check_host_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index b32392f..491c21b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -287,5 +287,9 @@ "updatingLists": "Updating lists...", "listsUpdated": "lists updated", "listsNotUpdated": "Couldn't update lists", - "listsNotLoaded": "Lists couldn't be loaded" + "listsNotLoaded": "Lists couldn't be loaded", + "domainNotValid": "Domain not valid", + "check": "Check", + "checkingHost": "Checking host...", + "errorCheckingHost": "Host couldn't be checked" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2786119..bcd0984 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -287,5 +287,9 @@ "updatingLists": "Actualizando listas...", "listsUpdated": "listas actualizadas", "listsNotUpdated": "No se pudieron actualizar las listas", - "listsNotLoaded": "No se pudieron cargar las listas" + "listsNotLoaded": "No se pudieron cargar las listas", + "domainNotValid": "Dominio no vĂ¡lido", + "check": "Comprobar", + "checkingHost": "Comprobando host...", + "errorCheckingHost": "No se pudo comprobar el host" } \ No newline at end of file diff --git a/lib/screens/filters/check_host_modal.dart b/lib/screens/filters/check_host_modal.dart new file mode 100644 index 0000000..4e906be --- /dev/null +++ b/lib/screens/filters/check_host_modal.dart @@ -0,0 +1,222 @@ +// 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/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 { + const CheckHostModal({Key? key}) : super(key: key); + + @override + State createState() => _CheckHostModalState(); +} + +class _CheckHostModalState extends State { + final TextEditingController domainController = TextEditingController(); + String? domainError; + + bool isChecking = false; + + Widget? resultWidget; + + 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); + } + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + + void checkHost() async { + setState(() => isChecking = true); + + final result = await checkHostFiltered(server: serversProvider.selectedServer!, host: domainController.text); + + if (result['result'] == 'success') { + final status = getFilteredStatus(context, result['data']['reason']); + setState(() => resultWidget = Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + status['icon'], + size: 18, + color: status['filtered'] == true + ? Colors.red + : Colors.green, + ), + const SizedBox(width: 10), + Text( + status['label'], + style: TextStyle( + color: status['filtered'] == true + ? Colors.red + : 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 + ), + ) + ], + )); + } + + setState(() => isChecking = false); + } + + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Stack( + children: [ + AnimatedContainer( + height: resultWidget != null + ? 350 + : 310, + width: double.maxFinite, + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: Center( + child: Column( + children: [ + const Padding( + padding: EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 26, + ), + ), + const SizedBox(height: 20), + Text( + AppLocalizations.of(context)!.checkHostFiltered, + style: const TextStyle( + fontSize: 24 + ), + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + 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.only( + top: 20, + left: 20, + right: 20 + ), + child: resultWidget, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.all(20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), + ), + const SizedBox(width: 20), + TextButton( + onPressed: checkHost, + child: Text(AppLocalizations.of(context)!.check), + ), + ], + ), + ) + ], + ), + ) + ], + ), + ), + ), + AnimatedOpacity( + opacity: isChecking == true ? 1 : 0, + duration: const Duration(milliseconds: 250), + curve: Curves.easeInOut, + child: IgnorePointer( + ignoring: isChecking == true ? false : true, + child: Container( + height: 310, + width: double.maxFinite, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), + ), + color: Colors.black.withOpacity(0.8) + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const CircularProgressIndicator( + color: Colors.white, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.checkingHost, + style: const TextStyle( + color: Colors.white, + fontSize: 22 + ), + ) + ], + ), + ), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index f11302f..eb4597d 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -5,6 +5,7 @@ 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/functions/snackbar.dart'; @@ -133,6 +134,19 @@ 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, + isDismissible: false, + enableDrag: false + ); + }); + } + return DefaultTabController( length: 3, child: NestedScrollView( @@ -162,6 +176,7 @@ class _FiltersWidgetState extends State with TickerProviderStateM ) ), PopupMenuItem( + onTap: showCheckHostModal, child: Row( children: [ const Icon(Icons.shield_rounded), diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index d7c1fb8..a4ccf8c 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -960,4 +960,40 @@ Future updateLists({ else { return result; } +} + +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'], + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } \ No newline at end of file