diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart index 2f8820d..7f230fb 100644 --- a/lib/screens/home/top_items/top_items_lists.dart +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -4,7 +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/home/top_items/top_items.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_items_section.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -106,7 +106,7 @@ class TopItemsLists extends StatelessWidget { case HomeTopItems.queriedDomains: return Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topQueriedDomains, type: HomeTopItems.queriedDomains, data: statusProvider.serverStatus?.stats.topQueriedDomains ?? [], @@ -134,7 +134,7 @@ class TopItemsLists extends StatelessWidget { case HomeTopItems.blockedDomains: return Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topBlockedDomains, type: HomeTopItems.blockedDomains, data: statusProvider.serverStatus?.stats.topBlockedDomains ?? [], @@ -162,7 +162,7 @@ class TopItemsLists extends StatelessWidget { case HomeTopItems.recurrentClients: return Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topClients, type: HomeTopItems.recurrentClients, data: statusProvider.serverStatus?.stats.topClients ?? [], @@ -186,7 +186,7 @@ class TopItemsLists extends StatelessWidget { return statusProvider.serverStatus!.stats.topUpstreamResponses != null ? Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topUpstreams, type: HomeTopItems.topUpstreams, data: statusProvider.serverStatus?.stats.topUpstreamResponses ?? [], @@ -210,7 +210,7 @@ class TopItemsLists extends StatelessWidget { return statusProvider.serverStatus!.stats.topUpstreamsAvgTime != null ? Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.averageUpstreamResponseTime, type: HomeTopItems.avgUpstreamResponseTime, data: statusProvider.serverStatus?.stats.topUpstreamsAvgTime ?? [], diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart new file mode 100644 index 0000000..01ac83e --- /dev/null +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -0,0 +1,324 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/options_menu.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +class TopItemsScreen extends StatefulWidget { + final HomeTopItems type; + final String title; + final bool? isClient; + final List> data; + final bool withProgressBar; + final String Function(dynamic) buildValue; + final List options; + final void Function(dynamic)? onTapEntry; + final bool isFullscreen; + + const TopItemsScreen({ + super.key, + required this.type, + required this.title, + this.isClient, + required this.data, + required this.withProgressBar, + required this.buildValue, + required this.options, + this.onTapEntry, + required this.isFullscreen, + }); + + @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) { + double total = 0; + for (var element in data) { + total = total + double.parse(element.values.toList()[0].toString()); + } + + if (widget.isFullscreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + title: searchActive == true + ? Padding( + padding: const EdgeInsets.only(bottom: 3), + child: 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 + ), + autofocus: true, + ), + ) + : 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: 8) + ], + ), + body: _Content( + buildValue: widget.buildValue, + isClient: widget.isClient, + onTapEntry: widget.onTapEntry, + options: widget.options, + screenData: screenData, + total: total, + withProgressBar: widget.withProgressBar, + ), + ), + ); + } + else { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 1, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + ], + ), + ), + Expanded( + flex: 1, + child: TextField( + controller: searchController, + onChanged: search, + decoration: InputDecoration( + filled: true, + fillColor: Theme.of(context).colorScheme.primary.withOpacity(0.1), + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + contentPadding: const EdgeInsets.only(left: 14, bottom: 9, top: 11), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.circular(25.7), + ), + enabledBorder: UnderlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.circular(25.7), + ), + ), + ), + ), + ], + ), + ), + Expanded( + child: _Content( + buildValue: widget.buildValue, + isClient: widget.isClient, + onTapEntry: widget.onTapEntry, + options: widget.options, + screenData: screenData, + total: total, + withProgressBar: widget.withProgressBar, + ), + ), + ], + ), + ), + ); + } + } +} + +class _Content extends StatelessWidget { + final List> screenData; + final bool? isClient; + final List options; + final bool withProgressBar; + final void Function(dynamic)? onTapEntry; + final String Function(dynamic) buildValue; + final double total; + + const _Content({ + required this.screenData, + required this.isClient, + required this.options, + required this.withProgressBar, + required this.onTapEntry, + required this.buildValue, + required this.total, + }); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + if (screenData.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.only(top: 0), + itemCount: screenData.length, + itemBuilder: (context, index) { + String? name; + if (isClient != null && isClient == true) { + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + } catch (e) { + // ---- // + } + } + + return OptionsMenu( + options: options, + value: screenData[index].keys.toList()[0], + onTap: onTapEntry != null + ? (v) { + onTapEntry!(v); + Navigator.pop(context); + } + : null, + child: CustomListTile( + title: screenData[index].keys.toList()[0], + trailing: Text( + buildValue(screenData[index].values.toList()[0]), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 5), + ], + if (withProgressBar == true) Row( + children: [ + SizedBox( + width: 50, + child: Text( + "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), + ), + ), + const SizedBox(width: 10), + Flexible( + child: LinearPercentIndicator( + animation: true, + lineHeight: 4, + animationDuration: 500, + curve: Curves.easeOut, + percent: screenData[index].values.toList()[0]/total, + barRadius: const Radius.circular(5), + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + ), + ), + const SizedBox(width: 10), + ], + ), + ], + ) + ), + ); + } + ); + } + else { + return Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.noItemsSearch, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ); + } + } +} \ No newline at end of file diff --git a/lib/screens/home/top_items/top_items.dart b/lib/screens/home/top_items/top_items_section.dart similarity index 86% rename from lib/screens/home/top_items/top_items.dart rename to lib/screens/home/top_items/top_items_section.dart index 00fa63c..f084b3f 100644 --- a/lib/screens/home/top_items/top_items.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -7,15 +7,14 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; -import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; -import 'package:adguard_home_manager/screens/top_items/top_items.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_items_screen.dart'; import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class TopItems extends StatefulWidget { +class TopItemsSection extends StatefulWidget { final HomeTopItems type; final String label; final List> data; @@ -25,7 +24,7 @@ class TopItems extends StatefulWidget { final List menuOptions; final void Function(dynamic)? onTapEntry; - const TopItems({ + const TopItemsSection({ super.key, required this.type, required this.label, @@ -38,10 +37,10 @@ class TopItems extends StatefulWidget { }); @override - State createState() => _TopItemsState(); + State createState() => _TopItemsState(); } -class _TopItemsState extends State { +class _TopItemsState extends State { bool _showChart = true; final colors = [ @@ -289,38 +288,37 @@ class _TopItemsState extends State { children: [ TextButton( onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => TopItemsModal( - type: widget.type, - title: widget.label, - isClient: widget.type == HomeTopItems.recurrentClients, - data: widget.data, - withProgressBar: widget.withProgressBar, - buildValue: widget.buildValue, - options: widget.menuOptions, - onTapEntry: widget.onTapEntry, - ) + showGeneralDialog( + context: context, + barrierColor: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => TopItemsScreen( + type: widget.type, + title: widget.label, + isClient: widget.type == HomeTopItems.recurrentClients, + data: widget.data, + withProgressBar: widget.withProgressBar, + buildValue: widget.buildValue, + options: widget.menuOptions, + onTapEntry: widget.onTapEntry, + isFullscreen: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)), ) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => TopItemsScreen( - type: widget.type, - title: widget.label, - isClient: widget.type == HomeTopItems.recurrentClients, - data: widget.data, - withProgressBar: widget.withProgressBar, - buildValue: widget.buildValue, - menuOptions: widget.menuOptions, - onTapEntry: widget.onTapEntry, - ) - ) - ) - } + ) }, child: Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart deleted file mode 100644 index 498ce75..0000000 --- a/lib/screens/top_items/top_items.dart +++ /dev/null @@ -1,241 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:percent_indicator/percent_indicator.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/options_menu.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; - -import 'package:adguard_home_manager/models/menu_option.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; - -class TopItemsScreen extends StatefulWidget { - final HomeTopItems type; - final String title; - final bool? isClient; - final List> data; - final bool withProgressBar; - final String Function(dynamic) buildValue; - final List menuOptions; - final void Function(dynamic)? onTapEntry; - - const TopItemsScreen({ - super.key, - required this.type, - required this.title, - this.isClient, - required this.data, - required this.withProgressBar, - required this.buildValue, - required this.menuOptions, - this.onTapEntry, - }); - - @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 statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - double total = 0; - for (var element in data) { - total = total + double.parse(element.values.toList()[0].toString()); - } - - return Scaffold( - appBar: AppBar( - title: searchActive == true - ? Padding( - padding: const EdgeInsets.only(bottom: 3), - child: 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 - ), - autofocus: true, - ), - ) - : 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) - ], - bottom: PreferredSize( - preferredSize: const Size(double.maxFinite, 1), - child: Container( - width: double.maxFinite, - height: 1, - decoration: BoxDecoration( - color: searchActive == true - ? Colors.grey.withOpacity(0.5) - : Colors.transparent - ), - ), - ), - ), - body: RefreshIndicator( - onRefresh: () async { - final result = await statusProvider.getServerStatus(); - if (mounted && result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverStatusNotRefreshed, - color: Colors.red - ); - } - }, - child: screenData.isNotEmpty - ? ListView.builder( - itemCount: screenData.length, - itemBuilder: (context, index) { - String? name; - if (widget.isClient != null && widget.isClient == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } - - return OptionsMenu( - value: screenData[index].keys.toList()[0], - options: widget.menuOptions, - onTap: widget.onTapEntry != null - ? (v) { - widget.onTapEntry!(v); - Navigator.pop(context); - } - : null, - child: CustomListTile( - title: screenData[index].keys.toList()[0], - trailing: Text( - widget.buildValue(screenData[index].values.toList()[0]), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 5), - ], - if (widget.withProgressBar == true) Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), - ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, - ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) - ), - ); - } - ) - : Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.noItemsSearch, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ) - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart deleted file mode 100644 index 36ea793..0000000 --- a/lib/screens/top_items/top_items_modal.dart +++ /dev/null @@ -1,218 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:percent_indicator/percent_indicator.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/options_menu.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; - -import 'package:adguard_home_manager/models/menu_option.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; - -class TopItemsModal extends StatefulWidget { - final HomeTopItems type; - final String title; - final bool? isClient; - final List> data; - final bool withProgressBar; - final String Function(dynamic) buildValue; - final List options; - final void Function(dynamic)? onTapEntry; - - const TopItemsModal({ - super.key, - required this.type, - required this.title, - this.isClient, - required this.data, - required this.withProgressBar, - required this.buildValue, - required this.options, - this.onTapEntry, - }); - - @override - State createState() => _TopItemsModalState(); -} - -class _TopItemsModalState 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 statusProvider = Provider.of(context); - - double total = 0; - for (var element in data) { - total = total + double.parse(element.values.toList()[0].toString()); - } - - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - flex: 1, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded), - tooltip: AppLocalizations.of(context)!.close, - ), - ], - ), - ), - Expanded( - flex: 1, - child: TextField( - controller: searchController, - onChanged: search, - decoration: InputDecoration( - filled: true, - fillColor: Theme.of(context).colorScheme.primary.withOpacity(0.1), - hintText: AppLocalizations.of(context)!.search, - prefixIcon: const Icon(Icons.search_rounded), - contentPadding: const EdgeInsets.only(left: 14, bottom: 9, top: 11), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent), - borderRadius: BorderRadius.circular(25.7), - ), - enabledBorder: UnderlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent), - borderRadius: BorderRadius.circular(25.7), - ), - ), - ), - ) - ], - ), - ), - if (screenData.isNotEmpty) Flexible( - child: ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: screenData.length, - itemBuilder: (context, index) { - String? name; - if (widget.isClient != null && widget.isClient == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } - - return OptionsMenu( - options: widget.options, - value: screenData[index].keys.toList()[0], - onTap: widget.onTapEntry != null - ? (v) { - widget.onTapEntry!(v); - Navigator.pop(context); - } - : null, - child: CustomListTile( - title: screenData[index].keys.toList()[0], - trailing: Text( - widget.buildValue(screenData[index].values.toList()[0]), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 5), - ], - if (widget.withProgressBar == true) Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), - ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, - ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) - ), - ); - } - ), - ), - if (screenData.isEmpty) Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.noItemsSearch, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ) - ], - ), - ), - ); - } -} \ No newline at end of file