From 53113735c8578d93057caf8de07ffccd1f5d3df9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 25 Oct 2022 19:41:49 +0200 Subject: [PATCH] Added search on top items --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- lib/screens/home/status_box.dart | 2 +- lib/screens/home/top_items.dart | 17 +++ lib/screens/logs/log_tile.dart | 9 -- lib/screens/top_items/top_items.dart | 181 ++++++++++++++++++--------- 6 files changed, 148 insertions(+), 71 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fd2b10b..0df88de 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -525,5 +525,8 @@ "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." + "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" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 97ab7d3..b3991df 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -525,5 +525,8 @@ "encryptionConfigNotSaved": "No se pudo guardar la configuración de encriptado", "configError": "Configuration error", "enterOnlyCertificate": "Introduce sólo el certificado. No introduzcas las líneas ---BEGIN--- y ---END---.", - "enterOnlyPrivateKey": "Introduce sólo la clave privada. No introduzcas las líneas ---BEGIN--- y ---END---." + "enterOnlyPrivateKey": "Introduce sólo la clave privada. No introduzcas las líneas ---BEGIN--- y ---END---.", + "noItemsSearch": "No hay items para esa búsqueda.", + "clearSearch": "Limpiar búsqueda", + "exitSearch": "Salir de la búsqueda" } \ No newline at end of file diff --git a/lib/screens/home/status_box.dart b/lib/screens/home/status_box.dart index 7bea088..c7e1f51 100644 --- a/lib/screens/home/status_box.dart +++ b/lib/screens/home/status_box.dart @@ -24,7 +24,7 @@ class StatusBox extends StatelessWidget { color: isEnabled == true ? Colors.green : Colors.red, - borderRadius: BorderRadius.circular(10) + borderRadius: BorderRadius.circular(16) ), child: Row( children: [ diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 03fd4c7..5eee31f 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -72,6 +72,22 @@ class TopItems extends StatelessWidget { ); } + List> generateData() { + switch (type) { + case 'topQueriedDomains': + return serversProvider.serverStatus.data!.stats.topQueriedDomains; + + case 'topBlockedDomains': + return serversProvider.serverStatus.data!.stats.topBlockedDomains; + + case 'topClients': + return serversProvider.serverStatus.data!.stats.topClients; + + default: + return []; + } + } + return SizedBox( child: Column( children: [ @@ -115,6 +131,7 @@ class TopItems extends StatelessWidget { type: type, title: label, isClient: clients, + data: generateData(), ) ) ), diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index bd67b67..2331973 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -151,15 +151,6 @@ class LogTile extends StatelessWidget { child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), - decoration: BoxDecoration( - border: index < length - ? Border( - bottom: BorderSide( - color: Theme.of(context).dividerColor - ) - ) - : null - ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 402aefc..fcc3f71 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -13,50 +13,99 @@ 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 StatelessWidget { +class TopItemsScreen extends StatefulWidget { final String type; final String title; final bool? isClient; + final List> data; const TopItemsScreen({ Key? key, required this.type, required this.title, this.isClient, + required this.data, }) : super(key: key); + @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 serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - List> data = []; - switch (type) { - case 'topQueriedDomains': - data = serversProvider.serverStatus.data!.stats.topQueriedDomains; - break; - - case 'topBlockedDomains': - data = serversProvider.serverStatus.data!.stats.topBlockedDomains; - break; - - case 'topClients': - data = serversProvider.serverStatus.data!.stats.topClients; - break; - - default: - break; - } - int total = 0; for (var element in data) { total = total + int.parse(element.values.toList()[0].toString()); } - return Scaffold( appBar: AppBar( - title: Text(title), + title: searchActive == true + ? 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 + ), + ) + : 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) + ], ), body: RefreshIndicator( onRefresh: () async { @@ -74,47 +123,61 @@ class TopItemsScreen extends StatelessWidget { ); } }, - child: ListView.builder( - itemCount: data.length, - itemBuilder: (context, index) { - String? name; - if (isClient != null && isClient == true) { - try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(data[index].keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } + child: screenData.isNotEmpty + ? ListView.builder( + 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( - title: data[index].keys.toList()[0], - trailing: Text(data[index].values.toList()[0].toString()), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).brightness == Brightness.light - ? Colors.black - : Colors.white + return CustomListTile( + title: screenData[index].keys.toList()[0], + trailing: Text(screenData[index].values.toList()[0].toString()), + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).brightness == Brightness.light + ? Colors.black + : Colors.white + ), + ), + const SizedBox(height: 5), + ], + Text( + "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.iconColor + ), ), - ), - const SizedBox(height: 5), - ], - Text( - "${doubleFormat((data[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.iconColor - ), + ], + ) + ); + } + ) + : Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.noItemsSearch, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 22, + color: Colors.grey ), - ], - ) - ); - } - ), + ), + ), + ) ), ); }