mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-05-04 20:30:35 +00:00
Adapted home screen
This commit is contained in:
parent
4531e15566
commit
aacf68569d
10 changed files with 612 additions and 162 deletions
|
@ -45,10 +45,10 @@
|
|||
"save": "Save",
|
||||
"serverStatus": "Server status",
|
||||
"connectionNotUpdated": "Connection not updated",
|
||||
"ruleFilteringWidget": "Rule\nfiltering",
|
||||
"safeBrowsingWidget": "Safe\nbrowsing",
|
||||
"parentalFilteringWidget": "Parental\nfiltering",
|
||||
"safeSearchWidget": "Safe\nsearch",
|
||||
"ruleFilteringWidget": "Rule filtering",
|
||||
"safeBrowsingWidget": "Safe browsing",
|
||||
"parentalFilteringWidget": "Parental filtering",
|
||||
"safeSearchWidget": "Safe search",
|
||||
"ruleFiltering": "Rule filtering",
|
||||
"safeBrowsing": "Safe browsing",
|
||||
"parentalFiltering": "Parental filtering",
|
||||
|
|
|
@ -45,10 +45,10 @@
|
|||
"save": "Guardar",
|
||||
"connectionNotUpdated": "Conexión no actualizada",
|
||||
"serverStatus": "Estado del servidor",
|
||||
"ruleFilteringWidget": "Bloqueo por\nfiltros",
|
||||
"safeBrowsingWidget": "Navegación\nsegura",
|
||||
"parentalFilteringWidget": "Control\nparental",
|
||||
"safeSearchWidget": "Búsqueda\nsegura",
|
||||
"ruleFilteringWidget": "Bloqueo por filtros",
|
||||
"safeBrowsingWidget": "Navegación segura",
|
||||
"parentalFilteringWidget": "Control parental",
|
||||
"safeSearchWidget": "Búsqueda segura",
|
||||
"ruleFiltering": "Bloqueo por filtros",
|
||||
"safeBrowsing": "Navegación segura",
|
||||
"parentalFiltering": "Control parental",
|
||||
|
|
|
@ -48,12 +48,15 @@ class HomeChart extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurface
|
||||
Flexible(
|
||||
child: Text(
|
||||
label,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurface
|
||||
),
|
||||
),
|
||||
),
|
||||
!isEmpty
|
||||
|
|
|
@ -12,13 +12,27 @@ class HomeFab extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
void openManagementBottomSheet() {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => const ManagementModal(),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
if (width > 700) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const ManagementModal(
|
||||
dialog: true,
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => const ManagementModal(
|
||||
dialog: false,
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return serversProvider.serverStatus.loadStatus == 1
|
||||
|
|
|
@ -55,6 +55,8 @@ class _HomeState extends State<Home> {
|
|||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
Widget status() {
|
||||
switch (serversProvider.serverStatus.loadStatus) {
|
||||
case 0:
|
||||
|
@ -92,72 +94,138 @@ class _HomeState extends State<Home> {
|
|||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.dnsQueries,
|
||||
label: AppLocalizations.of(context)!.dnsQueries,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName),
|
||||
secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms",
|
||||
color: Colors.blue,
|
||||
),
|
||||
|
||||
HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.blockedFiltering,
|
||||
label: AppLocalizations.of(context)!.blockedFilters,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName),
|
||||
secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%",
|
||||
color: Colors.red,
|
||||
Wrap(
|
||||
children: [
|
||||
FractionallySizedBox(
|
||||
widthFactor: width > 700 ? 0.5 : 1,
|
||||
child: HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.dnsQueries,
|
||||
label: AppLocalizations.of(context)!.dnsQueries,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName),
|
||||
secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms",
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
FractionallySizedBox(
|
||||
widthFactor: width > 700 ? 0.5 : 1,
|
||||
child: HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.blockedFiltering,
|
||||
label: AppLocalizations.of(context)!.blockedFilters,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName),
|
||||
secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%",
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
FractionallySizedBox(
|
||||
widthFactor: width > 700 ? 0.5 : 1,
|
||||
child: HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing,
|
||||
label: AppLocalizations.of(context)!.malwarePhisingBlocked,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName),
|
||||
secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%",
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
FractionallySizedBox(
|
||||
widthFactor: width > 700 ? 0.5 : 1,
|
||||
child: HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.replacedParental,
|
||||
label: AppLocalizations.of(context)!.blockedAdultWebsites,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName),
|
||||
secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%",
|
||||
color: Colors.orange,
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing,
|
||||
label: AppLocalizations.of(context)!.malwarePhisingBlocked,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName),
|
||||
secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%",
|
||||
color: Colors.green,
|
||||
),
|
||||
|
||||
HomeChart(
|
||||
data: serversProvider.serverStatus.data!.stats.replacedParental,
|
||||
label: AppLocalizations.of(context)!.blockedAdultWebsites,
|
||||
primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName),
|
||||
secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%",
|
||||
color: Colors.orange,
|
||||
),
|
||||
|
||||
TopItems(
|
||||
label: AppLocalizations.of(context)!.topQueriedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topQueriedDomains,
|
||||
type: 'topQueriedDomains',
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Divider(
|
||||
thickness: 1,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2),
|
||||
if (width <= 700) ...[
|
||||
TopItems(
|
||||
label: AppLocalizations.of(context)!.topQueriedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topQueriedDomains,
|
||||
type: 'topQueriedDomains',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
TopItems(
|
||||
label: AppLocalizations.of(context)!.topBlockedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topBlockedDomains,
|
||||
type: 'topBlockedDomains',
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Divider(
|
||||
thickness: 1,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Divider(
|
||||
thickness: 1,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
TopItems(
|
||||
label: AppLocalizations.of(context)!.topClients,
|
||||
data: serversProvider.serverStatus.data!.stats.topClients,
|
||||
type: 'topClients',
|
||||
clients: true,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
TopItems(
|
||||
label: AppLocalizations.of(context)!.topBlockedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topBlockedDomains,
|
||||
type: 'topBlockedDomains',
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Divider(
|
||||
thickness: 1,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
TopItems(
|
||||
label: AppLocalizations.of(context)!.topClients,
|
||||
data: serversProvider.serverStatus.data!.stats.topClients,
|
||||
type: 'topClients',
|
||||
clients: true,
|
||||
),
|
||||
],
|
||||
if (width > 700) Column(
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 500
|
||||
),
|
||||
child: TopItems(
|
||||
label: AppLocalizations.of(context)!.topQueriedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topQueriedDomains,
|
||||
type: 'topQueriedDomains',
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 500
|
||||
),
|
||||
child: TopItems(
|
||||
label: AppLocalizations.of(context)!.topBlockedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topBlockedDomains,
|
||||
type: 'topBlockedDomains',
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 500
|
||||
),
|
||||
child: TopItems(
|
||||
label: AppLocalizations.of(context)!.topBlockedDomains,
|
||||
data: serversProvider.serverStatus.data!.stats.topBlockedDomains,
|
||||
type: 'topBlockedDomains',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
@ -15,7 +15,12 @@ import 'package:adguard_home_manager/services/http_requests.dart';
|
|||
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||
|
||||
class ManagementModal extends StatefulWidget {
|
||||
const ManagementModal({Key? key}) : super(key: key);
|
||||
final bool dialog;
|
||||
|
||||
const ManagementModal({
|
||||
Key? key,
|
||||
required this.dialog
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ManagementModal> createState() => _ManagementModalState();
|
||||
|
@ -364,8 +369,112 @@ class _ManagementModalState extends State<ManagementModal> with SingleTickerProv
|
|||
);
|
||||
}
|
||||
|
||||
return SafeArea(
|
||||
child: Container(
|
||||
Widget header() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 24),
|
||||
child: Icon(
|
||||
Icons.shield_rounded,
|
||||
size: 24,
|
||||
color: Theme.of(context).listTileTheme.iconColor
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.manageServer,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> toggles() {
|
||||
return [
|
||||
mainSwitch(),
|
||||
Container(height: 10),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.ruleFiltering,
|
||||
Icons.filter_list_rounded,
|
||||
serversProvider.serverStatus.data!.filteringEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'filtering'),
|
||||
serversProvider.protectionsManagementProcess.contains('filtering')
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.safeBrowsing,
|
||||
Icons.vpn_lock_rounded,
|
||||
serversProvider.serverStatus.data!.safeBrowsingEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'safeBrowsing'),
|
||||
serversProvider.protectionsManagementProcess.contains('safeBrowsing')
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.parentalFiltering,
|
||||
Icons.block,
|
||||
serversProvider.serverStatus.data!.parentalControlEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'parentalControl'),
|
||||
serversProvider.protectionsManagementProcess.contains('parentalControl')
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.safeSearch,
|
||||
Icons.search_rounded,
|
||||
serversProvider.serverStatus.data!.safeSearchEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'safeSearch'),
|
||||
serversProvider.protectionsManagementProcess.contains('safeSearch')
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
if (widget.dialog == true) {
|
||||
return Dialog(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 400
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Wrap(
|
||||
children: [
|
||||
header(),
|
||||
...toggles()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(AppLocalizations.of(context)!.close),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (Platform.isIOS) const SizedBox(height: 16)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: const BorderRadius.only(
|
||||
|
@ -373,66 +482,18 @@ class _ManagementModalState extends State<ManagementModal> with SingleTickerProv
|
|||
topRight: Radius.circular(28)
|
||||
)
|
||||
),
|
||||
child: Wrap(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Wrap(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 24),
|
||||
child: Icon(
|
||||
Icons.shield_rounded,
|
||||
size: 24,
|
||||
color: Theme.of(context).listTileTheme.iconColor
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.manageServer,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
header(),
|
||||
...toggles()
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
mainSwitch(),
|
||||
const SizedBox(height: 10),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.ruleFiltering,
|
||||
Icons.filter_list_rounded,
|
||||
serversProvider.serverStatus.data!.filteringEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'filtering'),
|
||||
serversProvider.protectionsManagementProcess.contains('filtering')
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.safeBrowsing,
|
||||
Icons.vpn_lock_rounded,
|
||||
serversProvider.serverStatus.data!.safeBrowsingEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'safeBrowsing'),
|
||||
serversProvider.protectionsManagementProcess.contains('safeBrowsing')
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.parentalFiltering,
|
||||
Icons.block,
|
||||
serversProvider.serverStatus.data!.parentalControlEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'parentalControl'),
|
||||
serversProvider.protectionsManagementProcess.contains('parentalControl')
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.safeSearch,
|
||||
Icons.search_rounded,
|
||||
serversProvider.serverStatus.data!.safeSearchEnabled,
|
||||
(value) => updateBlocking(value: value, filter: 'safeSearch'),
|
||||
serversProvider.protectionsManagementProcess.contains('safeSearch')
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
|
@ -449,7 +510,7 @@ class _ManagementModalState extends State<ManagementModal> with SingleTickerProv
|
|||
if (Platform.isIOS) const SizedBox(height: 16)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,8 +15,12 @@ class ServerStatus extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: width > 700
|
||||
? const EdgeInsets.only(left: 20, right: 20, bottom: 20)
|
||||
: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
|
@ -29,11 +33,11 @@ class ServerStatus extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
height: 140,
|
||||
height: width > 700 ? 70 : 140,
|
||||
child: GridView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: width > 700 ? 4 : 2,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
mainAxisExtent: 65
|
||||
|
|
|
@ -44,13 +44,15 @@ class StatusBox extends StatelessWidget {
|
|||
: Colors.grey.computeLuminance() > 0.5 ? Colors.black : Colors.white,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: appConfigProvider.useThemeColorForStatus == true
|
||||
? Theme.of(context).colorScheme.primary.computeLuminance() > 0.5 ? Colors.black : Colors.white
|
||||
: Colors.grey.computeLuminance() > 0.5 ? Colors.black : Colors.white,
|
||||
fontWeight: FontWeight.w500
|
||||
Flexible(
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: appConfigProvider.useThemeColorForStatus == true
|
||||
? Theme.of(context).colorScheme.primary.computeLuminance() > 0.5 ? Colors.black : Colors.white
|
||||
: Colors.grey.computeLuminance() > 0.5 ? Colors.black : Colors.white,
|
||||
fontWeight: FontWeight.w500
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart';
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -35,6 +39,8 @@ class TopItems extends StatelessWidget {
|
|||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||
final logsProvider = Provider.of<LogsProvider>(context);
|
||||
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
bool? getIsBlocked() {
|
||||
if (type == 'topBlockedDomains') {
|
||||
return true;
|
||||
|
@ -266,16 +272,32 @@ class TopItems extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TopItemsScreen(
|
||||
type: type,
|
||||
title: label,
|
||||
isClient: clients,
|
||||
data: generateData(),
|
||||
onPressed: () => {
|
||||
if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => TopItemsModal(
|
||||
type: type,
|
||||
title: label,
|
||||
isClient: clients,
|
||||
data: generateData(),
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
}
|
||||
else {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TopItemsScreen(
|
||||
type: type,
|
||||
title: label,
|
||||
isClient: clients,
|
||||
data: generateData(),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
|
276
lib/screens/top_items/top_items_modal.dart
Normal file
276
lib/screens/top_items/top_items_modal.dart
Normal file
|
@ -0,0 +1,276 @@
|
|||
// 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/screens/home/top_items_options_modal.dart';
|
||||
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
||||
|
||||
import 'package:adguard_home_manager/models/applied_filters.dart';
|
||||
import 'package:adguard_home_manager/functions/copy_clipboard.dart';
|
||||
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
||||
import 'package:adguard_home_manager/functions/snackbar.dart';
|
||||
import 'package:adguard_home_manager/functions/number_format.dart';
|
||||
import 'package:adguard_home_manager/functions/block_unblock_domain.dart';
|
||||
import 'package:adguard_home_manager/providers/app_config_provider.dart';
|
||||
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||
|
||||
class TopItemsModal extends StatefulWidget {
|
||||
final String type;
|
||||
final String title;
|
||||
final bool? isClient;
|
||||
final List<Map<String, dynamic>> data;
|
||||
|
||||
const TopItemsModal({
|
||||
Key? key,
|
||||
required this.type,
|
||||
required this.title,
|
||||
this.isClient,
|
||||
required this.data,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<TopItemsModal> createState() => _TopItemsModalState();
|
||||
}
|
||||
|
||||
class _TopItemsModalState extends State<TopItemsModal> {
|
||||
bool searchActive = false;
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
List<Map<String, dynamic>> data = [];
|
||||
List<Map<String, dynamic>> screenData = [];
|
||||
|
||||
void search(String value) {
|
||||
List<Map<String, dynamic>> 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<ServersProvider>(context);
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||
final logsProvider = Provider.of<LogsProvider>(context);
|
||||
|
||||
int total = 0;
|
||||
for (var element in data) {
|
||||
total = total + int.parse(element.values.toList()[0].toString());
|
||||
}
|
||||
|
||||
bool? getIsBlocked() {
|
||||
if (widget.type == 'topBlockedDomains') {
|
||||
return true;
|
||||
}
|
||||
else if (widget.type == 'topQueriedDomains') {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void changeBlockStatus(String status, String domain) async {
|
||||
final result = await blockUnblock(context, domain, status);
|
||||
showSnacbkar(
|
||||
context: context,
|
||||
appConfigProvider: appConfigProvider,
|
||||
label: result['message'],
|
||||
color: result['success'] == true ? Colors.green : Colors.red
|
||||
);
|
||||
}
|
||||
|
||||
void openOptionsModal(String domain, String type) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => TopItemsOptionsModal(
|
||||
isBlocked: getIsBlocked(),
|
||||
changeStatus: (String status) => changeBlockStatus(status, domain),
|
||||
copyToClipboard: () => copyToClipboard(
|
||||
context: context,
|
||||
value: domain,
|
||||
successMessage: AppLocalizations.of(context)!.domainCopiedClipboard
|
||||
),
|
||||
type: type,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
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 = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name;
|
||||
} catch (e) {
|
||||
// ---- //
|
||||
}
|
||||
}
|
||||
|
||||
return CustomListTile(
|
||||
onTap: () {
|
||||
if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') {
|
||||
logsProvider.setSearchText(screenData[index].keys.toList()[0]);
|
||||
logsProvider.setSelectedClients(null);
|
||||
logsProvider.setAppliedFilters(
|
||||
AppliedFiters(
|
||||
selectedResultStatus: 'all',
|
||||
searchText: screenData[index].keys.toList()[0],
|
||||
clients: null
|
||||
)
|
||||
);
|
||||
appConfigProvider.setSelectedScreen(2);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
else if (widget.type == 'topClients') {
|
||||
logsProvider.setSearchText(null);
|
||||
logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]);
|
||||
logsProvider.setAppliedFilters(
|
||||
AppliedFiters(
|
||||
selectedResultStatus: 'all',
|
||||
searchText: null,
|
||||
clients: [screenData[index].keys.toList()[0]]
|
||||
)
|
||||
);
|
||||
appConfigProvider.setSelectedScreen(2);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
onLongPress: () => openOptionsModal(
|
||||
screenData[index].keys.toList()[0],
|
||||
widget.type
|
||||
),
|
||||
title: screenData[index].keys.toList()[0],
|
||||
trailing: Text(
|
||||
screenData[index].values.toList()[0].toString(),
|
||||
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),
|
||||
],
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue