diff --git a/lib/models/applied_filters.dart b/lib/models/applied_filters.dart index 2b60e716..f4ef1ee5 100644 --- a/lib/models/applied_filters.dart +++ b/lib/models/applied_filters.dart @@ -1,7 +1,7 @@ class AppliedFiters { String selectedResultStatus = 'all'; String? searchText; - List? clients; + List clients; AppliedFiters({ required this.selectedResultStatus, diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index 63e81cdc..cba46c0c 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -30,7 +30,7 @@ class LogsProvider with ChangeNotifier { AppliedFiters _appliedFilters = AppliedFiters( selectedResultStatus: 'all', searchText: null, - clients: null + clients: [] ); LoadStatus get loadStatus { @@ -177,18 +177,18 @@ class LogsProvider with ChangeNotifier { if (loadingMore != null && loadingMore == true && logsData != null) { LogsData newLogsData = result.content; newLogsData.data = [...logsData!.data, ...(result.content as LogsData).data]; - if (appliedFilters.clients != null) { + if (appliedFilters.clients.isNotEmpty) { newLogsData.data = newLogsData.data.where( - (item) => appliedFilters.clients!.contains(item.client) + (item) => appliedFilters.clients.contains(item.client) ).toList(); } _logsData = newLogsData; } else { LogsData newLogsData = result.content; - if (appliedFilters.clients != null) { + if (appliedFilters.clients.isNotEmpty) { newLogsData.data = newLogsData.data.where( - (item) => appliedFilters.clients!.contains(item.client) + (item) => appliedFilters.clients.contains(item.client) ).toList(); } _logsData = newLogsData; @@ -217,7 +217,7 @@ class LogsProvider with ChangeNotifier { _appliedFilters = AppliedFiters( selectedResultStatus: 'all', searchText: null, - clients: null + clients: [] ); if (result.successful == true) { @@ -254,9 +254,9 @@ class LogsProvider with ChangeNotifier { if (result.successful == true) { LogsData newLogsData = result.content as LogsData; - if (appliedFilters.clients != null) { + if (appliedFilters.clients.isNotEmpty) { newLogsData.data = newLogsData.data.where( - (item) => appliedFilters.clients!.contains(item.client) + (item) => appliedFilters.clients.contains(item.client) ).toList(); } _logsData = newLogsData; diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart index 758a0b68..7c24bd3f 100644 --- a/lib/screens/home/top_items/top_items_lists.dart +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -51,7 +51,7 @@ class TopItemsLists extends StatelessWidget { AppliedFiters( selectedResultStatus: 'all', searchText: value, - clients: null + clients: [] ) ); appConfigProvider.setSelectedScreen(2); diff --git a/lib/screens/logs/filters/filter_status_modal.dart b/lib/screens/logs/filters/filter_status_modal.dart index c08d9a87..d4e41555 100644 --- a/lib/screens/logs/filters/filter_status_modal.dart +++ b/lib/screens/logs/filters/filter_status_modal.dart @@ -1,9 +1,11 @@ -import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; + import 'package:adguard_home_manager/providers/logs_provider.dart'; class FilterStatusModal extends StatefulWidget { @@ -33,169 +35,141 @@ class _FilterStatusModalState extends State { Widget build(BuildContext context) { final logsProvider = Provider.of(context); - void apply() async { - logsProvider.setSelectedResultStatus(value: selectedResultStatus); - - Navigator.pop(context); - } - if (widget.dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 400 ), - child: _Content( - onApply: apply, - updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), - selectedResultStatus: selectedResultStatus, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.only(top: 16, left: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + CloseButton( + onPressed: () => Navigator.pop(context), + ), + const SizedBox(width: 12), + Text( + AppLocalizations.of(context)!.responseStatus, + style: const TextStyle( + fontSize: 22 + ), + ) + ], + ), + ), + Container(height: 16), + _ItemsList( + selectedResultStatus: logsProvider.selectedResultStatus, + updateSelectedResultStatus: (v) => logsProvider.setSelectedResultStatus(value: v), + ), + Container(height: 16) + ], + ), + ), + ), + ], ) ), ); } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor + return SizedBox( + height: 700, + child: ListBottomSheet( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.responseStatus, + initialChildSize: 1, + minChildSize: 0.5, + children: [ + _ItemsList( + selectedResultStatus: logsProvider.selectedResultStatus, + updateSelectedResultStatus: (v) => logsProvider.setSelectedResultStatus(value: v), + ) + ] ), - child: SafeArea( - child: _Content( - onApply: apply, - updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), - selectedResultStatus: selectedResultStatus, - ), - ) ); } } } -class _Content extends StatelessWidget { +class _ItemsList extends StatelessWidget { final String selectedResultStatus; final void Function(String) updateSelectedResultStatus; - final void Function() onApply; - const _Content({ + const _ItemsList({ required this.selectedResultStatus, - required this.updateSelectedResultStatus, - required this.onApply, + required this.updateSelectedResultStatus }); @override Widget build(BuildContext context) { return Column( - mainAxisSize: MainAxisSize.min, children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.responseStatus, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ) - ], - ), - Container(height: 16), - _Item( - selectedResultStatus: selectedResultStatus, - id: "all", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.all, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "filtered", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.filtered, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "processed", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "whitelisted", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedWhitelistRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "blocked", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blocked, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "blocked_safebrowsing", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "blocked_parental", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedParentalRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "safe_search", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeSearchRow, - onChanged: updateSelectedResultStatus - ), - ], - ), - ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "all", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.all, + onChanged: updateSelectedResultStatus ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: onApply, - child: Text(AppLocalizations.of(context)!.apply) - ) - ], - ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "filtered", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.filtered, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "processed", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "whitelisted", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedWhitelistRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blocked, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked_safebrowsing", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked_parental", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedParentalRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "safe_search", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeSearchRow, + onChanged: updateSelectedResultStatus ), - if (Platform.isIOS) const SizedBox(height: 16) ], ); } diff --git a/lib/screens/logs/filters/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart index 9f776663..b02dbd2e 100644 --- a/lib/screens/logs/filters/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -82,10 +82,9 @@ class _FiltersList extends StatelessWidget { final void Function() onClearSearch; const _FiltersList({ - Key? key, required this.searchController, required this.onClearSearch, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -125,7 +124,8 @@ class _FiltersList extends StatelessWidget { dialog: false, ), isScrollControlled: true, - backgroundColor: Colors.transparent + backgroundColor: Colors.transparent, + useSafeArea: true ); } } diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 144a55e3..01a870c4 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -70,8 +70,6 @@ class LogsListAppBar extends StatelessWidget { forceElevated: innerBoxIsScrolled, surfaceTintColor: isDesktop(width) ? Colors.transparent : null, title: Text(AppLocalizations.of(context)!.logs), - expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? 170 : null, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) IconButton( onPressed: () => logsProvider.fetchLogs(inOffset: 0), @@ -87,7 +85,7 @@ class LogsListAppBar extends StatelessWidget { : const SizedBox(), const SizedBox(width: 5), ], - bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients.isNotEmpty ? PreferredSize( preferredSize: const Size(double.maxFinite, 70), child: Container( @@ -172,7 +170,7 @@ class LogsListAppBar extends StatelessWidget { }, ), ], - if (logsProvider.appliedFilters.clients != null) ...[ + if (logsProvider.appliedFilters.clients.isNotEmpty) ...[ const SizedBox(width: 15), Chip( avatar: const Icon( @@ -181,9 +179,9 @@ class LogsListAppBar extends StatelessWidget { label: Row( children: [ Text( - logsProvider.appliedFilters.clients!.length == 1 - ? logsProvider.appliedFilters.clients![0] - : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", + logsProvider.appliedFilters.clients.length == 1 + ? logsProvider.appliedFilters.clients[0] + : "${logsProvider.appliedFilters.clients.length} ${AppLocalizations.of(context)!.clients}", ), ], ), @@ -196,7 +194,7 @@ class LogsListAppBar extends StatelessWidget { AppliedFiters( selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, searchText: logsProvider.appliedFilters.searchText, - clients: null + clients: [] ) ); logsProvider.setSelectedClients(null); diff --git a/lib/widgets/list_bottom_sheet.dart b/lib/widgets/list_bottom_sheet.dart index 2f8bd03e..219df8ce 100644 --- a/lib/widgets/list_bottom_sheet.dart +++ b/lib/widgets/list_bottom_sheet.dart @@ -4,12 +4,18 @@ class ListBottomSheet extends StatelessWidget { final IconData icon; final String title; final List children; + final double? initialChildSize; + final double? minChildSize; + final double? maxChildSize; const ListBottomSheet({ super.key, required this.icon, required this.title, - required this.children + required this.children, + this.initialChildSize, + this.maxChildSize, + this.minChildSize, }); @override @@ -17,9 +23,9 @@ class ListBottomSheet extends StatelessWidget { return GestureDetector( onTap: () => Navigator.of(context).pop(), child: DraggableScrollableSheet( - initialChildSize: 0.6, - minChildSize: 0.3, - maxChildSize: 1, + initialChildSize: initialChildSize ?? 0.6, + minChildSize: minChildSize ?? 0.3, + maxChildSize: maxChildSize ?? 1, builder: (context, controller) { return Container( decoration: BoxDecoration( diff --git a/pubspec.yaml b/pubspec.yaml index 2d641947..aa5c3835 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.0+125 +version: 2.15.1+126 environment: sdk: '>=2.18.1 <3.0.0'