Added sorting options custom rules

This commit is contained in:
Juan Gilsanz Polo 2025-01-21 21:54:04 +01:00
parent 47b5313bf3
commit 10ff5183f1
5 changed files with 161 additions and 8 deletions

View file

@ -1,2 +1,3 @@
enum LoadStatus { loading, loaded, error }
enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime }
enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime }
enum CustomRulesSorting { topBottom, bottomTop }

View file

@ -801,5 +801,7 @@
"applicationDetails": "Application details",
"applicationDetailsDescription": "App repository, stores where it's available, and more",
"myOtherApps": "Check my other apps",
"myOtherAppsDescription": "Created by JGeek00"
"myOtherAppsDescription": "Created by JGeek00",
"topToBottom": "From top to bottom",
"bottomToTop": "From bottom to top"
}

View file

@ -801,5 +801,7 @@
"applicationDetails": "Detalles de la aplicación",
"applicationDetailsDescription": "Repositorio de la app, tiendas donde está disponible, y más",
"myOtherApps": "Comprueba mis otras apps",
"myOtherAppsDescription": "Creadas por JGeek00"
"myOtherAppsDescription": "Creadas por JGeek00",
"topToBottom": "Desde arriba hacia abajo",
"bottomToTop": "Desde abajo hacia arriba"
}

View file

@ -6,6 +6,7 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/filters/add_button.dart';
import 'package:adguard_home_manager/screens/filters/modals/custom_rules/sort_rules.dart';
import 'package:adguard_home_manager/widgets/tab_content_list.dart';
import 'package:adguard_home_manager/functions/snackbar.dart';
@ -34,6 +35,8 @@ class CustomRulesList extends StatefulWidget {
class _CustomRulesListState extends State<CustomRulesList> {
late bool isVisible;
CustomRulesSorting _sortingMethod = CustomRulesSorting.topBottom;
@override
initState(){
super.initState();
@ -60,6 +63,8 @@ class _CustomRulesListState extends State<CustomRulesList> {
final filteringProvider = Provider.of<FilteringProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
final renderData = _sortingMethod == CustomRulesSorting.bottomTop ? widget.data.reversed.toList() : widget.data.toList();
bool checkIfComment(String value) {
final regex = RegExp(r'^(!|#).*$');
if (regex.hasMatch(value)) {
@ -104,6 +109,16 @@ class _CustomRulesListState extends State<CustomRulesList> {
}
}
void showSortingMethodModal() {
showDialog(
context: context,
builder: (ctx) => SortCustomRulesModal(
sortingMethod: _sortingMethod,
onSelect: (value) => setState(() => _sortingMethod = value),
),
);
}
return CustomTabContentList(
loadingGenerator: () => SizedBox(
width: double.maxFinite,
@ -124,10 +139,10 @@ class _CustomRulesListState extends State<CustomRulesList> {
],
),
),
itemsCount: widget.data.length,
itemsCount: renderData.length,
contentWidget: (index) => ListTile(
title: Text(
widget.data[index],
renderData[index],
style: TextStyle(
color: checkIfComment(widget.data[index]) == true
? Theme.of(context).colorScheme.onSurface.withOpacity(0.6)
@ -135,9 +150,9 @@ class _CustomRulesListState extends State<CustomRulesList> {
fontWeight: FontWeight.normal,
),
),
subtitle: generateSubtitle(widget.data[index]),
subtitle: generateSubtitle(renderData[index]),
trailing: IconButton(
onPressed: () => widget.onRemoveCustomRule(widget.data[index]),
onPressed: () => widget.onRemoveCustomRule(renderData[index]),
icon: const Icon(Icons.delete)
),
),
@ -212,6 +227,11 @@ class _CustomRulesListState extends State<CustomRulesList> {
},
fab: Column(
children: [
FloatingActionButton.small(
onPressed: showSortingMethodModal,
child: Icon(Icons.sort_rounded),
),
const SizedBox(height: 16),
AddFiltersButton(
type: 'edit_custom_rule',
widget: (fn) => FloatingActionButton.small(
@ -229,7 +249,7 @@ class _CustomRulesListState extends State<CustomRulesList> {
),
],
),
heightFabHidden: -120,
heightFabHidden: -180,
fabVisible: isVisible,
);
}

View file

@ -0,0 +1,128 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/constants/enums.dart';
class SortCustomRulesModal extends StatelessWidget {
final CustomRulesSorting sortingMethod;
final void Function(CustomRulesSorting) onSelect;
const SortCustomRulesModal({
super.key,
required this.sortingMethod,
required this.onSelect,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: const EdgeInsets.symmetric(vertical: 16),
scrollable: true,
title: Column(
children: [
Icon(
Icons.sort_rounded,
size: 24,
color: Theme.of(context).listTileTheme.iconColor
),
const SizedBox(height: 16),
Text(
AppLocalizations.of(context)!.sortingOptions,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface
),
)
],
),
content: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 500
),
child: Column(
children: [
_CustomListTileDialog(
title: AppLocalizations.of(context)!.topToBottom,
icon: Icons.arrow_downward_rounded,
onTap: () {
Navigator.pop(context);
onSelect(CustomRulesSorting.topBottom);
},
isSelected: sortingMethod == CustomRulesSorting.topBottom
),
_CustomListTileDialog(
title: AppLocalizations.of(context)!.bottomToTop,
icon: Icons.arrow_upward_rounded,
onTap: () {
Navigator.pop(context);
onSelect(CustomRulesSorting.bottomTop);
},
isSelected: sortingMethod == CustomRulesSorting.bottomTop
),
]
),
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.close)
)
],
)
],
);
}
}
class _CustomListTileDialog extends StatelessWidget {
final String title;
final IconData? icon;
final void Function()? onTap;
final bool isSelected;
const _CustomListTileDialog({
required this.title,
required this.icon,
required this.onTap,
required this.isSelected,
});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Icon(
icon,
color: Theme.of(context).colorScheme.onSurface,
),
const SizedBox(width: 24),
Flexible(
child: Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface,
),
),
),
const SizedBox(width: 24),
Icon(
isSelected == true ? Icons.radio_button_checked_rounded : Icons.radio_button_unchecked_rounded,
color: Theme.of(context).colorScheme.primary,
)
],
),
),
),
);
}
}