diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f6beb3f..9caaaae 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -614,5 +614,8 @@ "enableList": "Enable list", "screens": "Screens", "copiedClipboard": "Copied to clipboard", - "seeDetails": "See details" + "seeDetails": "See details", + "listNotAvailable": "List not available", + "copyListUrl": "Copy list URL", + "listUrlCopied": "List URL copied to the clipboard" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 88940fd..068f8db 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -614,5 +614,8 @@ "enableList": "Habilitar lista", "screens": "Pantallas", "copiedClipboard": "Copiado al portapapeles", - "seeDetails": "Ver los detalles" + "seeDetails": "Ver los detalles", + "listNotAvailable": "Lista no disponible", + "copyListUrl": "Copiar URL de lista", + "listUrlCopied": "URL de la lista copiada al portapapeles" } \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 8ad0268..ce7e858 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -286,7 +286,7 @@ class _FiltersWidgetState extends State { showDialog( context: context, builder: (context) => ListDetailsScreen( - list: filter, + listId: filter.id, type: type, dialog: true, ), @@ -297,7 +297,7 @@ class _FiltersWidgetState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (context) => ListDetailsScreen( - list: filter, + listId: filter.id, type: type, dialog: false, ) diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index be4ff75..8f87b34 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; +import 'package:adguard_home_manager/screens/filters/list_options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; @@ -87,22 +88,26 @@ class _FiltersListState extends State { ), ), itemsCount: widget.data.length, - contentWidget: (index) => CustomListTile( - title: widget.data[index].name, - subtitle: "${intFormat(widget.data[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - widget.data[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: widget.data[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red + contentWidget: (index) => ListOptionsMenu( + list: widget.data[index], + listType: widget.type, + child: CustomListTile( + title: widget.data[index].name, + subtitle: "${intFormat(widget.data[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + widget.data[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: widget.data[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => widget.onOpenDetailsScreen(widget.data[index], widget.type), ), - onTap: () => widget.onOpenDetailsScreen(widget.data[index], widget.type), ), noData: Container( width: double.maxFinite, diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 337a1e8..d8bc00a 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'dart:io'; import 'package:flutter/material.dart'; @@ -6,6 +8,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; +import 'package:adguard_home_manager/screens/filters/list_options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; @@ -128,8 +131,9 @@ class FiltersTripleColumn extends StatelessWidget { type: 'whitelist', widget: (fn) => IconButton( onPressed: fn, - icon: const Icon(Icons.add_rounded) - ) + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addWhitelist, + ), ) ], ), @@ -137,22 +141,26 @@ class FiltersTripleColumn extends StatelessWidget { Expanded( child: ListView.builder( itemCount: serversProvider.filtering.data!.whitelistFilters.length, - itemBuilder: (context, index) => CustomListTile( - title: serversProvider.filtering.data!.whitelistFilters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - serversProvider.filtering.data!.whitelistFilters[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red + itemBuilder: (context, index) => ListOptionsMenu( + list: serversProvider.filtering.data!.whitelistFilters[index], + listType: 'whitelist', + child: CustomListTile( + title: serversProvider.filtering.data!.whitelistFilters[index].name, + subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + serversProvider.filtering.data!.whitelistFilters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), ), ), ) @@ -179,7 +187,8 @@ class FiltersTripleColumn extends StatelessWidget { type: 'blacklist', widget: (fn) => IconButton( onPressed: fn, - icon: const Icon(Icons.add_rounded) + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addBlacklist, ) ) ], @@ -188,22 +197,26 @@ class FiltersTripleColumn extends StatelessWidget { Expanded( child: ListView.builder( itemCount: serversProvider.filtering.data!.filters.length, - itemBuilder: (context, index) => CustomListTile( - title: serversProvider.filtering.data!.filters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - serversProvider.filtering.data!.filters[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: serversProvider.filtering.data!.filters[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red + itemBuilder: (context, index) => ListOptionsMenu( + list: serversProvider.filtering.data!.filters[index], + listType: 'blacklist', + child: CustomListTile( + title: serversProvider.filtering.data!.filters[index].name, + subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + serversProvider.filtering.data!.filters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: serversProvider.filtering.data!.filters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), ), ), ) @@ -230,7 +243,8 @@ class FiltersTripleColumn extends StatelessWidget { type: '', widget: (fn) => IconButton( onPressed: fn, - icon: const Icon(Icons.add_rounded) + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addCustomRule, ) ) ], diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 92ae4e0..0117390 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -9,25 +9,23 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; +import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; +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'; import 'package:adguard_home_manager/models/filtering.dart'; class ListDetailsScreen extends StatefulWidget { - final Filter list; + final int listId; final String type; final bool dialog; const ListDetailsScreen({ Key? key, - required this.list, + required this.listId, required this.type, required this.dialog }) : super(key: key); @@ -38,15 +36,10 @@ class ListDetailsScreen extends StatefulWidget { class _ListDetailsScreenState extends State { final ScrollController scrollController = ScrollController(); - String name = ""; - bool enabled = true; bool fabVisible = true; @override void initState() { - name = widget.list.name; - enabled = widget.list.enabled; - scrollController.addListener(() { if (scrollController.position.userScrollDirection == ScrollDirection.reverse) { if (mounted && fabVisible == true) { @@ -72,152 +65,15 @@ class _ListDetailsScreenState extends State { final width = MediaQuery.of(context).size.width; - void enableDisableList(Filter list, bool newStatus) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open( - enabled == true - ? AppLocalizations.of(context)!.disablingList - : AppLocalizations.of(context)!.enablingList, - ); - - final result = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": newStatus, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": widget.type == 'whitelist' ? true : false - }); - - processModal.close(); - - if (result['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - setState(() => enabled = newStatus); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - appConfigProvider.addLog(result['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - } - - void confirmEditList({required Filter list, required String type}) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingListData); - - final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": list.enabled, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - processModal.close(); - - setState(() => name = list.name); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - } - - void deleteList(Filter list, String type) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.deletingList); - - final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: { - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); - } - - processModal.close(); - - Navigator.pop(context); // Closes the screen - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDeleted, - color: Colors.green - ); - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listNotDeleted, - color: Colors.red - ); - } + Filter? list; + try { + list = serversProvider.filtering.data != null + ? widget.type == 'whitelist' + ? serversProvider.filtering.data!.whitelistFilters.firstWhere((l) => l.id == widget.listId) + : serversProvider.filtering.data!.filters.firstWhere((l) => l.id == widget.listId) + : null; + } catch (e) { + // ------- // } List content() { @@ -226,11 +82,11 @@ class _ListDetailsScreenState extends State { icon: Icons.shield_rounded, title: AppLocalizations.of(context)!.currentStatus, subtitleWidget: Text( - enabled == true + list!.enabled == true ? AppLocalizations.of(context)!.enabled : AppLocalizations.of(context)!.disabled, style: TextStyle( - color: enabled == true + color: list.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -250,7 +106,7 @@ class _ListDetailsScreenState extends State { CustomListTile( icon: Icons.badge_rounded, title: AppLocalizations.of(context)!.name, - subtitle: name, + subtitle: list.name, padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -261,7 +117,7 @@ class _ListDetailsScreenState extends State { CustomListTile( icon: Icons.link_rounded, title: "URL", - subtitle: widget.list.url, + subtitle: list.url, padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -272,7 +128,7 @@ class _ListDetailsScreenState extends State { CustomListTile( icon: Icons.list_rounded, title: AppLocalizations.of(context)!.rules, - subtitle: widget.list.rulesCount.toString(), + subtitle: list.rulesCount.toString(), padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -293,10 +149,10 @@ class _ListDetailsScreenState extends State { ) : null, ), - if (widget.list.lastUpdated != null) CustomListTile( + if (list.lastUpdated != null) CustomListTile( icon: Icons.schedule_rounded, title: AppLocalizations.of(context)!.latestUpdate, - subtitle: convertTimestampLocalTimezone(widget.list.lastUpdated!, 'dd-MM-yyyy HH:mm'), + subtitle: convertTimestampLocalTimezone(list.lastUpdated!, 'dd-MM-yyyy HH:mm'), padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -316,9 +172,31 @@ class _ListDetailsScreenState extends State { showDialog( context: context, builder: (ctx) => AddListModal( - list: widget.list, + list: list, type: widget.type, - onEdit: confirmEditList, + onEdit: ({required Filter list, required String type}) async { + final result = await editList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list, + type: widget.type + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, dialog: true, ), ) @@ -327,9 +205,31 @@ class _ListDetailsScreenState extends State { showModalBottomSheet( context: context, builder: (ctx) => AddListModal( - list: widget.list, + list: list, type: widget.type, - onEdit: confirmEditList, + onEdit: ({required Filter list, required String type}) async { + final result = await editList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list, + type: widget.type + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, dialog: false, ), isScrollControlled: true, @@ -344,8 +244,31 @@ class _ListDetailsScreenState extends State { onPressed: () { showDialog( context: context, - builder: (context) => DeleteListModal( - onConfirm: () => deleteList(widget.list, widget.type), + builder: (c) => DeleteListModal( + onConfirm: () async { + final result = await deleteList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list!, + type: widget.type, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDeleted, + color: Colors.green + ); + Navigator.pop(context); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listNotDeleted, + color: Colors.red + ); + } + } ) ); }, @@ -386,16 +309,38 @@ class _ListDetailsScreenState extends State { ) ], ), - Row( + if (list != null) Row( children: [ IconButton( - onPressed: () => enableDisableList(widget.list, !enabled), + onPressed: () async { + final result = await enableDisableList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list!, + listType: widget.type, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, icon: Icon( - enabled == true + list.enabled == true ? Icons.gpp_bad_rounded : Icons.verified_user_rounded, ), - tooltip: enabled == true + tooltip: list.enabled == true ? AppLocalizations.of(context)!.disableList : AppLocalizations.of(context)!.enableList, ), @@ -406,11 +351,20 @@ class _ListDetailsScreenState extends State { ), ), Flexible( - child: SingleChildScrollView( - child: Wrap( - children: content(), - ), - ) + child: list != null + ? SingleChildScrollView( + child: Wrap( + children: content(), + ), + ) + : Center( + child: Text( + AppLocalizations.of(context)!.listNotAvailable, + style: const TextStyle( + fontSize: 24, + ), + ), + ), ) ], ), @@ -421,14 +375,22 @@ class _ListDetailsScreenState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.listDetails), - actions: actions(), + actions: list != null ? actions() : null, ), body: Stack( children: [ - ListView( + if (list != null) ListView( children: content(), ), - AnimatedPositioned( + if (list == null) Center( + child: Text( + AppLocalizations.of(context)!.listNotAvailable, + style: const TextStyle( + fontSize: 24, + ), + ), + ), + if (list != null) AnimatedPositioned( duration: const Duration(milliseconds: 100), curve: Curves.easeInOut, bottom: fabVisible ? @@ -437,9 +399,31 @@ class _ListDetailsScreenState extends State { : -70, right: 20, child: FloatingActionButton( - onPressed: () => enableDisableList(widget.list, !enabled), + onPressed: () async { + final result = await enableDisableList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list!, + listType: widget.type, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, child: Icon( - enabled == true + list.enabled == true ? Icons.gpp_bad_rounded : Icons.verified_user_rounded, ), diff --git a/lib/screens/filters/list_functions.dart b/lib/screens/filters/list_functions.dart new file mode 100644 index 0000000..7db194f --- /dev/null +++ b/lib/screens/filters/list_functions.dart @@ -0,0 +1,141 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +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'; + +Future enableDisableList({ + required BuildContext context, + required ServersProvider serversProvider, + required AppConfigProvider appConfigProvider, + required Filter list, + required String listType, +}) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open( + list.enabled == true + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList, + ); + + final result = await updateFilterList(server: serversProvider.selectedServer!, data: { + "data": { + "enabled": !list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": listType == 'whitelist' ? true : false + }); + + processModal.close(); + + if (result['result'] == 'success') { + final result2 = await getFiltering(server: serversProvider.selectedServer!); + + if (result2['result'] == 'success') { + serversProvider.setFilteringData(result2['data']); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + } + else { + appConfigProvider.addLog(result2['log']); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + } + + return true; + } + else { + appConfigProvider.addLog(result['log']); + + return false; + } +} + +Future editList({ + required BuildContext context, + required ServersProvider serversProvider, + required AppConfigProvider appConfigProvider, + required Filter list, + required String type +}) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingListData); + + final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: { + "data": { + "enabled": list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": type == 'whitelist' ? true : false + }); + + if (result1['result'] == 'success') { + final result2 = await getFiltering(server: serversProvider.selectedServer!); + + if (result2['result'] == 'success') { + serversProvider.setFilteringData(result2['data']); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + } + else { + appConfigProvider.addLog(result2['log']); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + } + + processModal.close(); + + return true; + } + else { + processModal.close(); + appConfigProvider.addLog(result1['log']); + + return false; + } +} + +Future deleteList({ + required BuildContext context, + required ServersProvider serversProvider, + required AppConfigProvider appConfigProvider, + required Filter list, + required String type +}) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.deletingList); + + final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: { + "url": list.url, + "whitelist": type == 'whitelist' ? true : false + }); + + if (result1['result'] == 'success') { + final result2 = await getFiltering(server: serversProvider.selectedServer!); + + if (result2['result'] == 'success') { + serversProvider.setFilteringData(result2['data']); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + } + else { + appConfigProvider.addLog(result2['log']); + serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); + } + + processModal.close(); + + return true; + } + else { + processModal.close(); + appConfigProvider.addLog(result1['log']); + + return false; + } +} \ No newline at end of file diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart new file mode 100644 index 0000000..f052890 --- /dev/null +++ b/lib/screens/filters/list_options_menu.dart @@ -0,0 +1,120 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:contextmenu/contextmenu.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/filters/list_functions.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/options_modal.dart'; + +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.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/providers/servers_provider.dart'; + +class ListOptionsMenu extends StatelessWidget { + final Filter list; + final Widget child; + final String listType; + + const ListOptionsMenu({ + Key? key, + required this.list, + required this.child, + required this.listType, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void enableDisable() async { + final result = await enableDisableList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list, + listType: listType, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + } + + return ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: list.enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + icon: list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + onTap: () { + Navigator.pop(context); // Closes the context menu + enableDisable(); + } + ), + CustomListTile( + title: AppLocalizations.of(context)!.copyListUrl, + icon: Icons.copy_rounded, + onTap: () { + Navigator.pop(context); // Closes the context menu + copyToClipboard( + context: context, + value: list.url, + successMessage: AppLocalizations.of(context)!.listUrlCopied + ); + } + ), + ], + child: Material( + color: Colors.transparent, + child: InkWell( + onLongPress: () => showDialog( + context: context, + builder: (context) => OptionsModal( + options: [ + MenuOption( + title: list.enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + icon: list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + action: enableDisable + ), + MenuOption( + title: AppLocalizations.of(context)!.copyListUrl, + icon: Icons.copy_rounded, + action: () => copyToClipboard( + context: context, + value: list.url, + successMessage: AppLocalizations.of(context)!.listUrlCopied + ) + ), + ] + ) + ), + child: child + ), + ), + ); + } +} \ No newline at end of file