mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-24 15:56:05 +00:00
Added show and hide top items
This commit is contained in:
parent
ed0bc65285
commit
3e152db6ac
7 changed files with 317 additions and 104 deletions
|
@ -769,5 +769,7 @@
|
|||
"editCustomRules": "Edit custom rules",
|
||||
"savingCustomRules": "Saving custom rules...",
|
||||
"customRulesUpdatedSuccessfully": "Custom rules updated successfully",
|
||||
"customRulesNotUpdated": "Custom rules could not be updated"
|
||||
"customRulesNotUpdated": "Custom rules could not be updated",
|
||||
"reorder": "Reorder",
|
||||
"showHide": "Show/hide"
|
||||
}
|
|
@ -769,5 +769,7 @@
|
|||
"editCustomRules": "Editar reglas personalizadas",
|
||||
"savingCustomRules": "Guardando reglas personalizadas...",
|
||||
"customRulesUpdatedSuccessfully": "Reglas personalizadas actualizadas correctamente",
|
||||
"customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas"
|
||||
"customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas",
|
||||
"reorder": "Reordenar",
|
||||
"showHide": "Mostrar/ocultar"
|
||||
}
|
|
@ -8,7 +8,7 @@ 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/screens/settings/general_settings/top_items_list/top_items_list_settings.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
||||
import 'package:adguard_home_manager/widgets/section_label.dart';
|
||||
|
@ -199,10 +199,10 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
|||
title: AppLocalizations.of(context)!.topItemsOrder,
|
||||
subtitle: AppLocalizations.of(context)!.topItemsOrderDescription,
|
||||
onTap: () => widget.splitView == true
|
||||
? SplitView.of(context).push(const ReorderableTopItemsHome())
|
||||
? SplitView.of(context).push(const TopItemsListSettings())
|
||||
: Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const ReorderableTopItemsHome()
|
||||
builder: (context) => const TopItemsListSettings()
|
||||
)
|
||||
)
|
||||
),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
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;
|
||||
|
@ -8,8 +7,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|||
|
||||
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
|
||||
|
||||
import 'package:adguard_home_manager/functions/desktop_mode.dart';
|
||||
import 'package:adguard_home_manager/functions/snackbar.dart';
|
||||
import 'package:adguard_home_manager/constants/enums.dart';
|
||||
import 'package:adguard_home_manager/providers/app_config_provider.dart';
|
||||
|
||||
|
@ -29,7 +26,14 @@ enum DraggingMode {
|
|||
}
|
||||
|
||||
class ReorderableTopItemsHome extends StatefulWidget {
|
||||
const ReorderableTopItemsHome({super.key});
|
||||
final List<HomeTopItems> persistHomeTopItems;
|
||||
final void Function(List<HomeTopItems> value) setPersistHomeTopItems;
|
||||
|
||||
const ReorderableTopItemsHome({
|
||||
super.key,
|
||||
required this.persistHomeTopItems,
|
||||
required this.setPersistHomeTopItems,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ReorderableTopItemsHome> createState() => _ReorderableTopItemsHomeState();
|
||||
|
@ -37,7 +41,6 @@ class ReorderableTopItemsHome extends StatefulWidget {
|
|||
|
||||
class _ReorderableTopItemsHomeState extends State<ReorderableTopItemsHome> {
|
||||
List<HomeTopItems> homeTopItemsList = [];
|
||||
List<HomeTopItems> persistHomeTopItemsList = [];
|
||||
List<_ItemData> renderItems = [];
|
||||
|
||||
int _indexOfKey(Key key) {
|
||||
|
@ -63,7 +66,7 @@ class _ReorderableTopItemsHomeState extends State<ReorderableTopItemsHome> {
|
|||
|
||||
void _reorderDone(Key item) {
|
||||
renderItems[_indexOfKey(item)];
|
||||
setState(() => persistHomeTopItemsList = homeTopItemsList);
|
||||
widget.setPersistHomeTopItems(homeTopItemsList);
|
||||
}
|
||||
|
||||
List<HomeTopItems> reorderEnumItems(int oldIndex, int newIndex) {
|
||||
|
@ -75,10 +78,8 @@ class _ReorderableTopItemsHomeState extends State<ReorderableTopItemsHome> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context, listen: false);
|
||||
homeTopItemsList = appConfigProvider.homeTopItemsOrder;
|
||||
persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder;
|
||||
renderItems = appConfigProvider.homeTopItemsOrder.asMap().entries.map(
|
||||
homeTopItemsList = widget.persistHomeTopItems;
|
||||
renderItems = widget.persistHomeTopItems.asMap().entries.map(
|
||||
(e) => _ItemData(
|
||||
key: ValueKey(e.key),
|
||||
title: e.value,
|
||||
|
@ -136,99 +137,80 @@ class _ReorderableTopItemsHomeState extends State<ReorderableTopItemsHome> {
|
|||
}
|
||||
}
|
||||
|
||||
void saveSettings() async {
|
||||
final result = await appConfigProvider.setHomeTopItemsOrder(homeTopItemsList);
|
||||
if (!mounted) return;
|
||||
if (result == true) {
|
||||
showSnacbkar(
|
||||
appConfigProvider: appConfigProvider,
|
||||
label: AppLocalizations.of(context)!.settingsSaved,
|
||||
color: Colors.green
|
||||
);
|
||||
}
|
||||
else {
|
||||
showSnacbkar(
|
||||
appConfigProvider: appConfigProvider,
|
||||
label: AppLocalizations.of(context)!.settingsNotSaved,
|
||||
color: Colors.red
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final draggingMode = Platform.isAndroid
|
||||
? DraggingMode.android
|
||||
: DraggingMode.iOS;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context)!.topItemsOrder),
|
||||
surfaceTintColor: isDesktop(width) ? Colors.transparent : null,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)
|
||||
? () => saveSettings()
|
||||
: 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.ReorderableList(
|
||||
onReorder: _reorderCallback,
|
||||
onReorderDone: _reorderDone,
|
||||
child: ListView.builder(
|
||||
itemBuilder: (context, index) => reorderable_list.ReorderableItem(
|
||||
key: renderItems[index].key,
|
||||
childBuilder: (context, state) {
|
||||
if (draggingMode == DraggingMode.android) {
|
||||
return reorderable_list.DelayedReorderableListener(
|
||||
child: _Tile(
|
||||
draggingMode: draggingMode,
|
||||
isFirst: index == 0,
|
||||
isLast: index == renderItems.length - 1,
|
||||
state: state,
|
||||
tileWidget: tile(renderItems[index].title),
|
||||
return SafeArea(
|
||||
top: false,
|
||||
bottom: true,
|
||||
child: Builder(
|
||||
builder: (context) => CustomScrollView(
|
||||
slivers: [
|
||||
SliverOverlapInjector(
|
||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||
),
|
||||
SliverList.list(
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
return _Tile(
|
||||
draggingMode: draggingMode,
|
||||
isFirst: index == 0,
|
||||
isLast: index == renderItems.length - 1,
|
||||
state: state,
|
||||
tileWidget: tile(renderItems[index].title),
|
||||
);
|
||||
}
|
||||
},
|
||||
const SizedBox(width: 16),
|
||||
Flexible(
|
||||
child: Text(AppLocalizations.of(context)!.topItemsReorderInfo)
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
itemCount: renderItems.length,
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
reorderable_list.ReorderableList(
|
||||
onReorder: _reorderCallback,
|
||||
onReorderDone: _reorderDone,
|
||||
child: ListView.builder(
|
||||
primary: false,
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.only(top: 0),
|
||||
itemBuilder: (context, index) => reorderable_list.ReorderableItem(
|
||||
key: renderItems[index].key,
|
||||
childBuilder: (context, state) {
|
||||
if (draggingMode == DraggingMode.android) {
|
||||
return reorderable_list.DelayedReorderableListener(
|
||||
child: _Tile(
|
||||
draggingMode: draggingMode,
|
||||
isFirst: index == 0,
|
||||
isLast: index == renderItems.length - 1,
|
||||
state: state,
|
||||
tileWidget: tile(renderItems[index].title),
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
return _Tile(
|
||||
draggingMode: draggingMode,
|
||||
isFirst: index == 0,
|
||||
isLast: index == renderItems.length - 1,
|
||||
state: state,
|
||||
tileWidget: tile(renderItems[index].title),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
itemCount: renderItems.length,
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart';
|
||||
import 'package:adguard_home_manager/constants/enums.dart';
|
||||
|
||||
class ShowHideTopItemsList extends StatelessWidget {
|
||||
final List<HomeTopItems> enabledHomeTopItems;
|
||||
final void Function(List<HomeTopItems>) setEnabledHomeTopItems;
|
||||
|
||||
const ShowHideTopItemsList({
|
||||
super.key,
|
||||
required this.enabledHomeTopItems,
|
||||
required this.setEnabledHomeTopItems,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const padding = EdgeInsets.symmetric(horizontal: 16, vertical: 8);
|
||||
|
||||
void updateValue(HomeTopItems value, bool newStatus) {
|
||||
if (newStatus == true) {
|
||||
setEnabledHomeTopItems([
|
||||
...enabledHomeTopItems,
|
||||
value
|
||||
]);
|
||||
}
|
||||
else {
|
||||
setEnabledHomeTopItems(enabledHomeTopItems.where((e) => e != value).toList());
|
||||
}
|
||||
}
|
||||
|
||||
return SafeArea(
|
||||
top: false,
|
||||
bottom: true,
|
||||
child: Builder(
|
||||
builder: (context) => CustomScrollView(
|
||||
slivers: [
|
||||
SliverOverlapInjector(
|
||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||
),
|
||||
SliverList.list(
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
CustomSwitchListTile(
|
||||
value: enabledHomeTopItems.contains(HomeTopItems.queriedDomains),
|
||||
onChanged: (v) => updateValue(HomeTopItems.queriedDomains, v),
|
||||
title: AppLocalizations.of(context)!.topQueriedDomains,
|
||||
leadingIcon: Icons.install_desktop_outlined,
|
||||
padding: padding,
|
||||
),
|
||||
CustomSwitchListTile(
|
||||
value: enabledHomeTopItems.contains(HomeTopItems.blockedDomains),
|
||||
onChanged: (v) => updateValue(HomeTopItems.blockedDomains, v),
|
||||
title: AppLocalizations.of(context)!.topBlockedDomains,
|
||||
leadingIcon: Icons.block_rounded,
|
||||
padding: padding,
|
||||
),
|
||||
CustomSwitchListTile(
|
||||
value: enabledHomeTopItems.contains(HomeTopItems.recurrentClients),
|
||||
onChanged: (v) => updateValue(HomeTopItems.recurrentClients, v),
|
||||
title: AppLocalizations.of(context)!.topClients,
|
||||
leadingIcon: Icons.smartphone_rounded,
|
||||
padding: padding,
|
||||
),
|
||||
CustomSwitchListTile(
|
||||
value: enabledHomeTopItems.contains(HomeTopItems.topUpstreams),
|
||||
onChanged: (v) => updateValue(HomeTopItems.topUpstreams, v),
|
||||
title: AppLocalizations.of(context)!.topUpstreams,
|
||||
leadingIcon: Icons.upload_file_rounded,
|
||||
padding: padding,
|
||||
),
|
||||
CustomSwitchListTile(
|
||||
value: enabledHomeTopItems.contains(HomeTopItems.avgUpstreamResponseTime),
|
||||
onChanged: (v) => updateValue(HomeTopItems.avgUpstreamResponseTime, v),
|
||||
title: AppLocalizations.of(context)!.averageUpstreamResponseTime,
|
||||
leadingIcon: Icons.timer_rounded,
|
||||
padding: padding,
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'package:adguard_home_manager/screens/settings/general_settings/top_items_list/show_hide_top_items_list.dart';
|
||||
import 'package:adguard_home_manager/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart';
|
||||
|
||||
import 'package:adguard_home_manager/constants/enums.dart';
|
||||
import 'package:adguard_home_manager/functions/desktop_mode.dart';
|
||||
import 'package:adguard_home_manager/functions/snackbar.dart';
|
||||
import 'package:adguard_home_manager/providers/app_config_provider.dart';
|
||||
|
||||
class TopItemsListSettings extends StatefulWidget {
|
||||
const TopItemsListSettings({super.key});
|
||||
|
||||
@override
|
||||
State<TopItemsListSettings> createState() => _TopItemsListSettingsState();
|
||||
}
|
||||
|
||||
class _TopItemsListSettingsState extends State<TopItemsListSettings> with TickerProviderStateMixin {
|
||||
late TabController _tabController;
|
||||
|
||||
List<HomeTopItems> persistHomeTopItemsList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context, listen: false);
|
||||
persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder;
|
||||
|
||||
super.initState();
|
||||
|
||||
_tabController = TabController(length: 2, vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
void saveSettings() async {
|
||||
final result = await appConfigProvider.setHomeTopItemsOrder(persistHomeTopItemsList);
|
||||
if (!context.mounted) return;
|
||||
if (result == true) {
|
||||
showSnacbkar(
|
||||
appConfigProvider: appConfigProvider,
|
||||
label: AppLocalizations.of(context)!.settingsSaved,
|
||||
color: Colors.green
|
||||
);
|
||||
}
|
||||
else {
|
||||
showSnacbkar(
|
||||
appConfigProvider: appConfigProvider,
|
||||
label: AppLocalizations.of(context)!.settingsNotSaved,
|
||||
color: Colors.red
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: DefaultTabController(
|
||||
length: 2,
|
||||
child: NestedScrollView(
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||
SliverOverlapAbsorber(
|
||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||
sliver: SliverAppBar(
|
||||
pinned: true,
|
||||
floating: true,
|
||||
centerTitle: false,
|
||||
forceElevated: innerBoxIsScrolled,
|
||||
surfaceTintColor: isDesktop(width) ? Colors.transparent : null,
|
||||
title: Text(AppLocalizations.of(context)!.topItemsOrder),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)
|
||||
? () => saveSettings()
|
||||
: null,
|
||||
icon: const Icon(Icons.save_rounded),
|
||||
tooltip: AppLocalizations.of(context)!.save,
|
||||
),
|
||||
const SizedBox(width: 8)
|
||||
],
|
||||
bottom: TabBar(
|
||||
controller: _tabController,
|
||||
unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.reorder_rounded),
|
||||
const SizedBox(width: 8),
|
||||
Text(AppLocalizations.of(context)!.reorder)
|
||||
],
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.remove_red_eye_rounded),
|
||||
const SizedBox(width: 8),
|
||||
Text(AppLocalizations.of(context)!.showHide)
|
||||
],
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
body: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
ReorderableTopItemsHome(
|
||||
persistHomeTopItems: persistHomeTopItemsList,
|
||||
setPersistHomeTopItems: (v) => setState(() => persistHomeTopItemsList = v),
|
||||
),
|
||||
ShowHideTopItemsList(
|
||||
enabledHomeTopItems: persistHomeTopItemsList,
|
||||
setEnabledHomeTopItems: (v) => setState(() => persistHomeTopItemsList = v),
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,16 +7,18 @@ class CustomSwitchListTile extends StatelessWidget {
|
|||
final String? subtitle;
|
||||
final bool? disabled;
|
||||
final EdgeInsets? padding;
|
||||
final IconData? leadingIcon;
|
||||
|
||||
const CustomSwitchListTile({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
required this.title,
|
||||
this.disabled,
|
||||
this.subtitle,
|
||||
this.padding
|
||||
}) : super(key: key);
|
||||
this.padding,
|
||||
this.leadingIcon,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -33,6 +35,13 @@ class CustomSwitchListTile extends StatelessWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (leadingIcon != null) ...[
|
||||
Icon(
|
||||
leadingIcon,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
Loading…
Add table
Reference in a new issue