mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-06-08 15:47:47 +00:00
Added option to block and unblock clients from home screen
This commit is contained in:
parent
71b870b42f
commit
569ab7d569
16 changed files with 139 additions and 53 deletions
|
@ -715,5 +715,8 @@
|
||||||
"blockedResponseTtlDescription": "Specifies for how many seconds the clients should cache a filtered response",
|
"blockedResponseTtlDescription": "Specifies for how many seconds the clients should cache a filtered response",
|
||||||
"invalidValue": "Invalid value",
|
"invalidValue": "Invalid value",
|
||||||
"noDataChart": "There's no data to display this chart.",
|
"noDataChart": "There's no data to display this chart.",
|
||||||
"noData": "No data"
|
"noData": "No data",
|
||||||
|
"unblockClient": "Unblock client",
|
||||||
|
"blockingClient": "Blocking client...",
|
||||||
|
"unblockingClient": "Unblocking client..."
|
||||||
}
|
}
|
|
@ -715,5 +715,8 @@
|
||||||
"blockedResponseTtlDescription": "Especifica durante cuántos segundos los clientes deben almacenar en cache una respuesta filtrada",
|
"blockedResponseTtlDescription": "Especifica durante cuántos segundos los clientes deben almacenar en cache una respuesta filtrada",
|
||||||
"invalidValue": "Valor no válido",
|
"invalidValue": "Valor no válido",
|
||||||
"noDataChart": "No hay datos para mostrar este gráfico.",
|
"noDataChart": "No hay datos para mostrar este gráfico.",
|
||||||
"noData": "No hay datos"
|
"noData": "No hay datos",
|
||||||
|
"unblockClient": "Desbloquear cliente",
|
||||||
|
"blockingClient": "Bloqueando cliente...",
|
||||||
|
"unblockingClient": "Desbloqueando cliente..."
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
class MenuOption {
|
class MenuOption {
|
||||||
final IconData? icon;
|
final IconData? icon;
|
||||||
final String title;
|
final String title;
|
||||||
final void Function(dynamic) action;
|
final void Function() action;
|
||||||
final bool? disabled;
|
final bool? disabled;
|
||||||
|
|
||||||
const MenuOption({
|
const MenuOption({
|
||||||
|
|
|
@ -190,6 +190,16 @@ class ClientsProvider with ChangeNotifier {
|
||||||
"blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [],
|
"blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (body['allowed_clients']!.contains(item)) {
|
||||||
|
body['allowed_clients'] = body['allowed_clients']!.where((e) => e != item).toList();
|
||||||
|
}
|
||||||
|
else if (body['disallowed_clients']!.contains(item)) {
|
||||||
|
body['disallowed_clients'] = body['disallowed_clients']!.where((e) => e != item).toList();
|
||||||
|
}
|
||||||
|
else if (body['blocked_hosts']!.contains(item)) {
|
||||||
|
body['blocked_hosts'] = body['blocked_hosts']!.where((e) => e != item).toList();
|
||||||
|
}
|
||||||
|
|
||||||
if (type == AccessSettingsList.allowed) {
|
if (type == AccessSettingsList.allowed) {
|
||||||
body['allowed_clients']!.add(item);
|
body['allowed_clients']!.add(item);
|
||||||
}
|
}
|
||||||
|
@ -223,6 +233,18 @@ class ClientsProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AccessSettingsList? checkClientList(String client) {
|
||||||
|
if (_clients!.clientsAllowedBlocked!.allowedClients.contains(client)) {
|
||||||
|
return AccessSettingsList.allowed;
|
||||||
|
}
|
||||||
|
else if (_clients!.clientsAllowedBlocked!.disallowedClients.contains(client)) {
|
||||||
|
return AccessSettingsList.disallowed;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<ApiResponse> removeClientList(String client, AccessSettingsList type) async {
|
Future<ApiResponse> removeClientList(String client, AccessSettingsList type) async {
|
||||||
Map<String, List<String>> body = {
|
Map<String, List<String>> body = {
|
||||||
"allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [],
|
"allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [],
|
||||||
|
|
|
@ -28,11 +28,11 @@ class ActiveClientTile extends StatelessWidget {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: OptionsMenu(
|
child: OptionsMenu(
|
||||||
options: [
|
options: (_) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: client.name != ''
|
value: client.name != ''
|
||||||
? client.name!
|
? client.name!
|
||||||
: client.ip,
|
: client.ip,
|
||||||
|
@ -99,11 +99,11 @@ class ActiveClientTile extends StatelessWidget {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return OptionsMenu(
|
return OptionsMenu(
|
||||||
options: [
|
options: (_) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: client.name != ''
|
value: client.name != ''
|
||||||
? client.name!
|
? client.name!
|
||||||
: client.ip,
|
: client.ip,
|
||||||
|
|
|
@ -46,11 +46,11 @@ class _AddedClientTileState extends State<AddedClientTile> {
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(28),
|
borderRadius: BorderRadius.circular(28),
|
||||||
child: OptionsMenu(
|
child: OptionsMenu(
|
||||||
options: [
|
options: (_) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''),
|
value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''),
|
||||||
successMessage: AppLocalizations.of(context)!.copiedClipboard,
|
successMessage: AppLocalizations.of(context)!.copiedClipboard,
|
||||||
)
|
)
|
||||||
|
@ -164,16 +164,16 @@ class _AddedClientTileState extends State<AddedClientTile> {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return OptionsMenu(
|
return OptionsMenu(
|
||||||
options: [
|
options: (_) => [
|
||||||
if (widget.onEdit != null) MenuOption(
|
if (widget.onEdit != null) MenuOption(
|
||||||
title: AppLocalizations.of(context)!.seeDetails,
|
title: AppLocalizations.of(context)!.seeDetails,
|
||||||
icon: Icons.file_open_rounded,
|
icon: Icons.file_open_rounded,
|
||||||
action: (_) => widget.onEdit!(widget.client)
|
action: () => widget.onEdit!(widget.client)
|
||||||
),
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''),
|
value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''),
|
||||||
successMessage: AppLocalizations.of(context)!.copiedClipboard,
|
successMessage: AppLocalizations.of(context)!.copiedClipboard,
|
||||||
)
|
)
|
||||||
|
|
|
@ -226,16 +226,16 @@ class _SearchClientsState extends State<SearchClients> {
|
||||||
itemCount: clientsScreen.length,
|
itemCount: clientsScreen.length,
|
||||||
padding: const EdgeInsets.only(bottom: 0),
|
padding: const EdgeInsets.only(bottom: 0),
|
||||||
itemBuilder: (context, index) => OptionsMenu(
|
itemBuilder: (context, index) => OptionsMenu(
|
||||||
options: [
|
options: (v) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
icon: Icons.edit_rounded,
|
icon: Icons.edit_rounded,
|
||||||
title: AppLocalizations.of(context)!.edit,
|
title: AppLocalizations.of(context)!.edit,
|
||||||
action: (v) => openClientModal(v)
|
action: () => openClientModal(v)
|
||||||
),
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
icon: Icons.delete_rounded,
|
icon: Icons.delete_rounded,
|
||||||
title: AppLocalizations.of(context)!.delete,
|
title: AppLocalizations.of(context)!.delete,
|
||||||
action: (v) => openDeleteModal(v)
|
action: () => openDeleteModal(v)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
value: clientsScreen[index],
|
value: clientsScreen[index],
|
||||||
|
|
|
@ -283,11 +283,11 @@ class FiltersTripleColumn extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: OptionsMenu(
|
child: OptionsMenu(
|
||||||
options: [
|
options: (_) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: filteringProvider.filtering!.userRules[index],
|
value: filteringProvider.filtering!.userRules[index],
|
||||||
successMessage: AppLocalizations.of(context)!.copiedClipboard,
|
successMessage: AppLocalizations.of(context)!.copiedClipboard,
|
||||||
)
|
)
|
||||||
|
|
|
@ -146,7 +146,7 @@ class ListOptionsMenu extends StatelessWidget {
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
child: OptionsMenu(
|
child: OptionsMenu(
|
||||||
options: [
|
options: (_) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: list.enabled == true
|
title: list.enabled == true
|
||||||
? AppLocalizations.of(context)!.disable
|
? AppLocalizations.of(context)!.disable
|
||||||
|
@ -154,12 +154,12 @@ class ListOptionsMenu extends StatelessWidget {
|
||||||
icon: list.enabled == true
|
icon: list.enabled == true
|
||||||
? Icons.gpp_bad_rounded
|
? Icons.gpp_bad_rounded
|
||||||
: Icons.verified_user_rounded,
|
: Icons.verified_user_rounded,
|
||||||
action: (_) => enableDisable()
|
action: () => enableDisable()
|
||||||
),
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyListUrl,
|
title: AppLocalizations.of(context)!.copyListUrl,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: list.url,
|
value: list.url,
|
||||||
successMessage: AppLocalizations.of(context)!.listUrlCopied
|
successMessage: AppLocalizations.of(context)!.listUrlCopied
|
||||||
)
|
)
|
||||||
|
@ -167,12 +167,12 @@ class ListOptionsMenu extends StatelessWidget {
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.openListUrl,
|
title: AppLocalizations.of(context)!.openListUrl,
|
||||||
icon: Icons.open_in_browser_rounded,
|
icon: Icons.open_in_browser_rounded,
|
||||||
action: (_) => openUrl(list.url)
|
action: () => openUrl(list.url)
|
||||||
),
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.selectionMode,
|
title: AppLocalizations.of(context)!.selectionMode,
|
||||||
icon: Icons.check_rounded,
|
icon: Icons.check_rounded,
|
||||||
action: (_) => Future.delayed(
|
action: () => Future.delayed(
|
||||||
const Duration(milliseconds: 0),
|
const Duration(milliseconds: 0),
|
||||||
() => openSelectionMode()
|
() => openSelectionMode()
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'package:adguard_home_manager/screens/home/appbar.dart';
|
||||||
import 'package:adguard_home_manager/screens/home/fab.dart';
|
import 'package:adguard_home_manager/screens/home/fab.dart';
|
||||||
import 'package:adguard_home_manager/screens/home/chart.dart';
|
import 'package:adguard_home_manager/screens/home/chart.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/providers/clients_provider.dart';
|
||||||
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
||||||
import 'package:adguard_home_manager/functions/number_format.dart';
|
import 'package:adguard_home_manager/functions/number_format.dart';
|
||||||
import 'package:adguard_home_manager/constants/enums.dart';
|
import 'package:adguard_home_manager/constants/enums.dart';
|
||||||
|
@ -39,6 +40,9 @@ class _HomeState extends State<Home> {
|
||||||
withLoadingIndicator: statusProvider.serverStatus != null ? false : true
|
withLoadingIndicator: statusProvider.serverStatus != null ? false : true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final clientsProvider = Provider.of<ClientsProvider>(context, listen: false);
|
||||||
|
clientsProvider.fetchClients(updateLoading: false);
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
isVisible = true;
|
isVisible = true;
|
||||||
|
|
|
@ -16,7 +16,7 @@ class RowItem extends StatefulWidget {
|
||||||
final bool clients;
|
final bool clients;
|
||||||
final bool showColor;
|
final bool showColor;
|
||||||
final String? unit;
|
final String? unit;
|
||||||
final List<MenuOption> options;
|
final List<MenuOption> Function(dynamic) options;
|
||||||
final void Function(dynamic)? onTapEntry;
|
final void Function(dynamic)? onTapEntry;
|
||||||
|
|
||||||
const RowItem({
|
const RowItem({
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
import 'package:adguard_home_manager/screens/home/top_items/top_items_section.dart';
|
import 'package:adguard_home_manager/screens/home/top_items/top_items_section.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/providers/clients_provider.dart';
|
||||||
import 'package:adguard_home_manager/functions/number_format.dart';
|
import 'package:adguard_home_manager/functions/number_format.dart';
|
||||||
import 'package:adguard_home_manager/functions/snackbar.dart';
|
import 'package:adguard_home_manager/functions/snackbar.dart';
|
||||||
import 'package:adguard_home_manager/classes/process_modal.dart';
|
import 'package:adguard_home_manager/classes/process_modal.dart';
|
||||||
|
@ -30,6 +31,7 @@ class TopItemsLists extends StatelessWidget {
|
||||||
final statusProvider = Provider.of<StatusProvider>(context);
|
final statusProvider = Provider.of<StatusProvider>(context);
|
||||||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||||
final logsProvider = Provider.of<LogsProvider>(context);
|
final logsProvider = Provider.of<LogsProvider>(context);
|
||||||
|
final clientsProvider = Provider.of<ClientsProvider>(context);
|
||||||
|
|
||||||
List<Widget> bottom = [
|
List<Widget> bottom = [
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -96,10 +98,53 @@ class TopItemsLists extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyValueClipboard(value) {
|
void copyValueClipboard(dynamic value) {
|
||||||
copyToClipboard(value: value, successMessage: AppLocalizations.of(context)!.copiedClipboard);
|
copyToClipboard(value: value, successMessage: AppLocalizations.of(context)!.copiedClipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void blockUnblockClient(dynamic client) async {
|
||||||
|
final currentList = clientsProvider.checkClientList(client);
|
||||||
|
final newList = currentList == AccessSettingsList.allowed || currentList == null
|
||||||
|
? AccessSettingsList.disallowed
|
||||||
|
: AccessSettingsList.allowed;
|
||||||
|
|
||||||
|
ProcessModal processModal = ProcessModal();
|
||||||
|
processModal.open(
|
||||||
|
currentList == AccessSettingsList.allowed || currentList == null
|
||||||
|
? AppLocalizations.of(context)!.blockingClient
|
||||||
|
: AppLocalizations.of(context)!.unblockingClient
|
||||||
|
);
|
||||||
|
|
||||||
|
final result = await clientsProvider.addClientList(client, newList);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
processModal.close();
|
||||||
|
|
||||||
|
if (result.successful == true) {
|
||||||
|
showSnacbkar(
|
||||||
|
appConfigProvider: appConfigProvider,
|
||||||
|
label: AppLocalizations.of(context)!.clientAddedSuccessfully,
|
||||||
|
color: Colors.green
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (result.successful == false && result.content == 'client_another_list') {
|
||||||
|
showSnacbkar(
|
||||||
|
appConfigProvider: appConfigProvider,
|
||||||
|
label: AppLocalizations.of(context)!.clientAnotherList,
|
||||||
|
color: Colors.red
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showSnacbkar(
|
||||||
|
appConfigProvider: appConfigProvider,
|
||||||
|
label: newList == AccessSettingsList.allowed || newList == AccessSettingsList.disallowed
|
||||||
|
? AppLocalizations.of(context)!.clientNotRemoved
|
||||||
|
: AppLocalizations.of(context)!.domainNotAdded,
|
||||||
|
color: Colors.red
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: order.asMap().entries.map((item) {
|
children: order.asMap().entries.map((item) {
|
||||||
switch (item.value) {
|
switch (item.value) {
|
||||||
|
@ -113,16 +158,16 @@ class TopItemsLists extends StatelessWidget {
|
||||||
withChart: true,
|
withChart: true,
|
||||||
withProgressBar: true,
|
withProgressBar: true,
|
||||||
buildValue: (v) => v.toString(),
|
buildValue: (v) => v.toString(),
|
||||||
menuOptions: [
|
menuOptions: (v) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.blockDomain,
|
title: AppLocalizations.of(context)!.blockDomain,
|
||||||
icon: Icons.block_rounded,
|
icon: Icons.block_rounded,
|
||||||
action: (v) => blockUnblock(domain: v.toString(), newStatus: 'block')
|
action: () => blockUnblock(domain: v.toString(), newStatus: 'block')
|
||||||
),
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: copyValueClipboard
|
action: () => copyValueClipboard(v)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
onTapEntry: (v) => filterDomainLogs(value: v.toString()),
|
onTapEntry: (v) => filterDomainLogs(value: v.toString()),
|
||||||
|
@ -141,16 +186,16 @@ class TopItemsLists extends StatelessWidget {
|
||||||
withChart: true,
|
withChart: true,
|
||||||
withProgressBar: true,
|
withProgressBar: true,
|
||||||
buildValue: (v) => v.toString(),
|
buildValue: (v) => v.toString(),
|
||||||
menuOptions: [
|
menuOptions: (v) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.unblockDomain,
|
title: AppLocalizations.of(context)!.unblockDomain,
|
||||||
icon: Icons.check_rounded,
|
icon: Icons.check_rounded,
|
||||||
action: (v) => blockUnblock(domain: v, newStatus: 'unblock')
|
action: () => blockUnblock(domain: v, newStatus: 'unblock')
|
||||||
),
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: copyValueClipboard
|
action: () => copyValueClipboard(v)
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
onTapEntry: (v) => filterDomainLogs(value: v),
|
onTapEntry: (v) => filterDomainLogs(value: v),
|
||||||
|
@ -169,12 +214,21 @@ class TopItemsLists extends StatelessWidget {
|
||||||
withChart: true,
|
withChart: true,
|
||||||
withProgressBar: true,
|
withProgressBar: true,
|
||||||
buildValue: (v) => v.toString(),
|
buildValue: (v) => v.toString(),
|
||||||
menuOptions: [
|
menuOptions: (v) => [
|
||||||
|
if (clientsProvider.clients?.clientsAllowedBlocked != null) MenuOption(
|
||||||
|
title: clientsProvider.checkClientList(v) == AccessSettingsList.allowed || clientsProvider.checkClientList(v) == null
|
||||||
|
? AppLocalizations.of(context)!.blockClient
|
||||||
|
: AppLocalizations.of(context)!.unblockClient,
|
||||||
|
icon: clientsProvider.checkClientList(v) == AccessSettingsList.allowed || clientsProvider.checkClientList(v) == null
|
||||||
|
? Icons.block_rounded
|
||||||
|
: Icons.check_rounded,
|
||||||
|
action: () => blockUnblockClient(v)
|
||||||
|
),
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: copyValueClipboard
|
action: () => copyValueClipboard(v)
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
onTapEntry: (v) => filterClientLogs(value: v),
|
onTapEntry: (v) => filterClientLogs(value: v),
|
||||||
),
|
),
|
||||||
|
@ -193,11 +247,11 @@ class TopItemsLists extends StatelessWidget {
|
||||||
withChart: true,
|
withChart: true,
|
||||||
withProgressBar: true,
|
withProgressBar: true,
|
||||||
buildValue: (v) => v.toString(),
|
buildValue: (v) => v.toString(),
|
||||||
menuOptions: [
|
menuOptions: (v) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: copyValueClipboard
|
action: () => copyValueClipboard(v)
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -217,11 +271,11 @@ class TopItemsLists extends StatelessWidget {
|
||||||
withChart: false,
|
withChart: false,
|
||||||
withProgressBar: false,
|
withProgressBar: false,
|
||||||
buildValue: (v) => "${doubleFormat(v*1000, Platform.localeName)} ms",
|
buildValue: (v) => "${doubleFormat(v*1000, Platform.localeName)} ms",
|
||||||
menuOptions: [
|
menuOptions: (v) => [
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: copyValueClipboard
|
action: () => copyValueClipboard(v)
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -24,7 +24,7 @@ class TopItemsScreen extends StatefulWidget {
|
||||||
final List<Map<String, dynamic>> data;
|
final List<Map<String, dynamic>> data;
|
||||||
final bool withProgressBar;
|
final bool withProgressBar;
|
||||||
final String Function(dynamic) buildValue;
|
final String Function(dynamic) buildValue;
|
||||||
final List<MenuOption> options;
|
final List<MenuOption> Function(dynamic) options;
|
||||||
final void Function(dynamic)? onTapEntry;
|
final void Function(dynamic)? onTapEntry;
|
||||||
final bool isFullscreen;
|
final bool isFullscreen;
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ class _TopItemsScreenState extends State<TopItemsScreen> {
|
||||||
class _Content extends StatelessWidget {
|
class _Content extends StatelessWidget {
|
||||||
final List<Map<String, dynamic>> screenData;
|
final List<Map<String, dynamic>> screenData;
|
||||||
final bool? isClient;
|
final bool? isClient;
|
||||||
final List<MenuOption> options;
|
final List<MenuOption> Function(dynamic) options;
|
||||||
final bool withProgressBar;
|
final bool withProgressBar;
|
||||||
final void Function(dynamic)? onTapEntry;
|
final void Function(dynamic)? onTapEntry;
|
||||||
final String Function(dynamic) buildValue;
|
final String Function(dynamic) buildValue;
|
||||||
|
|
|
@ -21,7 +21,7 @@ class TopItemsSection extends StatefulWidget {
|
||||||
final bool withChart;
|
final bool withChart;
|
||||||
final bool withProgressBar;
|
final bool withProgressBar;
|
||||||
final String Function(dynamic) buildValue;
|
final String Function(dynamic) buildValue;
|
||||||
final List<MenuOption> menuOptions;
|
final List<MenuOption> Function(dynamic) menuOptions;
|
||||||
final void Function(dynamic)? onTapEntry;
|
final void Function(dynamic)? onTapEntry;
|
||||||
|
|
||||||
const TopItemsSection({
|
const TopItemsSection({
|
||||||
|
@ -350,7 +350,7 @@ class _ItemsList extends StatelessWidget {
|
||||||
final HomeTopItems type;
|
final HomeTopItems type;
|
||||||
final bool showChart;
|
final bool showChart;
|
||||||
final String Function(dynamic) buildValue;
|
final String Function(dynamic) buildValue;
|
||||||
final List<MenuOption> menuOptions;
|
final List<MenuOption> Function(dynamic) menuOptions;
|
||||||
final void Function(dynamic)? onTapEntry;
|
final void Function(dynamic)? onTapEntry;
|
||||||
|
|
||||||
const _ItemsList({
|
const _ItemsList({
|
||||||
|
|
|
@ -128,7 +128,7 @@ class LogTile extends StatelessWidget {
|
||||||
child: OptionsMenu(
|
child: OptionsMenu(
|
||||||
onTap: (_) => onLogTap(log),
|
onTap: (_) => onLogTap(log),
|
||||||
borderRadius: BorderRadius.circular(28),
|
borderRadius: BorderRadius.circular(28),
|
||||||
options: [
|
options: (v) => [
|
||||||
if (log.question.name != null) MenuOption(
|
if (log.question.name != null) MenuOption(
|
||||||
title: domainBlocked == true
|
title: domainBlocked == true
|
||||||
? AppLocalizations.of(context)!.unblockDomain
|
? AppLocalizations.of(context)!.unblockDomain
|
||||||
|
@ -136,7 +136,7 @@ class LogTile extends StatelessWidget {
|
||||||
icon: domainBlocked == true
|
icon: domainBlocked == true
|
||||||
? Icons.check_rounded
|
? Icons.check_rounded
|
||||||
: Icons.block_rounded,
|
: Icons.block_rounded,
|
||||||
action: (_) => blockUnblock(
|
action: () => blockUnblock(
|
||||||
domain: log.question.name!,
|
domain: log.question.name!,
|
||||||
newStatus: domainBlocked == true ? 'unblock' : 'block'
|
newStatus: domainBlocked == true ? 'unblock' : 'block'
|
||||||
)
|
)
|
||||||
|
@ -144,7 +144,7 @@ class LogTile extends StatelessWidget {
|
||||||
MenuOption(
|
MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: (v) => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard)
|
action: () => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard)
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -306,7 +306,7 @@ class LogTile extends StatelessWidget {
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: OptionsMenu(
|
child: OptionsMenu(
|
||||||
onTap: (_) => onLogTap(log),
|
onTap: (_) => onLogTap(log),
|
||||||
options: [
|
options: (_) => [
|
||||||
if (log.question.name != null) MenuOption(
|
if (log.question.name != null) MenuOption(
|
||||||
title: domainBlocked == true
|
title: domainBlocked == true
|
||||||
? AppLocalizations.of(context)!.unblockDomain
|
? AppLocalizations.of(context)!.unblockDomain
|
||||||
|
@ -314,7 +314,7 @@ class LogTile extends StatelessWidget {
|
||||||
icon: domainBlocked == true
|
icon: domainBlocked == true
|
||||||
? Icons.check_rounded
|
? Icons.check_rounded
|
||||||
: Icons.block_rounded,
|
: Icons.block_rounded,
|
||||||
action: (_) => blockUnblock(
|
action: () => blockUnblock(
|
||||||
domain: log.question.name!,
|
domain: log.question.name!,
|
||||||
newStatus: domainBlocked == true ? 'unblock' : 'block'
|
newStatus: domainBlocked == true ? 'unblock' : 'block'
|
||||||
)
|
)
|
||||||
|
@ -322,7 +322,7 @@ class LogTile extends StatelessWidget {
|
||||||
if (log.question.name != null) MenuOption(
|
if (log.question.name != null) MenuOption(
|
||||||
title: AppLocalizations.of(context)!.copyClipboard,
|
title: AppLocalizations.of(context)!.copyClipboard,
|
||||||
icon: Icons.copy_rounded,
|
icon: Icons.copy_rounded,
|
||||||
action: (_) => copyToClipboard(
|
action: () => copyToClipboard(
|
||||||
value: log.question.name!,
|
value: log.question.name!,
|
||||||
successMessage: AppLocalizations.of(context)!.copiedClipboard
|
successMessage: AppLocalizations.of(context)!.copiedClipboard
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import 'package:adguard_home_manager/models/menu_option.dart';
|
||||||
|
|
||||||
class OptionsMenu extends StatelessWidget {
|
class OptionsMenu extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final List<MenuOption> options;
|
final List<MenuOption> Function(dynamic) options;
|
||||||
final dynamic value;
|
final dynamic value;
|
||||||
final BorderRadius? borderRadius;
|
final BorderRadius? borderRadius;
|
||||||
final void Function(dynamic)? onTap;
|
final void Function(dynamic)? onTap;
|
||||||
|
@ -40,11 +40,11 @@ class OptionsMenu extends StatelessWidget {
|
||||||
return Material(
|
return Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: ContextMenuArea(
|
child: ContextMenuArea(
|
||||||
builder: (context) => options.map((opt) => CustomListTile(
|
builder: (context) => options(value).map((opt) => CustomListTile(
|
||||||
title: opt.title,
|
title: opt.title,
|
||||||
icon: opt.icon,
|
icon: opt.icon,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
opt.action(value);
|
opt.action();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
)).toList(),
|
)).toList(),
|
||||||
|
@ -64,7 +64,7 @@ class OptionsMenu extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OptionsModal extends StatelessWidget {
|
class _OptionsModal extends StatelessWidget {
|
||||||
final List<MenuOption> options;
|
final List<MenuOption> Function(dynamic) options;
|
||||||
final dynamic value;
|
final dynamic value;
|
||||||
|
|
||||||
const _OptionsModal({
|
const _OptionsModal({
|
||||||
|
@ -98,12 +98,12 @@ class _OptionsModal extends StatelessWidget {
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: options.map((opt) => CustomListTileDialog(
|
children: options(value).map((opt) => CustomListTileDialog(
|
||||||
title: opt.title,
|
title: opt.title,
|
||||||
icon: opt.icon,
|
icon: opt.icon,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
opt.action(value);
|
opt.action();
|
||||||
},
|
},
|
||||||
)).toList()
|
)).toList()
|
||||||
),
|
),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue