mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-23 15:29:13 +00:00
Optimized logs
This commit is contained in:
parent
aacf68569d
commit
578e606b83
8 changed files with 1043 additions and 626 deletions
|
@ -606,5 +606,6 @@
|
||||||
"remainingTime": "Remaining time",
|
"remainingTime": "Remaining time",
|
||||||
"safeSearchSettings": "Safe search settings",
|
"safeSearchSettings": "Safe search settings",
|
||||||
"loadingSafeSearchSettings": "Loading safe search settings...",
|
"loadingSafeSearchSettings": "Loading safe search settings...",
|
||||||
"safeSearchSettingsNotLoaded": "Error when loading safe search settings."
|
"safeSearchSettingsNotLoaded": "Error when loading safe search settings.",
|
||||||
|
"loadingLogsSettings": "Loading logs settings..."
|
||||||
}
|
}
|
|
@ -606,5 +606,6 @@
|
||||||
"remainingTime": "Tiempo restante",
|
"remainingTime": "Tiempo restante",
|
||||||
"safeSearchSettings": "Configuración de búsqueda segura",
|
"safeSearchSettings": "Configuración de búsqueda segura",
|
||||||
"loadingSafeSearchSettings": "Cargando configuración de búsqueda segura...",
|
"loadingSafeSearchSettings": "Cargando configuración de búsqueda segura...",
|
||||||
"safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura."
|
"safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura.",
|
||||||
|
"loadingLogsSettings": "Cargando configuración de registros..."
|
||||||
}
|
}
|
|
@ -8,10 +8,12 @@ import 'package:adguard_home_manager/providers/logs_provider.dart';
|
||||||
|
|
||||||
class ClientsModal extends StatefulWidget {
|
class ClientsModal extends StatefulWidget {
|
||||||
final List<String>? value;
|
final List<String>? value;
|
||||||
|
final bool dialog;
|
||||||
|
|
||||||
const ClientsModal({
|
const ClientsModal({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.value
|
required this.value,
|
||||||
|
required this.dialog
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -94,44 +96,36 @@ class _ClientsModalState extends State<ClientsModal> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
Widget content() {
|
||||||
height: height >= (logsProvider.clients!.length*64) == true
|
return Column(
|
||||||
? logsProvider.clients!.length*64
|
mainAxisSize: MainAxisSize.min,
|
||||||
: height-50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(28),
|
|
||||||
topRight: Radius.circular(28)
|
|
||||||
),
|
|
||||||
color: Theme.of(context).dialogBackgroundColor
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Column(
|
||||||
padding: const EdgeInsets.only(
|
children: [
|
||||||
top: 24,
|
Padding(
|
||||||
bottom: 16,
|
padding: const EdgeInsets.only(
|
||||||
),
|
top: 24,
|
||||||
child: Icon(
|
bottom: 16,
|
||||||
Icons.smartphone_rounded,
|
),
|
||||||
size: 24,
|
child: Icon(
|
||||||
color: Theme.of(context).listTileTheme.iconColor
|
Icons.smartphone_rounded,
|
||||||
),
|
size: 24,
|
||||||
|
color: Theme.of(context).listTileTheme.iconColor
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!.clients,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Text(
|
Flexible(
|
||||||
AppLocalizations.of(context)!.clients,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
color: Theme.of(context).colorScheme.onSurface
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
physics: height >= (logsProvider.clients!.length*64) == true
|
|
||||||
? const NeverScrollableScrollPhysics()
|
|
||||||
: null,
|
|
||||||
itemCount: logsProvider.clients!.length,
|
itemCount: logsProvider.clients!.length,
|
||||||
itemBuilder: (context, index) => listItem(
|
itemBuilder: (context, index) => listItem(
|
||||||
label: logsProvider.clients![index].ip,
|
label: logsProvider.clients![index].ip,
|
||||||
|
@ -150,7 +144,7 @@ class _ClientsModalState extends State<ClientsModal> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
|
@ -176,7 +170,35 @@ class _ClientsModalState extends State<ClientsModal> {
|
||||||
),
|
),
|
||||||
if (Platform.isIOS) const SizedBox(height: 16)
|
if (Platform.isIOS) const SizedBox(height: 16)
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
if (widget.dialog == true) {
|
||||||
|
return Dialog(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxWidth: 500
|
||||||
|
),
|
||||||
|
child: content()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: height-50
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(28),
|
||||||
|
topRight: Radius.circular(28)
|
||||||
|
),
|
||||||
|
color: Theme.of(context).dialogBackgroundColor
|
||||||
|
),
|
||||||
|
child: content()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,10 +8,12 @@ import 'package:adguard_home_manager/providers/logs_provider.dart';
|
||||||
|
|
||||||
class FilterStatusModal extends StatefulWidget {
|
class FilterStatusModal extends StatefulWidget {
|
||||||
final String value;
|
final String value;
|
||||||
|
final bool dialog;
|
||||||
|
|
||||||
const FilterStatusModal({
|
const FilterStatusModal({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.value
|
required this.value,
|
||||||
|
required this.dialog
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -31,8 +33,6 @@ class _FilterStatusModalState extends State<FilterStatusModal> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final logsProvider = Provider.of<LogsProvider>(context);
|
final logsProvider = Provider.of<LogsProvider>(context);
|
||||||
|
|
||||||
final height = MediaQuery.of(context).size.height;
|
|
||||||
|
|
||||||
void apply() async {
|
void apply() async {
|
||||||
logsProvider.setSelectedResultStatus(selectedResultStatus);
|
logsProvider.setSelectedResultStatus(selectedResultStatus);
|
||||||
|
|
||||||
|
@ -83,95 +83,94 @@ class _FilterStatusModalState extends State<FilterStatusModal> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
Widget content() {
|
||||||
height: height >= (Platform.isIOS ? 736 : 720) == true
|
return Column(
|
||||||
? (Platform.isIOS ? 736 : 720)
|
mainAxisSize: MainAxisSize.min,
|
||||||
: height-25,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(28),
|
|
||||||
topRight: Radius.circular(28)
|
|
||||||
),
|
|
||||||
color: Theme.of(context).dialogBackgroundColor
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Flexible(
|
||||||
padding: const EdgeInsets.only(
|
child: SingleChildScrollView(
|
||||||
top: 24,
|
child: Wrap(
|
||||||
bottom: 16,
|
children: [
|
||||||
),
|
Row(
|
||||||
child: Icon(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Icons.shield_rounded,
|
children: [
|
||||||
size: 24,
|
Column(
|
||||||
color: Theme.of(context).listTileTheme.iconColor
|
children: [
|
||||||
),
|
Padding(
|
||||||
),
|
padding: const EdgeInsets.only(
|
||||||
Text(
|
top: 24,
|
||||||
AppLocalizations.of(context)!.responseStatus,
|
bottom: 16,
|
||||||
style: TextStyle(
|
),
|
||||||
fontSize: 24,
|
child: Icon(
|
||||||
fontWeight: FontWeight.w400,
|
Icons.shield_rounded,
|
||||||
color: Theme.of(context).colorScheme.onSurface
|
size: 24,
|
||||||
),
|
color: Theme.of(context).listTileTheme.iconColor
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
Expanded(
|
Text(
|
||||||
child: ListView(
|
AppLocalizations.of(context)!.responseStatus,
|
||||||
physics: height >= 720 == true
|
style: TextStyle(
|
||||||
? const NeverScrollableScrollPhysics()
|
fontSize: 24,
|
||||||
: null,
|
fontWeight: FontWeight.w400,
|
||||||
children: [
|
color: Theme.of(context).colorScheme.onSurface
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "all",
|
),
|
||||||
icon: Icons.shield_rounded,
|
],
|
||||||
label: AppLocalizations.of(context)!.all,
|
)
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
],
|
||||||
),
|
),
|
||||||
filterStatusListItem(
|
Container(height: 16),
|
||||||
id: "filtered",
|
filterStatusListItem(
|
||||||
icon: Icons.shield_rounded,
|
id: "all",
|
||||||
label: AppLocalizations.of(context)!.filtered,
|
icon: Icons.shield_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.all,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "processed",
|
filterStatusListItem(
|
||||||
icon: Icons.verified_user_rounded,
|
id: "filtered",
|
||||||
label: AppLocalizations.of(context)!.processedRow,
|
icon: Icons.shield_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.filtered,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "whitelisted",
|
filterStatusListItem(
|
||||||
icon: Icons.verified_user_rounded,
|
id: "processed",
|
||||||
label: AppLocalizations.of(context)!.processedWhitelistRow,
|
icon: Icons.verified_user_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.processedRow,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "blocked",
|
filterStatusListItem(
|
||||||
icon: Icons.gpp_bad_rounded,
|
id: "whitelisted",
|
||||||
label: AppLocalizations.of(context)!.blocked,
|
icon: Icons.verified_user_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.processedWhitelistRow,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "blocked_safebrowsing",
|
filterStatusListItem(
|
||||||
icon: Icons.gpp_bad_rounded,
|
id: "blocked",
|
||||||
label: AppLocalizations.of(context)!.blockedSafeBrowsingRow,
|
icon: Icons.gpp_bad_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.blocked,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "blocked_parental",
|
filterStatusListItem(
|
||||||
icon: Icons.gpp_bad_rounded,
|
id: "blocked_safebrowsing",
|
||||||
label: AppLocalizations.of(context)!.blockedParentalRow,
|
icon: Icons.gpp_bad_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.blockedSafeBrowsingRow,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
filterStatusListItem(
|
),
|
||||||
id: "safe_search",
|
filterStatusListItem(
|
||||||
icon: Icons.gpp_bad_rounded,
|
id: "blocked_parental",
|
||||||
label: AppLocalizations.of(context)!.blockedSafeSearchRow,
|
icon: Icons.gpp_bad_rounded,
|
||||||
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
label: AppLocalizations.of(context)!.blockedParentalRow,
|
||||||
),
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
|
),
|
||||||
],
|
filterStatusListItem(
|
||||||
|
id: "safe_search",
|
||||||
|
icon: Icons.gpp_bad_rounded,
|
||||||
|
label: AppLocalizations.of(context)!.blockedSafeSearchRow,
|
||||||
|
onChanged: (value) => setState(() => selectedResultStatus = value!)
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -188,7 +187,30 @@ class _FilterStatusModalState extends State<FilterStatusModal> {
|
||||||
),
|
),
|
||||||
if (Platform.isIOS) const SizedBox(height: 16)
|
if (Platform.isIOS) const SizedBox(height: 16)
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
if (widget.dialog == true) {
|
||||||
|
return Dialog(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxWidth: 400
|
||||||
|
),
|
||||||
|
child: content()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(28),
|
||||||
|
topRight: Radius.circular(28)
|
||||||
|
),
|
||||||
|
color: Theme.of(context).dialogBackgroundColor
|
||||||
|
),
|
||||||
|
child: content()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.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/screens/home/top_items_options_modal.dart';
|
||||||
import 'package:adguard_home_manager/screens/logs/log_details_screen.dart';
|
|
||||||
|
|
||||||
import 'package:adguard_home_manager/functions/copy_clipboard.dart';
|
import 'package:adguard_home_manager/functions/copy_clipboard.dart';
|
||||||
import 'package:adguard_home_manager/functions/block_unblock_domain.dart';
|
import 'package:adguard_home_manager/functions/block_unblock_domain.dart';
|
||||||
|
@ -18,12 +18,16 @@ class LogTile extends StatelessWidget {
|
||||||
final Log log;
|
final Log log;
|
||||||
final int length;
|
final int length;
|
||||||
final int index;
|
final int index;
|
||||||
|
final bool? isLogSelected;
|
||||||
|
final void Function(Log) onLogTap;
|
||||||
|
|
||||||
const LogTile({
|
const LogTile({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.log,
|
required this.log,
|
||||||
required this.length,
|
required this.length,
|
||||||
required this.index
|
required this.index,
|
||||||
|
this.isLogSelected,
|
||||||
|
required this.onLogTap
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -95,133 +99,250 @@ class LogTile extends StatelessWidget {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Material(
|
if (width > 1100) {
|
||||||
color: Colors.transparent,
|
return Padding(
|
||||||
child: InkWell(
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
onTap: () => Navigator.push(context, MaterialPageRoute(
|
child: Material(
|
||||||
builder: (context) => LogDetailsScreen(log: log)
|
color: Colors.transparent,
|
||||||
)),
|
borderRadius: BorderRadius.circular(28),
|
||||||
onLongPress: () => openOptionsModal(log),
|
child: InkWell(
|
||||||
child: Container(
|
borderRadius: BorderRadius.circular(28),
|
||||||
width: double.maxFinite,
|
onTap: () => onLogTap(log),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
child: Container(
|
||||||
child: Row(
|
width: double.maxFinite,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
children: [
|
decoration: BoxDecoration(
|
||||||
SizedBox(
|
borderRadius: BorderRadius.circular(28),
|
||||||
width: width-130,
|
color: isLogSelected == true
|
||||||
child: Column(
|
? Theme.of(context).colorScheme.primaryContainer
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
: null
|
||||||
children: [
|
),
|
||||||
Text(
|
child: Row(
|
||||||
log.question.name,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: TextStyle(
|
children: [
|
||||||
fontSize: 16,
|
Flexible(
|
||||||
height: 1.5,
|
child: Row(
|
||||||
fontWeight: FontWeight.w400,
|
mainAxisSize: MainAxisSize.min,
|
||||||
color: Theme.of(context).colorScheme.onSurface
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row(
|
|
||||||
children: [
|
children: [
|
||||||
...[
|
Flexible(
|
||||||
Icon(
|
child: Column(
|
||||||
Icons.smartphone_rounded,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
size: 16,
|
children: [
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
Text(
|
||||||
),
|
log.question.name,
|
||||||
const SizedBox(width: 5),
|
style: TextStyle(
|
||||||
Flexible(
|
fontSize: 16,
|
||||||
child: Text(
|
fontWeight: FontWeight.w400,
|
||||||
log.client,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
overflow: TextOverflow.ellipsis,
|
),
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
|
||||||
fontSize: 14,
|
|
||||||
height: 1.4,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 5),
|
||||||
)
|
if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row(
|
||||||
],
|
children: [
|
||||||
const SizedBox(width: 15),
|
...[
|
||||||
...[
|
Icon(
|
||||||
Icon(
|
Icons.smartphone_rounded,
|
||||||
Icons.schedule_rounded,
|
size: 16,
|
||||||
size: 16,
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
),
|
||||||
),
|
const SizedBox(width: 5),
|
||||||
const SizedBox(width: 5),
|
Flexible(
|
||||||
Flexible(
|
child: Text(
|
||||||
child: Text(
|
log.client,
|
||||||
convertTimestampLocalTimezone(log.time, 'HH:mm:ss'),
|
overflow: TextOverflow.ellipsis,
|
||||||
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
||||||
style: TextStyle(
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
fontSize: 14,
|
||||||
fontSize: 13
|
height: 1.4,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
...[
|
||||||
|
Icon(
|
||||||
|
Icons.schedule_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
convertTimestampLocalTimezone(log.time, 'HH:mm:ss'),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.smartphone_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
log.client,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.badge_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
log.clientInfo!.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.schedule_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
SizedBox(
|
||||||
|
child: Text(
|
||||||
|
convertTimestampLocalTimezone(log.time, 'HH:mm:ss'),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.timer,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
SizedBox(
|
||||||
|
child: Text(
|
||||||
|
"${double.parse(log.elapsedMs).toStringAsFixed(2)} ms",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column(
|
),
|
||||||
children: [
|
generateLogStatus()
|
||||||
Row(
|
],
|
||||||
children: [
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => onLogTap(log),
|
||||||
|
onLongPress: () => openOptionsModal(log),
|
||||||
|
child: Container(
|
||||||
|
width: double.maxFinite,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
log.question.name,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
height: 1.5,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row(
|
||||||
|
children: [
|
||||||
|
...[
|
||||||
Icon(
|
Icon(
|
||||||
Icons.smartphone_rounded,
|
Icons.smartphone_rounded,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 15),
|
const SizedBox(width: 5),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
log.client,
|
log.client,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
fontSize: 13
|
fontSize: 14,
|
||||||
|
height: 1.4,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
const SizedBox(width: 15),
|
||||||
if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[
|
...[
|
||||||
const SizedBox(height: 10),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.badge_rounded,
|
|
||||||
size: 16,
|
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 15),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
log.clientInfo!.name,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
|
||||||
fontSize: 13
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
Icon(
|
||||||
Icons.schedule_rounded,
|
Icons.schedule_rounded,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 15),
|
const SizedBox(width: 5),
|
||||||
SizedBox(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
convertTimestampLocalTimezone(log.time, 'HH:mm:ss'),
|
convertTimestampLocalTimezone(log.time, 'HH:mm:ss'),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
@ -230,22 +351,23 @@ class LogTile extends StatelessWidget {
|
||||||
fontSize: 13
|
fontSize: 13
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[
|
),
|
||||||
const SizedBox(height: 10),
|
if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column(
|
||||||
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Icons.timer,
|
Icons.smartphone_rounded,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 15),
|
const SizedBox(width: 15),
|
||||||
SizedBox(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
"${double.parse(log.elapsedMs).toStringAsFixed(2)} ms",
|
log.client,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).listTileTheme.textColor,
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
@ -255,18 +377,85 @@ class LogTile extends StatelessWidget {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.badge_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
log.clientInfo!.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.schedule_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
SizedBox(
|
||||||
|
child: Text(
|
||||||
|
convertTimestampLocalTimezone(log.time, 'HH:mm:ss'),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.timer,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
SizedBox(
|
||||||
|
child: Text(
|
||||||
|
"${double.parse(log.elapsedMs).toStringAsFixed(2)} ms",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).listTileTheme.textColor,
|
||||||
|
fontSize: 13
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 10),
|
||||||
const SizedBox(width: 10),
|
generateLogStatus()
|
||||||
generateLogStatus()
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
@ -7,6 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart';
|
import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart';
|
||||||
import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart';
|
import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart';
|
||||||
import 'package:adguard_home_manager/screens/logs/log_tile.dart';
|
import 'package:adguard_home_manager/screens/logs/log_tile.dart';
|
||||||
|
import 'package:adguard_home_manager/screens/logs/log_details_screen.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';
|
||||||
|
@ -64,6 +67,8 @@ class _LogsWidgetState extends State<LogsWidget> {
|
||||||
|
|
||||||
bool showDivider = true;
|
bool showDivider = true;
|
||||||
|
|
||||||
|
Log? selectedLog;
|
||||||
|
|
||||||
Future fetchLogs({
|
Future fetchLogs({
|
||||||
int? inOffset,
|
int? inOffset,
|
||||||
bool? loadingMore,
|
bool? loadingMore,
|
||||||
|
@ -188,6 +193,8 @@ class _LogsWidgetState extends State<LogsWidget> {
|
||||||
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 width = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
void updateConfig(Map<String, dynamic> data) async {
|
void updateConfig(Map<String, dynamic> data) async {
|
||||||
ProcessModal processModal = ProcessModal(context: context);
|
ProcessModal processModal = ProcessModal(context: context);
|
||||||
processModal.open(AppLocalizations.of(context)!.updatingSettings);
|
processModal.open(AppLocalizations.of(context)!.updatingSettings);
|
||||||
|
@ -252,12 +259,25 @@ class _LogsWidgetState extends State<LogsWidget> {
|
||||||
|
|
||||||
|
|
||||||
void openFilersModal() {
|
void openFilersModal() {
|
||||||
showModalBottomSheet(
|
if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) {
|
||||||
context: context,
|
showDialog(
|
||||||
builder: (context) => const LogsFiltersModal(),
|
context: context,
|
||||||
backgroundColor: Colors.transparent,
|
builder: (context) => const LogsFiltersModal(
|
||||||
isScrollControlled: true
|
dialog: true,
|
||||||
);
|
),
|
||||||
|
barrierDismissible: false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => const LogsFiltersModal(
|
||||||
|
dialog: false,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
isScrollControlled: true
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Map<String, String> translatedString = {
|
final Map<String, String> translatedString = {
|
||||||
|
@ -319,6 +339,15 @@ class _LogsWidgetState extends State<LogsWidget> {
|
||||||
log: logsProvider.logsData!.data[index],
|
log: logsProvider.logsData!.data[index],
|
||||||
index: index,
|
index: index,
|
||||||
length: logsProvider.logsData!.data.length,
|
length: logsProvider.logsData!.data.length,
|
||||||
|
isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index],
|
||||||
|
onLogTap: (log) {
|
||||||
|
if (width <= 700) {
|
||||||
|
Navigator.push(context, MaterialPageRoute(
|
||||||
|
builder: (context) => LogDetailsScreen(log: log)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
setState(() => selectedLog = log);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,161 +412,207 @@ class _LogsWidgetState extends State<LogsWidget> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
Widget logsScreen() {
|
||||||
appBar: AppBar(
|
return Scaffold(
|
||||||
title: Text(AppLocalizations.of(context)!.logs),
|
appBar: AppBar(
|
||||||
centerTitle: false,
|
title: Text(AppLocalizations.of(context)!.logs),
|
||||||
actions: [
|
centerTitle: false,
|
||||||
logsProvider.loadStatus == 1
|
actions: [
|
||||||
? IconButton(
|
if (!(Platform.isAndroid || Platform.isIOS)) IconButton(
|
||||||
onPressed: openFilersModal,
|
onPressed: () => fetchLogs(inOffset: 0),
|
||||||
icon: const Icon(Icons.filter_list_rounded)
|
icon: const Icon(Icons.refresh_rounded),
|
||||||
)
|
tooltip: AppLocalizations.of(context)!.refresh,
|
||||||
: const SizedBox(),
|
),
|
||||||
IconButton(
|
logsProvider.loadStatus == 1
|
||||||
onPressed: () => {
|
? IconButton(
|
||||||
showModalBottomSheet(
|
onPressed: openFilersModal,
|
||||||
context: context,
|
icon: const Icon(Icons.filter_list_rounded),
|
||||||
builder: (context) => LogsConfigModal(
|
tooltip: AppLocalizations.of(context)!.filters,
|
||||||
onConfirm: updateConfig,
|
)
|
||||||
onClear: clearQueries,
|
: const SizedBox(),
|
||||||
),
|
IconButton(
|
||||||
backgroundColor: Colors.transparent,
|
tooltip: AppLocalizations.of(context)!.settings,
|
||||||
isScrollControlled: true
|
onPressed: () => {
|
||||||
)
|
if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) {
|
||||||
},
|
showDialog(
|
||||||
icon: const Icon(Icons.settings)
|
context: context,
|
||||||
),
|
builder: (context) => LogsConfigModal(
|
||||||
const SizedBox(width: 5),
|
onConfirm: updateConfig,
|
||||||
],
|
onClear: clearQueries,
|
||||||
bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null
|
dialog: true,
|
||||||
? PreferredSize(
|
),
|
||||||
preferredSize: const Size(double.maxFinite, 50),
|
barrierDismissible: false
|
||||||
child: Container(
|
|
||||||
height: 50,
|
|
||||||
width: double.maxFinite,
|
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(
|
|
||||||
color: showDivider == true
|
|
||||||
? Theme.of(context).colorScheme.onSurface.withOpacity(0.1)
|
|
||||||
: Colors.transparent,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
}
|
||||||
child: ListView(
|
else {
|
||||||
scrollDirection: Axis.horizontal,
|
showModalBottomSheet(
|
||||||
children: [
|
context: context,
|
||||||
if (logsProvider.appliedFilters.searchText != null) ...[
|
builder: (context) => LogsConfigModal(
|
||||||
|
onConfirm: updateConfig,
|
||||||
|
onClear: clearQueries,
|
||||||
|
dialog: false,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
isScrollControlled: true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.settings)
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5),
|
||||||
|
],
|
||||||
|
bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null
|
||||||
|
? PreferredSize(
|
||||||
|
preferredSize: const Size(double.maxFinite, 50),
|
||||||
|
child: Container(
|
||||||
|
height: 50,
|
||||||
|
width: double.maxFinite,
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: showDivider == true
|
||||||
|
? Theme.of(context).colorScheme.onSurface.withOpacity(0.1)
|
||||||
|
: Colors.transparent,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
children: [
|
||||||
|
if (logsProvider.appliedFilters.searchText != null) ...[
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Chip(
|
||||||
|
avatar: const Icon(
|
||||||
|
Icons.link_rounded,
|
||||||
|
),
|
||||||
|
label: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
logsProvider.appliedFilters.searchText!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
deleteIcon: const Icon(
|
||||||
|
Icons.clear,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
onDeleted: () {
|
||||||
|
logsProvider.setAppliedFilters(
|
||||||
|
AppliedFiters(
|
||||||
|
selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus,
|
||||||
|
searchText: null,
|
||||||
|
clients: logsProvider.appliedFilters.clients
|
||||||
|
)
|
||||||
|
);
|
||||||
|
logsProvider.setSearchText(null);
|
||||||
|
fetchLogs(
|
||||||
|
inOffset: 0,
|
||||||
|
searchText: ''
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Chip(
|
||||||
|
avatar: const Icon(
|
||||||
|
Icons.shield_rounded,
|
||||||
|
),
|
||||||
|
label: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
translatedString[logsProvider.appliedFilters.selectedResultStatus]!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
deleteIcon: const Icon(
|
||||||
|
Icons.clear,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
onDeleted: () {
|
||||||
|
logsProvider.setAppliedFilters(
|
||||||
|
AppliedFiters(
|
||||||
|
selectedResultStatus: 'all',
|
||||||
|
searchText: logsProvider.appliedFilters.searchText,
|
||||||
|
clients: logsProvider.appliedFilters.clients
|
||||||
|
)
|
||||||
|
);
|
||||||
|
logsProvider.setSelectedResultStatus('all');
|
||||||
|
fetchLogs(
|
||||||
|
inOffset: 0,
|
||||||
|
responseStatus: 'all'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (logsProvider.appliedFilters.clients != null) ...[
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Chip(
|
||||||
|
avatar: const Icon(
|
||||||
|
Icons.smartphone_rounded,
|
||||||
|
),
|
||||||
|
label: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
logsProvider.appliedFilters.clients!.length == 1
|
||||||
|
? logsProvider.appliedFilters.clients![0]
|
||||||
|
: "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
deleteIcon: const Icon(
|
||||||
|
Icons.clear,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
onDeleted: () {
|
||||||
|
logsProvider.setAppliedFilters(
|
||||||
|
AppliedFiters(
|
||||||
|
selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus,
|
||||||
|
searchText: logsProvider.appliedFilters.searchText,
|
||||||
|
clients: null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
logsProvider.setSelectedClients(null);
|
||||||
|
fetchLogs(
|
||||||
|
inOffset: 0,
|
||||||
|
responseStatus: logsProvider.appliedFilters.selectedResultStatus
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(width: 15),
|
const SizedBox(width: 15),
|
||||||
Chip(
|
|
||||||
avatar: const Icon(
|
|
||||||
Icons.link_rounded,
|
|
||||||
),
|
|
||||||
label: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
logsProvider.appliedFilters.searchText!,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
deleteIcon: const Icon(
|
|
||||||
Icons.clear,
|
|
||||||
size: 18,
|
|
||||||
),
|
|
||||||
onDeleted: () {
|
|
||||||
logsProvider.setAppliedFilters(
|
|
||||||
AppliedFiters(
|
|
||||||
selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus,
|
|
||||||
searchText: null,
|
|
||||||
clients: logsProvider.appliedFilters.clients
|
|
||||||
)
|
|
||||||
);
|
|
||||||
logsProvider.setSearchText(null);
|
|
||||||
fetchLogs(
|
|
||||||
inOffset: 0,
|
|
||||||
searchText: ''
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[
|
),
|
||||||
const SizedBox(width: 15),
|
)
|
||||||
Chip(
|
|
||||||
avatar: const Icon(
|
|
||||||
Icons.shield_rounded,
|
|
||||||
),
|
|
||||||
label: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
translatedString[logsProvider.appliedFilters.selectedResultStatus]!,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
deleteIcon: const Icon(
|
|
||||||
Icons.clear,
|
|
||||||
size: 18,
|
|
||||||
),
|
|
||||||
onDeleted: () {
|
|
||||||
logsProvider.setAppliedFilters(
|
|
||||||
AppliedFiters(
|
|
||||||
selectedResultStatus: 'all',
|
|
||||||
searchText: logsProvider.appliedFilters.searchText,
|
|
||||||
clients: logsProvider.appliedFilters.clients
|
|
||||||
)
|
|
||||||
);
|
|
||||||
logsProvider.setSelectedResultStatus('all');
|
|
||||||
fetchLogs(
|
|
||||||
inOffset: 0,
|
|
||||||
responseStatus: 'all'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
if (logsProvider.appliedFilters.clients != null) ...[
|
|
||||||
const SizedBox(width: 15),
|
|
||||||
Chip(
|
|
||||||
avatar: const Icon(
|
|
||||||
Icons.smartphone_rounded,
|
|
||||||
),
|
|
||||||
label: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
logsProvider.appliedFilters.clients!.length == 1
|
|
||||||
? logsProvider.appliedFilters.clients![0]
|
|
||||||
: "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
deleteIcon: const Icon(
|
|
||||||
Icons.clear,
|
|
||||||
size: 18,
|
|
||||||
),
|
|
||||||
onDeleted: () {
|
|
||||||
logsProvider.setAppliedFilters(
|
|
||||||
AppliedFiters(
|
|
||||||
selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus,
|
|
||||||
searchText: logsProvider.appliedFilters.searchText,
|
|
||||||
clients: null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
logsProvider.setSelectedClients(null);
|
|
||||||
fetchLogs(
|
|
||||||
inOffset: 0,
|
|
||||||
responseStatus: logsProvider.appliedFilters.selectedResultStatus
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SizedBox(width: 15),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
body: generateBody()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width > 1100) {
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: logsScreen()
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: selectedLog != null
|
||||||
|
? LogDetailsScreen(log: selectedLog!)
|
||||||
|
: const SizedBox()
|
||||||
)
|
)
|
||||||
: null,
|
],
|
||||||
),
|
),
|
||||||
body: generateBody()
|
);
|
||||||
);
|
}
|
||||||
|
else {
|
||||||
|
return logsScreen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,11 +12,13 @@ import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||||
class LogsConfigModal extends StatelessWidget {
|
class LogsConfigModal extends StatelessWidget {
|
||||||
final void Function(Map<String, dynamic>) onConfirm;
|
final void Function(Map<String, dynamic>) onConfirm;
|
||||||
final void Function() onClear;
|
final void Function() onClear;
|
||||||
|
final bool dialog;
|
||||||
|
|
||||||
const LogsConfigModal({
|
const LogsConfigModal({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.onConfirm,
|
required this.onConfirm,
|
||||||
required this.onClear,
|
required this.onClear,
|
||||||
|
required this.dialog
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -30,6 +32,7 @@ class LogsConfigModal extends StatelessWidget {
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: onConfirm,
|
onConfirm: onConfirm,
|
||||||
onClear: onClear,
|
onClear: onClear,
|
||||||
|
dialog: dialog,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +43,7 @@ class LogsConfigModalWidget extends StatefulWidget {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final void Function(Map<String, dynamic>) onConfirm;
|
final void Function(Map<String, dynamic>) onConfirm;
|
||||||
final void Function() onClear;
|
final void Function() onClear;
|
||||||
|
final bool dialog;
|
||||||
|
|
||||||
const LogsConfigModalWidget({
|
const LogsConfigModalWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -48,6 +52,7 @@ class LogsConfigModalWidget extends StatefulWidget {
|
||||||
required this.context,
|
required this.context,
|
||||||
required this.onConfirm,
|
required this.onConfirm,
|
||||||
required this.onClear,
|
required this.onClear,
|
||||||
|
required this.dialog
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -146,125 +151,154 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
|
||||||
Widget generateBody() {
|
Widget generateBody() {
|
||||||
switch (loadStatus) {
|
switch (loadStatus) {
|
||||||
case 0:
|
case 0:
|
||||||
return const Center(
|
return Padding(
|
||||||
child: CircularProgressIndicator(),
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const CircularProgressIndicator(),
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!.loadingLogsSettings,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
return Column(
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Flexible(
|
||||||
child: ListView(
|
child: SingleChildScrollView(
|
||||||
physics: (Platform.isIOS ? 436 : 420) < MediaQuery.of(context).size.height
|
child: Wrap(
|
||||||
? const NeverScrollableScrollPhysics()
|
children: [
|
||||||
: null,
|
Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Padding(
|
children: [
|
||||||
padding: const EdgeInsets.only(top: 24),
|
Column(
|
||||||
child: Icon(
|
children: [
|
||||||
Icons.settings,
|
Padding(
|
||||||
size: 24,
|
padding: const EdgeInsets.only(top: 24),
|
||||||
color: Theme.of(context).listTileTheme.iconColor
|
child: Icon(
|
||||||
),
|
Icons.settings,
|
||||||
),
|
size: 24,
|
||||||
const SizedBox(height: 16),
|
color: Theme.of(context).listTileTheme.iconColor
|
||||||
Text(
|
|
||||||
AppLocalizations.of(context)!.logsSettings,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
color: Theme.of(context).colorScheme.onSurface
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
child: Material(
|
|
||||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
|
||||||
borderRadius: BorderRadius.circular(28),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () => setState(() => generalSwitch = !generalSwitch),
|
|
||||||
borderRadius: BorderRadius.circular(28),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
vertical: 8
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
AppLocalizations.of(context)!.enableLog,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Switch(
|
),
|
||||||
value: generalSwitch,
|
const SizedBox(height: 16),
|
||||||
onChanged: (value) => setState(() => generalSwitch = value),
|
Text(
|
||||||
)
|
AppLocalizations.of(context)!.logsSettings,
|
||||||
],
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Material(
|
||||||
|
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(28),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => setState(() => generalSwitch = !generalSwitch),
|
||||||
|
borderRadius: BorderRadius.circular(28),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
vertical: 8
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!.enableLog,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Switch(
|
||||||
|
value: generalSwitch,
|
||||||
|
onChanged: (value) => setState(() => generalSwitch = value),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(height: 16),
|
||||||
const SizedBox(height: 16),
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
Material(
|
||||||
Material(
|
color: Colors.transparent,
|
||||||
color: Colors.transparent,
|
child: InkWell(
|
||||||
child: InkWell(
|
onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp),
|
||||||
onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp),
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 30),
|
child: Row(
|
||||||
child: Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
AppLocalizations.of(context)!.anonymizeClientIp,
|
||||||
AppLocalizations.of(context)!.anonymizeClientIp,
|
style: const TextStyle(
|
||||||
style: const TextStyle(
|
fontSize: 16
|
||||||
fontSize: 16
|
),
|
||||||
),
|
),
|
||||||
),
|
Switch(
|
||||||
Switch(
|
value: anonymizeClientIp,
|
||||||
value: anonymizeClientIp,
|
onChanged: (value) => setState(() => anonymizeClientIp = value),
|
||||||
onChanged: (value) => setState(() => anonymizeClientIp = value),
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(height: 16),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: DropdownButtonFormField(
|
||||||
|
items: retentionItems.map<DropdownMenuItem<String>>((Map<String, dynamic> item) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: item['value'].toString(),
|
||||||
|
child: Text(item['label']),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: retentionTime,
|
||||||
|
onChanged: (value) => setState(() => retentionTime = value),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: const OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(10)
|
||||||
)
|
)
|
||||||
],
|
),
|
||||||
|
label: Text(AppLocalizations.of(context)!.retentionTime)
|
||||||
),
|
),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
Padding(
|
)
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
],
|
||||||
child: DropdownButtonFormField(
|
),
|
||||||
items: retentionItems.map<DropdownMenuItem<String>>((Map<String, dynamic> item) {
|
|
||||||
return DropdownMenuItem<String>(
|
|
||||||
value: item['value'].toString(),
|
|
||||||
child: Text(item['label']),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
value: retentionTime,
|
|
||||||
onChanged: (value) => setState(() => retentionTime = value),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: const OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(10)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
label: Text(AppLocalizations.of(context)!.retentionTime)
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -316,31 +350,29 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
|
||||||
);
|
);
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return SizedBox(
|
return Column(
|
||||||
width: double.maxFinite,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
||||||
children: [
|
const Icon(
|
||||||
const Icon(
|
Icons.error,
|
||||||
Icons.error,
|
color: Colors.red,
|
||||||
color: Colors.red,
|
size: 50,
|
||||||
size: 50,
|
),
|
||||||
),
|
const SizedBox(height: 30),
|
||||||
const SizedBox(height: 30),
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
child: Text(
|
||||||
child: Text(
|
AppLocalizations.of(context)!.logSettingsNotLoaded,
|
||||||
AppLocalizations.of(context)!.logSettingsNotLoaded,
|
textAlign: TextAlign.center,
|
||||||
textAlign: TextAlign.center,
|
style: TextStyle(
|
||||||
style: const TextStyle(
|
fontSize: 22,
|
||||||
fontSize: 22,
|
color: Theme.of(context).colorScheme.onSurfaceVariant
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
)
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -348,16 +380,28 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
if (widget.dialog == true) {
|
||||||
height: Platform.isIOS ? 436 : 420,
|
return Dialog(
|
||||||
decoration: BoxDecoration(
|
child: ConstrainedBox(
|
||||||
borderRadius: const BorderRadius.only(
|
constraints: const BoxConstraints(
|
||||||
topLeft: Radius.circular(28),
|
maxWidth: 500
|
||||||
topRight: Radius.circular(28)
|
),
|
||||||
|
child: generateBody()
|
||||||
),
|
),
|
||||||
color: Theme.of(context).dialogBackgroundColor
|
);
|
||||||
),
|
}
|
||||||
child: generateBody()
|
else {
|
||||||
);
|
return Container(
|
||||||
|
height: Platform.isIOS ? 436 : 420,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(28),
|
||||||
|
topRight: Radius.circular(28)
|
||||||
|
),
|
||||||
|
color: Theme.of(context).dialogBackgroundColor
|
||||||
|
),
|
||||||
|
child: generateBody()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,24 +18,32 @@ import 'package:adguard_home_manager/models/applied_filters.dart';
|
||||||
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
||||||
|
|
||||||
class LogsFiltersModal extends StatelessWidget {
|
class LogsFiltersModal extends StatelessWidget {
|
||||||
const LogsFiltersModal({Key? key}) : super(key: key);
|
final bool dialog;
|
||||||
|
|
||||||
|
const LogsFiltersModal({
|
||||||
|
Key? key,
|
||||||
|
required this.dialog
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final logsProvider = Provider.of<LogsProvider>(context);
|
final logsProvider = Provider.of<LogsProvider>(context);
|
||||||
|
|
||||||
return LogsFiltersModalWidget(
|
return LogsFiltersModalWidget(
|
||||||
logsProvider: logsProvider
|
logsProvider: logsProvider,
|
||||||
|
dialog: dialog,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LogsFiltersModalWidget extends StatefulWidget {
|
class LogsFiltersModalWidget extends StatefulWidget {
|
||||||
final LogsProvider logsProvider;
|
final LogsProvider logsProvider;
|
||||||
|
final bool dialog;
|
||||||
|
|
||||||
const LogsFiltersModalWidget({
|
const LogsFiltersModalWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.logsProvider
|
required this.logsProvider,
|
||||||
|
required this.dialog
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -57,6 +65,8 @@ class _LogsFiltersModalWidgetState extends State<LogsFiltersModalWidget> {
|
||||||
final serversProvider = Provider.of<ServersProvider>(context);
|
final serversProvider = Provider.of<ServersProvider>(context);
|
||||||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||||
|
|
||||||
|
final width = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
final Map<String, String> translatedString = {
|
final Map<String, String> translatedString = {
|
||||||
"all": AppLocalizations.of(context)!.all,
|
"all": AppLocalizations.of(context)!.all,
|
||||||
"filtered": AppLocalizations.of(context)!.filtered,
|
"filtered": AppLocalizations.of(context)!.filtered,
|
||||||
|
@ -101,25 +111,51 @@ class _LogsFiltersModalWidgetState extends State<LogsFiltersModalWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void openSelectFilterStatus() {
|
void openSelectFilterStatus() {
|
||||||
showModalBottomSheet(
|
if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) {
|
||||||
context: context,
|
showDialog(
|
||||||
builder: (context) => FilterStatusModal(
|
barrierDismissible: false,
|
||||||
value: logsProvider.selectedResultStatus,
|
context: context,
|
||||||
),
|
builder: (context) => FilterStatusModal(
|
||||||
isScrollControlled: true,
|
value: logsProvider.selectedResultStatus,
|
||||||
backgroundColor: Colors.transparent
|
dialog: true,
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => FilterStatusModal(
|
||||||
|
value: logsProvider.selectedResultStatus,
|
||||||
|
dialog: false,
|
||||||
|
),
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void openSelectClients() {
|
void openSelectClients() {
|
||||||
showModalBottomSheet(
|
if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) {
|
||||||
context: context,
|
showDialog(
|
||||||
builder: (context) => ClientsModal(
|
context: context,
|
||||||
value: logsProvider.selectedClients,
|
builder: (context) => ClientsModal(
|
||||||
),
|
value: logsProvider.selectedClients,
|
||||||
isScrollControlled: true,
|
dialog: true,
|
||||||
backgroundColor: Colors.transparent
|
),
|
||||||
);
|
barrierDismissible: false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => ClientsModal(
|
||||||
|
value: logsProvider.selectedClients,
|
||||||
|
dialog: false,
|
||||||
|
),
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void filterLogs() async {
|
void filterLogs() async {
|
||||||
|
@ -161,47 +197,45 @@ class _LogsFiltersModalWidgetState extends State<LogsFiltersModalWidget> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
Widget content() {
|
||||||
padding: MediaQuery.of(context).viewInsets,
|
return Column(
|
||||||
child: Container(
|
mainAxisSize: MainAxisSize.min,
|
||||||
height: Platform.isIOS ? 446 : 430,
|
children: [
|
||||||
decoration: BoxDecoration(
|
Flexible(
|
||||||
color: Theme.of(context).dialogBackgroundColor,
|
child: SingleChildScrollView(
|
||||||
borderRadius: const BorderRadius.only(
|
child: Wrap(
|
||||||
topLeft: Radius.circular(28),
|
|
||||||
topRight: Radius.circular(28)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: ListView(
|
|
||||||
physics: (Platform.isIOS ? 416 : 400) < MediaQuery.of(context).size.height
|
|
||||||
? const NeverScrollableScrollPhysics()
|
|
||||||
: null,
|
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Row(
|
||||||
padding: const EdgeInsets.only(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
top: 24,
|
children: [
|
||||||
bottom: 16,
|
Column(
|
||||||
),
|
children: [
|
||||||
child: Icon(
|
Padding(
|
||||||
Icons.filter_list_rounded,
|
padding: const EdgeInsets.only(
|
||||||
size: 24,
|
top: 24,
|
||||||
color: Theme.of(context).listTileTheme.iconColor
|
bottom: 16,
|
||||||
),
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.filter_list_rounded,
|
||||||
|
size: 24,
|
||||||
|
color: Theme.of(context).listTileTheme.iconColor
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!.filters,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
height: 1.3,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Text(
|
|
||||||
AppLocalizations.of(context)!.filters,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
height: 1.3,
|
|
||||||
color: Theme.of(context).colorScheme.onSurface
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -233,7 +267,7 @@ class _LogsFiltersModalWidgetState extends State<LogsFiltersModalWidget> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
Container(height: 16),
|
||||||
CustomListTile(
|
CustomListTile(
|
||||||
title: AppLocalizations.of(context)!.client,
|
title: AppLocalizations.of(context)!.client,
|
||||||
subtitle: logsProvider.selectedClients != null
|
subtitle: logsProvider.selectedClients != null
|
||||||
|
@ -270,26 +304,55 @@ class _LogsFiltersModalWidgetState extends State<LogsFiltersModalWidget> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.all(24),
|
Padding(
|
||||||
child: Row(
|
padding: const EdgeInsets.all(24),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
child: Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
TextButton(
|
children: [
|
||||||
onPressed: resetFilters,
|
TextButton(
|
||||||
child: Text(AppLocalizations.of(context)!.resetFilters)
|
onPressed: resetFilters,
|
||||||
),
|
child: Text(AppLocalizations.of(context)!.resetFilters)
|
||||||
TextButton(
|
),
|
||||||
onPressed: () => filterLogs(),
|
TextButton(
|
||||||
child: Text(AppLocalizations.of(context)!.apply)
|
onPressed: () => filterLogs(),
|
||||||
),
|
child: Text(AppLocalizations.of(context)!.apply)
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
if (Platform.isIOS) const SizedBox(height: 16)
|
),
|
||||||
],
|
if (Platform.isIOS) const SizedBox(height: 16)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.dialog == true) {
|
||||||
|
return Padding(
|
||||||
|
padding: MediaQuery.of(context).viewInsets,
|
||||||
|
child: Dialog(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxWidth: 500
|
||||||
|
),
|
||||||
|
child: content()
|
||||||
|
)
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
|
else {
|
||||||
|
return Padding(
|
||||||
|
padding: MediaQuery.of(context).viewInsets,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).dialogBackgroundColor,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(28),
|
||||||
|
topRight: Radius.circular(28)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
child: content()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue