mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-20 05:49:12 +00:00
Created home top items reorder screen
This commit is contained in:
parent
d967399b64
commit
520a14fcda
8 changed files with 313 additions and 4 deletions
|
@ -655,5 +655,10 @@
|
|||
"quickFilters": "Quick filters",
|
||||
"searchDomainInternet": "Search domain on the Internet",
|
||||
"hideServerAddress": "Hide server address",
|
||||
"hideServerAddressDescription": "Hides the server address on the home screen"
|
||||
"hideServerAddressDescription": "Hides the server address on the home screen",
|
||||
"topItemsOrder": "Top items order",
|
||||
"topItemsOrderDescription": "Order the home screen top items lists",
|
||||
"topItemsReorderInfo": "Hold and swipe an item to reorder it.",
|
||||
"discardChanges": "Discard changes",
|
||||
"discardChangesDescription": "Are you sure you want to discard the changes?"
|
||||
}
|
|
@ -655,5 +655,10 @@
|
|||
"quickFilters": "Filtros rápidos",
|
||||
"searchDomainInternet": "Buscar dominio en internet",
|
||||
"hideServerAddress": "Ocultar dirección del servidor",
|
||||
"hideServerAddressDescription": "Oculta la dirección del servidor en la pantalla de inicio"
|
||||
"hideServerAddressDescription": "Oculta la dirección del servidor en la pantalla de inicio",
|
||||
"topItemsOrder": "Orden de los top",
|
||||
"topItemsOrderDescription": "Ordena las listas de top de elementos en la pantalla de inicio",
|
||||
"topItemsReorderInfo": "Mantén presionado y desliza un elemento para reordenarlo.",
|
||||
"discardChanges": "Descartar cambios",
|
||||
"discardChangesDescription": "¿Estás seguro de que deseas descartar los cambios realizados?"
|
||||
}
|
|
@ -374,7 +374,7 @@ class AppConfigProvider with ChangeNotifier {
|
|||
final updated = await updateConfigQuery(
|
||||
db: _dbInstance!,
|
||||
column: 'homeTopItemsOrder',
|
||||
value: jsonEncode(order)
|
||||
value: jsonEncode(List<String>.from(order.map((e) => e.name)))
|
||||
);
|
||||
if (updated == true) {
|
||||
_homeTopItemsOrder = order;
|
||||
|
|
|
@ -7,6 +7,8 @@ import 'package:provider/provider.dart';
|
|||
import 'package:store_checker/store_checker.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'package:adguard_home_manager/screens/settings/general_settings/reorderable_top_items_home.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
||||
import 'package:adguard_home_manager/widgets/section_label.dart';
|
||||
|
||||
|
@ -181,6 +183,14 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
|||
right: 10
|
||||
)
|
||||
),
|
||||
CustomListTile(
|
||||
icon: Icons.reorder_rounded,
|
||||
title: AppLocalizations.of(context)!.topItemsOrder,
|
||||
subtitle: AppLocalizations.of(context)!.topItemsOrderDescription,
|
||||
onTap: () => Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const ReorderableTopItemsHome()
|
||||
)),
|
||||
),
|
||||
SectionLabel(label: AppLocalizations.of(context)!.logs),
|
||||
CustomListTile(
|
||||
icon: Icons.timer_rounded,
|
|
@ -0,0 +1,280 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_reorderable_list/flutter_reorderable_list.dart' as reorderable_list_library;
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
||||
|
||||
import 'package:adguard_home_manager/constants/enums.dart';
|
||||
import 'package:adguard_home_manager/providers/app_config_provider.dart';
|
||||
|
||||
class ItemData {
|
||||
final HomeTopItems title;
|
||||
final Key key;
|
||||
|
||||
const ItemData({
|
||||
required this.title,
|
||||
required this.key
|
||||
});
|
||||
}
|
||||
|
||||
enum DraggingMode {
|
||||
iOS,
|
||||
android,
|
||||
}
|
||||
|
||||
class ReorderableTopItemsHome extends StatefulWidget {
|
||||
const ReorderableTopItemsHome({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ReorderableTopItemsHome> createState() => _ReorderableTopItemsHomeState();
|
||||
}
|
||||
|
||||
class _ReorderableTopItemsHomeState extends State<ReorderableTopItemsHome> {
|
||||
List<HomeTopItems> homeTopItemsList = [];
|
||||
List<HomeTopItems> persistHomeTopItemsList = [];
|
||||
List<ItemData> renderItems = [];
|
||||
|
||||
int _indexOfKey(Key key) {
|
||||
return renderItems.indexWhere((ItemData d) => d.key == key);
|
||||
}
|
||||
|
||||
bool _reorderCallback(Key item, Key newPosition) {
|
||||
int draggingIndex = _indexOfKey(item);
|
||||
int newPositionIndex = _indexOfKey(newPosition);
|
||||
|
||||
final draggedItem = renderItems[draggingIndex];
|
||||
|
||||
final List<HomeTopItems> reorderedItems = reorderEnumItems(draggingIndex, newPositionIndex);
|
||||
|
||||
setState(() {
|
||||
renderItems.removeAt(draggingIndex);
|
||||
renderItems.insert(newPositionIndex, draggedItem);
|
||||
homeTopItemsList = reorderedItems;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void _reorderDone(Key item) {
|
||||
renderItems[_indexOfKey(item)];
|
||||
setState(() => persistHomeTopItemsList = homeTopItemsList);
|
||||
}
|
||||
|
||||
List<HomeTopItems> reorderEnumItems(int oldIndex, int newIndex) {
|
||||
final List<HomeTopItems> list = [...homeTopItemsList];
|
||||
final HomeTopItems item = list.removeAt(oldIndex);
|
||||
list.insert(newIndex, item);
|
||||
return list;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context, listen: false);
|
||||
homeTopItemsList = appConfigProvider.homeTopItemsOrder;
|
||||
persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder;
|
||||
renderItems = appConfigProvider.homeTopItemsOrder.asMap().entries.map(
|
||||
(e) => ItemData(
|
||||
key: ValueKey(e.key),
|
||||
title: e.value,
|
||||
)
|
||||
).toList();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||
|
||||
Widget tile(HomeTopItems title) {
|
||||
switch (title) {
|
||||
case HomeTopItems.queriedDomains:
|
||||
return CustomListTile(
|
||||
title: AppLocalizations.of(context)!.topQueriedDomains,
|
||||
icon: Icons.install_desktop_outlined,
|
||||
padding: const EdgeInsets.all(16)
|
||||
);
|
||||
|
||||
case HomeTopItems.blockedDomains:
|
||||
return CustomListTile(
|
||||
title: AppLocalizations.of(context)!.topBlockedDomains,
|
||||
icon: Icons.block_rounded,
|
||||
padding: const EdgeInsets.all(16)
|
||||
);
|
||||
|
||||
case HomeTopItems.recurrentClients:
|
||||
return CustomListTile(
|
||||
title: AppLocalizations.of(context)!.topClients,
|
||||
icon: Icons.smartphone_rounded,
|
||||
padding: const EdgeInsets.all(16)
|
||||
);
|
||||
|
||||
default:
|
||||
return const SizedBox();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> onWillPopScope() async {
|
||||
if (!listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (dialogContext) => AlertDialog(
|
||||
title: Text(AppLocalizations.of(context)!.discardChanges),
|
||||
content: Text(AppLocalizations.of(context)!.discardChangesDescription),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(dialogContext);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(AppLocalizations.of(context)!.confirm)
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogContext),
|
||||
child: Text(AppLocalizations.of(context)!.cancel)
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: onWillPopScope,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context)!.topItemsOrder),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)
|
||||
? () => appConfigProvider.setHomeTopItemsOrder(homeTopItemsList)
|
||||
: null,
|
||||
icon: const Icon(Icons.save_rounded),
|
||||
tooltip: AppLocalizations.of(context)!.save,
|
||||
),
|
||||
const SizedBox(width: 8)
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Card(
|
||||
margin: const EdgeInsets.all(16),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.info_rounded,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Flexible(
|
||||
child: Text(AppLocalizations.of(context)!.topItemsReorderInfo)
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: reorderable_list_library.ReorderableList(
|
||||
onReorder: _reorderCallback,
|
||||
onReorderDone: _reorderDone,
|
||||
child: ListView.builder(
|
||||
itemBuilder: (context, index) => reorderable_list_library.ReorderableItem(
|
||||
key: renderItems[index].key,
|
||||
childBuilder: (context, state) => Item(
|
||||
tileWidget: tile(renderItems[index].title),
|
||||
isFirst: index == 0,
|
||||
isLast: index == renderItems.length - 1,
|
||||
state: state
|
||||
),
|
||||
),
|
||||
itemCount: renderItems.length,
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Item extends StatelessWidget {
|
||||
final Widget tileWidget;
|
||||
final bool isFirst;
|
||||
final bool isLast;
|
||||
final reorderable_list_library.ReorderableItemState state;
|
||||
|
||||
const Item({
|
||||
Key? key,
|
||||
required this.tileWidget,
|
||||
required this.isFirst,
|
||||
required this.isLast,
|
||||
required this.state,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
BoxDecoration decoration;
|
||||
|
||||
if (
|
||||
state == reorderable_list_library.ReorderableItemState.dragProxy ||
|
||||
state == reorderable_list_library.ReorderableItemState.dragProxyFinished
|
||||
) {
|
||||
decoration = BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface.withOpacity(0.7)
|
||||
);
|
||||
}
|
||||
else {
|
||||
bool placeholder = state == reorderable_list_library.ReorderableItemState.placeholder;
|
||||
decoration = BoxDecoration(
|
||||
border: Border(
|
||||
top: isFirst && !placeholder ? BorderSide(
|
||||
width: 1,
|
||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1)
|
||||
) : BorderSide.none,
|
||||
bottom: isLast && placeholder ? BorderSide.none : BorderSide(
|
||||
width: 1,
|
||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return reorderable_list_library.DelayedReorderableListener(
|
||||
child: Container(
|
||||
decoration: decoration,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Opacity(
|
||||
opacity: state == reorderable_list_library.ReorderableItemState.placeholder ? 0.0 : 1.0,
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: tileWidget
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import 'package:adguard_home_manager/screens/settings/dns/dns.dart';
|
|||
import 'package:adguard_home_manager/screens/settings/dns_rewrites/dns_rewrites.dart';
|
||||
import 'package:adguard_home_manager/screens/servers/servers.dart';
|
||||
import 'package:adguard_home_manager/screens/settings/advanced_setings.dart';
|
||||
import 'package:adguard_home_manager/screens/settings/general_settings.dart';
|
||||
import 'package:adguard_home_manager/screens/settings/general_settings/general_settings.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/custom_settings_tile.dart';
|
||||
import 'package:adguard_home_manager/widgets/section_label.dart';
|
||||
|
|
|
@ -267,6 +267,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
flutter_reorderable_list:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_reorderable_list
|
||||
sha256: "0400ef34fa00b7cac69f71efc92d7e49727f425bc1080180ebe70bf47618afe0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
flutter_split_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -72,6 +72,7 @@ dependencies:
|
|||
async: ^2.10.0
|
||||
sentry_flutter: ^7.9.0
|
||||
flutter_dotenv: ^5.0.2
|
||||
flutter_reorderable_list: ^1.3.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Add table
Reference in a new issue