Optimized logs

This commit is contained in:
Juan Gilsanz Polo 2023-05-01 15:58:06 +02:00
parent aacf68569d
commit 578e606b83
8 changed files with 1043 additions and 626 deletions

View file

@ -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..."
} }

View file

@ -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..."
} }

View file

@ -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()
),
);
}
} }
} }

View file

@ -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()
);
}
} }
} }

View file

@ -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() ],
], ),
), ),
), ),
), );
); }
} }
} }

View file

@ -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();
}
} }
} }

View file

@ -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()
);
}
} }
} }

View file

@ -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()
),
);
}
} }
} }