More UI updates

This commit is contained in:
Juan Gilsanz Polo 2022-11-04 17:04:25 +01:00
parent bbf528e369
commit 55010f8896
21 changed files with 581 additions and 560 deletions

View file

@ -116,8 +116,8 @@ class _ClientScreenState extends State<ClientScreen> {
Widget sectionLabel(String label) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 30,
horizontal: 20
vertical: 24,
horizontal: 24
),
child: Text(
label,
@ -213,7 +213,7 @@ class _ClientScreenState extends State<ClientScreen> {
: null,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30,
horizontal: 42,
vertical: 5
),
child: Row(
@ -221,8 +221,9 @@ class _ClientScreenState extends State<ClientScreen> {
children: [
Text(
label,
style: const TextStyle(
fontSize: 15
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface,
),
),
useGlobalSettingsFiltering == false
@ -236,7 +237,7 @@ class _ClientScreenState extends State<ClientScreen> {
child: Text(
"Global",
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurface,
),
),
)
@ -290,9 +291,9 @@ class _ClientScreenState extends State<ClientScreen> {
),
body: ListView(
children: [
const SizedBox(height: 20),
const SizedBox(height: 24),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
enabled: widget.client != null ? false : true,
controller: nameController,
@ -315,30 +316,32 @@ class _ClientScreenState extends State<ClientScreen> {
onTap: editMode == true ? () => openTagsModal() : null,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 20
vertical: 0, horizontal: 24
),
child: Row(
children: [
const Icon(
Icon(
Icons.label_rounded,
color: Theme.of(context).colorScheme.onSurfaceVariant
),
const SizedBox(width: 20),
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.selectTags,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface
),
),
const SizedBox(height: 5),
const SizedBox(height: 3),
Text(
selectedTags.isNotEmpty
? "${selectedTags.length} ${AppLocalizations.of(context)!.tagsSelected}"
: AppLocalizations.of(context)!.noTagsSelected,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant
),
)
],
@ -365,9 +368,7 @@ class _ClientScreenState extends State<ClientScreen> {
],
),
if (identifiersControllers.isNotEmpty) ...identifiersControllers.map((controller) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Padding(
padding: const EdgeInsets.only(bottom: 20),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
@ -402,7 +403,6 @@ class _ClientScreenState extends State<ClientScreen> {
]
],
),
),
)).toList(),
if (identifiersControllers.isEmpty) Container(
padding: const EdgeInsets.only(top: 10),
@ -417,7 +417,7 @@ class _ClientScreenState extends State<ClientScreen> {
),
sectionLabel(AppLocalizations.of(context)!.settings),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Material(
color: Theme.of(context).primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(28),
@ -436,8 +436,9 @@ class _ClientScreenState extends State<ClientScreen> {
children: [
Text(
AppLocalizations.of(context)!.useGlobalSettings,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface
),
),
Switch(
@ -484,7 +485,7 @@ class _ClientScreenState extends State<ClientScreen> {
),
sectionLabel(AppLocalizations.of(context)!.blockedServices),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Material(
color: Theme.of(context).primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(28),
@ -503,8 +504,9 @@ class _ClientScreenState extends State<ClientScreen> {
children: [
Text(
AppLocalizations.of(context)!.useGlobalSettings,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurface
),
),
Switch(
@ -531,17 +533,17 @@ class _ClientScreenState extends State<ClientScreen> {
: null,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 20
vertical: 8, horizontal: 24
),
child: Row(
children: [
Icon(
Icons.public,
color: useGlobalSettingsServices == false
? null
: Colors.grey,
? Theme.of(context).colorScheme.onSurface
: Theme.of(context).colorScheme.onSurface.withOpacity(0.38),
),
const SizedBox(width: 20),
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -550,8 +552,8 @@ class _ClientScreenState extends State<ClientScreen> {
style: TextStyle(
fontSize: 16,
color: useGlobalSettingsServices == false
? null
: Theme.of(context).listTileTheme.iconColor,
? Theme.of(context).colorScheme.onSurface
: Theme.of(context).colorScheme.onSurface.withOpacity(0.38),
),
),
if (useGlobalSettingsServices == false) ...[
@ -561,7 +563,7 @@ class _ClientScreenState extends State<ClientScreen> {
? "${blockedServices.length} ${AppLocalizations.of(context)!.servicesBlocked}"
: AppLocalizations.of(context)!.noBlockedServicesSelected,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant
),
)
]

View file

@ -69,9 +69,10 @@ class ClientsFab extends StatelessWidget {
return FloatingActionButton(
onPressed: () => openAddClient(),
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
child: Icon(
Icons.add,
color: Theme.of(context).primaryColor.computeLuminance() > 0.5 ? Colors.black : Colors.white,
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
);
}

View file

@ -45,13 +45,21 @@ class _ServicesModalState extends State<ServicesModal> {
scrollable: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 0,
vertical: 20
vertical: 16
),
title: Column(
children: [
const Icon(Icons.public),
const SizedBox(height: 20),
Text(AppLocalizations.of(context)!.services)
Icon(
Icons.public,
color: Theme.of(context).colorScheme.onSurface,
),
const SizedBox(height: 16),
Text(
AppLocalizations.of(context)!.services,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
),
)
],
),
content: SizedBox(
@ -65,8 +73,9 @@ class _ServicesModalState extends State<ServicesModal> {
padding: const EdgeInsets.only(left: 10),
child: Text(
services[index]['label']!,
style: const TextStyle(
fontWeight: FontWeight.normal
style: TextStyle(
fontWeight: FontWeight.normal,
color: Theme.of(context).colorScheme.onSurface
),
),
),
@ -95,7 +104,7 @@ class _ServicesModalState extends State<ServicesModal> {
style: TextStyle(
color: blockedServices.isNotEmpty
? Theme.of(context).primaryColor
: Colors.grey
: Theme.of(context).colorScheme.onSurface.withOpacity(0.38)
),
)
),

View file

@ -45,13 +45,21 @@ class _TagsModalState extends State<TagsModal> {
scrollable: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 0,
vertical: 20
vertical: 16
),
title: Column(
children: [
const Icon(Icons.label_rounded),
const SizedBox(height: 20),
Text(AppLocalizations.of(context)!.tags)
Icon(
Icons.label_rounded,
color: Theme.of(context).colorScheme.onSurface
),
const SizedBox(height: 16),
Text(
AppLocalizations.of(context)!.tags,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface
),
)
],
),
content: SizedBox(
@ -63,8 +71,9 @@ class _TagsModalState extends State<TagsModal> {
itemBuilder: (context, index) => CheckboxListTile(
title: Text(
widget.tags[index],
style: const TextStyle(
fontWeight: FontWeight.normal
style: TextStyle(
fontWeight: FontWeight.normal,
color: Theme.of(context).colorScheme.onSurface
),
),
value: selectedTags.contains(widget.tags[index]),
@ -92,7 +101,7 @@ class _TagsModalState extends State<TagsModal> {
style: TextStyle(
color: selectedTags.isNotEmpty
? Theme.of(context).primaryColor
: Colors.grey
: Theme.of(context).colorScheme.onSurface.withOpacity(0.38)
),
)
),

View file

@ -69,7 +69,7 @@ class _AddListModalState extends State<AddListModal> {
return Padding(
padding: MediaQuery.of(context).viewInsets,
child: Container(
height: 410,
height: 370,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(28),
@ -86,15 +86,16 @@ class _AddListModalState extends State<AddListModal> {
: null,
children: [
Padding(
padding: const EdgeInsets.only(top: 28),
padding: const EdgeInsets.only(top: 24),
child: Icon(
widget.type == 'whitelist'
? Icons.verified_user_rounded
: Icons.gpp_bad_rounded,
size: 26,
size: 24,
color: Theme.of(context).colorScheme.secondary,
),
),
const SizedBox(height: 20),
const SizedBox(height: 16),
Text(
widget.list != null
? widget.type == 'whitelist'
@ -104,13 +105,14 @@ class _AddListModalState extends State<AddListModal> {
? AppLocalizations.of(context)!.addWhitelist
: AppLocalizations.of(context)!.addBlacklist,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 24
style: TextStyle(
fontSize: 24,
color: Theme.of(context).colorScheme.onSurface
),
),
const SizedBox(height: 30),
const SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 28),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: nameController,
onChanged: (_) => checkValidValues(),
@ -127,7 +129,7 @@ class _AddListModalState extends State<AddListModal> {
),
const SizedBox(height: 30),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 28),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: urlController,
onChanged: validateUrl,
@ -148,7 +150,7 @@ class _AddListModalState extends State<AddListModal> {
),
),
Padding(
padding: const EdgeInsets.all(20),
padding: const EdgeInsets.all(24),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [

View file

@ -14,15 +14,27 @@ class DeleteListModal extends StatelessWidget {
return AlertDialog(
title: Column(
children: [
const Icon(
Icon(
Icons.delete_rounded,
size: 26,
size: 24,
color: Theme.of(context).colorScheme.secondary,
),
const SizedBox(height: 20),
Text(AppLocalizations.of(context)!.deleteList)
const SizedBox(height: 16),
Text(
AppLocalizations.of(context)!.deleteList,
style: TextStyle(
fontSize: 24,
color: Theme.of(context).colorScheme.onSurface
),
)
],
),
content: Text(AppLocalizations.of(context)!.deleteListMessage),
content: Text(
AppLocalizations.of(context)!.deleteListMessage,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),

View file

@ -176,9 +176,10 @@ class FiltersFab extends StatelessWidget {
onPressed: type == 'blacklist' || type == 'whitelist'
? () => openAddWhitelistBlacklist()
: () => openAddCustomRule(),
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
child: Icon(
Icons.add,
color: Theme.of(context).primaryColor.computeLuminance() > 0.5 ? Colors.black : Colors.white,
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
);
}

View file

@ -19,31 +19,35 @@ class FilterListTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(
icon,
size: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 20),
const SizedBox(width: 16),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 18,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface
),
),
const SizedBox(height: 5),
const SizedBox(height: 3),
Text(
subtitle,
style: TextStyle(
fontSize: 14,
color: color ?? Theme.of(context).listTileTheme.iconColor,
fontWeight: bold == true ? FontWeight.bold : null
color: color ?? Theme.of(context).colorScheme.onSurfaceVariant,
fontWeight: bold == true ? FontWeight.bold : FontWeight.w400
),
),
],

View file

@ -3,21 +3,14 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:bottom_sheet/bottom_sheet.dart';
import 'package:provider/provider.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/filters/fab.dart';
import 'package:adguard_home_manager/screens/filters/list_details_modal.dart';
import 'package:adguard_home_manager/screens/filters/add_list_modal.dart';
import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart';
import 'package:adguard_home_manager/screens/filters/list_details_screen.dart';
import 'package:adguard_home_manager/widgets/custom_list_tile.dart';
import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/functions/snackbar.dart';
import 'package:adguard_home_manager/classes/process_modal.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/functions/number_format.dart';
import 'package:adguard_home_manager/models/filtering.dart';
@ -68,196 +61,16 @@ class _FiltersListState extends State<FiltersList> {
@override
Widget build(BuildContext context) {
final serversProvider = Provider.of<ServersProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
void enableDisableList(Filter list, bool enabled) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(
enabled == true
? AppLocalizations.of(context)!.enablingList
: AppLocalizations.of(context)!.disablingList,
);
final result = await updateFilterList(server: serversProvider.selectedServer!, data: {
"data": {
"enabled": enabled,
"name": list.name,
"url": list.url
},
"url": list.url,
"whitelist": widget.type == 'whitelist' ? true : false
});
processModal.close();
if (result['result'] == 'success') {
final result2 = await getFiltering(server: serversProvider.selectedServer!);
if (result2['result'] == 'success') {
serversProvider.setFilteringData(result2['data']);
serversProvider.setFilteringLoadStatus(1, true);
}
else {
appConfigProvider.addLog(result2['log']);
serversProvider.setFilteringLoadStatus(2, true);
}
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataUpdated,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataNotUpdated,
color: Colors.red
);
}
}
void confirmEditList({required Filter list, required String type}) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.updatingListData);
final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: {
"data": {
"enabled": list.enabled,
"name": list.name,
"url": list.url
},
"url": list.url,
"whitelist": type == 'whitelist' ? true : false
});
if (result1['result'] == 'success') {
final result2 = await getFiltering(server: serversProvider.selectedServer!);
if (result2['result'] == 'success') {
serversProvider.setFilteringData(result2['data']);
serversProvider.setFilteringLoadStatus(1, true);
}
else {
appConfigProvider.addLog(result2['log']);
serversProvider.setFilteringLoadStatus(2, true);
}
processModal.close();
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataUpdated,
color: Colors.green
);
}
else {
processModal.close();
appConfigProvider.addLog(result1['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataNotUpdated,
color: Colors.red
);
}
}
void deleteList(Filter list, String type) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.deletingList);
final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: {
"url": list.url,
"whitelist": type == 'whitelist' ? true : false
});
if (result1['result'] == 'success') {
final result2 = await getFiltering(server: serversProvider.selectedServer!);
if (result2['result'] == 'success') {
serversProvider.setFilteringData(result2['data']);
serversProvider.setFilteringLoadStatus(1, true);
}
else {
appConfigProvider.addLog(result2['log']);
serversProvider.setFilteringLoadStatus(2, true);
}
processModal.close();
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDeleted,
color: Colors.green
);
}
else {
processModal.close();
appConfigProvider.addLog(result1['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listNotDeleted,
color: Colors.red
);
}
}
void openDetailsModal(Filter filter) {
final height = (filter.enabled == true ? 774 : 755)/MediaQuery.of(context).size.height < 1
? (filter.enabled == true ? 774 : 755)/MediaQuery.of(context).size.height
: 0.95;
ScaffoldMessenger.of(context).clearSnackBars();
showFlexibleBottomSheet(
minHeight: 0.6,
initHeight: 0.6,
maxHeight: height,
isCollapsible: true,
duration: const Duration(milliseconds: 250),
anchors: [height],
context: context,
builder: (ctx, controller, offset) => ListDetailsModal(
scrollController: controller,
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ListDetailsScreen(
list: filter,
type: widget.type,
onDelete: (Filter list, String type) {
showDialog(
context: context,
builder: (context) => DeleteListModal(
onConfirm: () {
Navigator.pop(context);
deleteList(list, type);
},
)
);
},
edit: (type) => {
showModalBottomSheet(
context: context,
builder: (ctx) => AddListModal(
list: filter,
type: type,
onEdit: confirmEditList
),
isScrollControlled: true,
backgroundColor: Colors.transparent
)
},
onEnableDisable: enableDisableList,
),
bottomSheetColor: Colors.transparent
);
}

View file

@ -1,176 +0,0 @@
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/filters/filter_list_tile.dart';
import 'package:adguard_home_manager/functions/format_time.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/models/filtering.dart';
class ListDetailsModal extends StatelessWidget {
final ScrollController scrollController;
final Filter list;
final String type;
final void Function(Filter, String) onDelete;
final void Function(String) edit;
final void Function(Filter, bool) onEnableDisable;
const ListDetailsModal({
Key? key,
required this.scrollController,
required this.list,
required this.type,
required this.onDelete,
required this.edit,
required this.onEnableDisable,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final appConfigProvider = Provider.of<AppConfigProvider>(context);
return Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(28),
topRight: Radius.circular(28)
),
color: Theme.of(context).dialogBackgroundColor
),
child: Column(
children: [
Expanded(
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (overscroll) {
overscroll.disallowIndicator();
return false;
},
child: ListView(
controller: scrollController,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Padding(
padding: const EdgeInsets.only(top: 24),
child: Icon(
type == 'whitelist'
? Icons.verified_user_rounded
: Icons.gpp_bad_rounded,
size: 26,
),
),
),
const SizedBox(height: 20),
Text(
AppLocalizations.of(context)!.listDetails,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 24,
),
),
const SizedBox(height: 30),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () {
Navigator.pop(context);
onEnableDisable(list, !list.enabled);
},
label: Text(
list.enabled == true
? AppLocalizations.of(context)!.disable
: AppLocalizations.of(context)!.enable
),
icon: Icon(
list.enabled == true
? Icons.gpp_bad_rounded
: Icons.verified_user_rounded
),
),
],
),
const SizedBox(height: 30),
FilterListTile(
icon: Icons.shield_rounded,
title: AppLocalizations.of(context)!.currentStatus,
subtitle: list.enabled == true
? AppLocalizations.of(context)!.enabled
: AppLocalizations.of(context)!.disabled,
color: list.enabled == true
? appConfigProvider.useThemeColorForStatus == true
? Theme.of(context).primaryColor
: Colors.green
: appConfigProvider.useThemeColorForStatus == true
? Colors.grey
: Colors.red,
bold: true,
),
FilterListTile(
icon: Icons.badge_rounded,
title: AppLocalizations.of(context)!.name,
subtitle: list.name
),
FilterListTile(
icon: Icons.link_rounded,
title: "URL",
subtitle: list.url
),
FilterListTile(
icon: Icons.list_rounded,
title: AppLocalizations.of(context)!.rules,
subtitle: list.rulesCount.toString()
),
FilterListTile(
icon: Icons.shield_rounded,
title: AppLocalizations.of(context)!.listType,
subtitle: type == 'whitelist'
? AppLocalizations.of(context)!.whitelist
: AppLocalizations.of(context)!.blacklist,
),
if (list.lastUpdated != null) FilterListTile(
icon: Icons.schedule_rounded,
title: AppLocalizations.of(context)!.latestUpdate,
subtitle: formatTimestampUTC(list.lastUpdated!, 'dd-MM-yyyy HH:mm'),
),
],
),
)
),
Padding(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
IconButton(
onPressed: () {
Navigator.pop(context);
edit(type);
},
icon: const Icon(Icons.edit)
),
const SizedBox(width: 10),
IconButton(
onPressed: () {
onDelete(list, type);
},
icon: const Icon(Icons.delete)
),
],
),
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.close)
)
],
),
),
],
),
);
}
}

View file

@ -0,0 +1,322 @@
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/filters/filter_list_tile.dart';
import 'package:adguard_home_manager/screens/filters/add_list_modal.dart';
import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart';
import 'package:adguard_home_manager/functions/format_time.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/functions/snackbar.dart';
import 'package:adguard_home_manager/classes/process_modal.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/models/filtering.dart';
class ListDetailsScreen extends StatefulWidget {
final Filter list;
final String type;
const ListDetailsScreen({
Key? key,
required this.list,
required this.type,
}) : super(key: key);
@override
State<ListDetailsScreen> createState() => _ListDetailsScreenState();
}
class _ListDetailsScreenState extends State<ListDetailsScreen> {
final ScrollController scrollController = ScrollController();
String name = "";
bool enabled = true;
bool fabVisible = true;
@override
void initState() {
name = widget.list.name;
enabled = widget.list.enabled;
scrollController.addListener(() {
if (scrollController.position.userScrollDirection == ScrollDirection.reverse) {
if (mounted && fabVisible == true) {
setState(() => fabVisible = false);
}
}
else {
if (scrollController.position.userScrollDirection == ScrollDirection.forward) {
if (mounted && fabVisible == false) {
setState(() => fabVisible = true);
}
}
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
final serversProvider = Provider.of<ServersProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
void enableDisableList(Filter list, bool newStatus) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(
enabled == true
? AppLocalizations.of(context)!.disablingList
: AppLocalizations.of(context)!.enablingList,
);
final result = await updateFilterList(server: serversProvider.selectedServer!, data: {
"data": {
"enabled": newStatus,
"name": list.name,
"url": list.url
},
"url": list.url,
"whitelist": widget.type == 'whitelist' ? true : false
});
processModal.close();
if (result['result'] == 'success') {
final result2 = await getFiltering(server: serversProvider.selectedServer!);
if (result2['result'] == 'success') {
serversProvider.setFilteringData(result2['data']);
serversProvider.setFilteringLoadStatus(1, true);
}
else {
appConfigProvider.addLog(result2['log']);
serversProvider.setFilteringLoadStatus(2, true);
}
setState(() => enabled = newStatus);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataUpdated,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataNotUpdated,
color: Colors.red
);
}
}
void confirmEditList({required Filter list, required String type}) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.updatingListData);
final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: {
"data": {
"enabled": list.enabled,
"name": list.name,
"url": list.url
},
"url": list.url,
"whitelist": type == 'whitelist' ? true : false
});
if (result1['result'] == 'success') {
final result2 = await getFiltering(server: serversProvider.selectedServer!);
if (result2['result'] == 'success') {
serversProvider.setFilteringData(result2['data']);
serversProvider.setFilteringLoadStatus(1, true);
}
else {
appConfigProvider.addLog(result2['log']);
serversProvider.setFilteringLoadStatus(2, true);
}
processModal.close();
setState(() => name = list.name);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataUpdated,
color: Colors.green
);
}
else {
processModal.close();
appConfigProvider.addLog(result1['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDataNotUpdated,
color: Colors.red
);
}
}
void deleteList(Filter list, String type) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.deletingList);
final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: {
"url": list.url,
"whitelist": type == 'whitelist' ? true : false
});
if (result1['result'] == 'success') {
final result2 = await getFiltering(server: serversProvider.selectedServer!);
if (result2['result'] == 'success') {
serversProvider.setFilteringData(result2['data']);
serversProvider.setFilteringLoadStatus(1, true);
}
else {
appConfigProvider.addLog(result2['log']);
serversProvider.setFilteringLoadStatus(2, true);
}
processModal.close();
Navigator.pop(context); // Closes the screen
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listDeleted,
color: Colors.green
);
}
else {
processModal.close();
appConfigProvider.addLog(result1['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.listNotDeleted,
color: Colors.red
);
}
}
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.listDetails),
actions: [
IconButton(
onPressed: () => {
showModalBottomSheet(
context: context,
builder: (ctx) => AddListModal(
list: widget.list,
type: widget.type,
onEdit: confirmEditList
),
isScrollControlled: true,
backgroundColor: Colors.transparent
)
},
icon: const Icon(Icons.edit),
tooltip: AppLocalizations.of(context)!.edit,
),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => DeleteListModal(
onConfirm: () => deleteList(widget.list, widget.type),
)
);
},
icon: const Icon(Icons.delete),
tooltip: AppLocalizations.of(context)!.delete,
),
const SizedBox(width: 10),
],
),
body: Stack(
children: [
ListView(
children: [
FilterListTile(
icon: Icons.shield_rounded,
title: AppLocalizations.of(context)!.currentStatus,
subtitle: enabled == true
? AppLocalizations.of(context)!.enabled
: AppLocalizations.of(context)!.disabled,
color: enabled == true
? appConfigProvider.useThemeColorForStatus == true
? Theme.of(context).primaryColor
: Colors.green
: appConfigProvider.useThemeColorForStatus == true
? Colors.grey
: Colors.red,
bold: true,
),
FilterListTile(
icon: Icons.badge_rounded,
title: AppLocalizations.of(context)!.name,
subtitle: name
),
FilterListTile(
icon: Icons.link_rounded,
title: "URL",
subtitle: widget.list.url
),
FilterListTile(
icon: Icons.list_rounded,
title: AppLocalizations.of(context)!.rules,
subtitle: widget.list.rulesCount.toString()
),
FilterListTile(
icon: Icons.shield_rounded,
title: AppLocalizations.of(context)!.listType,
subtitle: widget.type == 'whitelist'
? AppLocalizations.of(context)!.whitelist
: AppLocalizations.of(context)!.blacklist,
),
if (widget.list.lastUpdated != null) FilterListTile(
icon: Icons.schedule_rounded,
title: AppLocalizations.of(context)!.latestUpdate,
subtitle: formatTimestampUTC(widget.list.lastUpdated!, 'dd-MM-yyyy HH:mm'),
),
],
),
AnimatedPositioned(
duration: const Duration(milliseconds: 100),
curve: Curves.easeInOut,
bottom: fabVisible ?
appConfigProvider.showingSnackbar
? 70 : 20
: -70,
right: 20,
child: FloatingActionButton(
onPressed: () => enableDisableList(widget.list, !enabled),
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
child: Icon(
enabled == true
? Icons.gpp_bad_rounded
: Icons.verified_user_rounded,
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
),
)
],
),
);
}
}

View file

@ -66,9 +66,9 @@ class HomeAppBar extends StatelessWidget with PreferredSizeWidget {
? Theme.of(context).primaryColor
: Colors.green
: appConfigProvider.useThemeColorForStatus == true
? Colors.grey
? Theme.of(context).colorScheme.onSurface.withOpacity(0.38)
: Colors.red
: Colors.grey,
: Theme.of(context).colorScheme.onSurface.withOpacity(0.38)
),
const SizedBox(width: 20),
Column(
@ -84,9 +84,9 @@ class HomeAppBar extends StatelessWidget with PreferredSizeWidget {
const SizedBox(height: 5),
Text(
"${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}",
style: const TextStyle(
style: TextStyle(
fontSize: 14,
color: Color.fromRGBO(140, 140, 140, 1)
color: Theme.of(context).colorScheme.onSurfaceVariant
),
)
],

View file

@ -24,9 +24,10 @@ class HomeFab extends StatelessWidget {
return serversProvider.serverStatus.loadStatus == 1
? FloatingActionButton(
onPressed: openManagementBottomSheet,
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
child: Icon(
Icons.shield_rounded,
color: Theme.of(context).primaryColor.computeLuminance() > 0.5 ? Colors.black : Colors.white,
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
)
: const SizedBox();

View file

@ -36,7 +36,7 @@ class ManagementModal extends StatelessWidget {
Widget mainSwitch() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Material(
color: Theme.of(context).primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(28),
@ -84,7 +84,7 @@ class ManagementModal extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 35,
vertical: 5
vertical: 8
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -94,12 +94,15 @@ class ManagementModal extends StatelessWidget {
Icon(
icon,
size: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 20),
const SizedBox(width: 16),
Text(
label,
style: const TextStyle(
fontSize: 15,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface,
),
),
],
@ -136,20 +139,22 @@ class ManagementModal extends StatelessWidget {
? const NeverScrollableScrollPhysics()
: null,
children: [
const Padding(
padding: EdgeInsets.only(top: 24),
Padding(
padding: const EdgeInsets.only(top: 24),
child: Icon(
Icons.shield_rounded,
size: 26,
size: 24,
color: Theme.of(context).colorScheme.onSurface,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 24),
padding: const EdgeInsets.symmetric(vertical: 16),
child: Text(
AppLocalizations.of(context)!.manageServer,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 22
style: TextStyle(
fontSize: 24,
color: Theme.of(context).colorScheme.onSurface,
),
),
),

View file

@ -19,7 +19,7 @@ class LogListTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -29,6 +29,7 @@ class LogListTile extends StatelessWidget {
Icon(
icon,
size: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 16),
Flexible(
@ -47,7 +48,7 @@ class LogListTile extends StatelessWidget {
subtitle!,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
)
],

View file

@ -83,10 +83,11 @@ class LogTile extends StatelessWidget {
children: [
Text(
log.question.name,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
height: 1.5,
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface
),
),
const SizedBox(height: 5),
@ -96,7 +97,7 @@ class LogTile extends StatelessWidget {
Icon(
Icons.smartphone_rounded,
size: 16,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 5),
SizedBox(
@ -104,7 +105,7 @@ class LogTile extends StatelessWidget {
log.client,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14,
height: 1.4,
fontWeight: FontWeight.w400,
@ -117,7 +118,7 @@ class LogTile extends StatelessWidget {
Icon(
Icons.schedule_rounded,
size: 16,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 5),
SizedBox(
@ -125,7 +126,7 @@ class LogTile extends StatelessWidget {
formatTimestampUTCFromAPI(log.time, 'HH:mm:ss'),
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13
),
),
@ -140,7 +141,7 @@ class LogTile extends StatelessWidget {
Icon(
Icons.smartphone_rounded,
size: 16,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 15),
SizedBox(
@ -148,7 +149,7 @@ class LogTile extends StatelessWidget {
log.client,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13
),
),
@ -162,7 +163,7 @@ class LogTile extends StatelessWidget {
Icon(
Icons.badge_rounded,
size: 16,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 15),
SizedBox(
@ -170,7 +171,7 @@ class LogTile extends StatelessWidget {
log.clientInfo!.name,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13
),
),
@ -184,7 +185,7 @@ class LogTile extends StatelessWidget {
Icon(
Icons.schedule_rounded,
size: 16,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 15),
SizedBox(
@ -192,7 +193,7 @@ class LogTile extends StatelessWidget {
formatTimestampUTCFromAPI(log.time, 'HH:mm:ss'),
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13
),
),
@ -206,7 +207,7 @@ class LogTile extends StatelessWidget {
Icon(
Icons.timer,
size: 16,
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 15),
SizedBox(
@ -214,7 +215,7 @@ class LogTile extends StatelessWidget {
"${double.parse(log.elapsedMs).toStringAsFixed(2)} ms",
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 13
),
),

View file

@ -88,9 +88,10 @@ class _ServersState extends State<Servers> {
right: 20,
child: FloatingActionButton(
onPressed: openAddServerModal,
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
child: Icon(
Icons.add,
color: Theme.of(context).primaryColor.computeLuminance() > 0.5 ? Colors.black : Colors.white,
color: Theme.of(context).colorScheme.onPrimaryContainer
),
),
),

View file

@ -154,7 +154,12 @@ class _TopItemsScreenState extends State<TopItemsScreen> {
return CustomListTile(
title: screenData[index].keys.toList()[0],
trailing: Text(screenData[index].values.toList()[0].toString()),
trailing: Text(
screenData[index].values.toList()[0].toString(),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant
),
),
subtitleWidget: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -163,9 +168,7 @@ class _TopItemsScreenState extends State<TopItemsScreen> {
name,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).brightness == Brightness.light
? Colors.black
: Colors.white
color: Theme.of(context).colorScheme.onSurface
),
),
const SizedBox(height: 5),
@ -177,7 +180,7 @@ class _TopItemsScreenState extends State<TopItemsScreen> {
child: Text(
"${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%",
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor
color: Theme.of(context).colorScheme.onSurfaceVariant
),
),
),

View file

@ -39,6 +39,7 @@ class CustomListTile extends StatelessWidget {
Icon(
icon,
size: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 16),
],
@ -48,9 +49,10 @@ class CustomListTile extends StatelessWidget {
children: [
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface,
),
),
if (subtitle != null || subtitleWidget != null) ...[
@ -59,7 +61,7 @@ class CustomListTile extends StatelessWidget {
if (subtitle != null && subtitleWidget == null) Text(
subtitle!,
style: TextStyle(
color: Theme.of(context).listTileTheme.iconColor,
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 14,
fontWeight: FontWeight.w400
),

View file

@ -46,16 +46,19 @@ class DeleteModal extends StatelessWidget {
return AlertDialog(
title: Column(
children: [
const Icon(
Icon(
Icons.delete,
size: 26,
size: 24,
color: Theme.of(context).colorScheme.onSurfaceVariant
),
Padding(
padding: const EdgeInsets.only(top: 20),
padding: const EdgeInsets.only(top: 16),
child: Text(
AppLocalizations.of(context)!.remove,
style: const TextStyle(
fontSize: 24
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface
),
),
),
@ -70,13 +73,17 @@ class DeleteModal extends StatelessWidget {
Text(
AppLocalizations.of(context)!.removeWarning,
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface
),
),
const SizedBox(height: 10),
Center(
child: Text(
"${serverToDelete.connectionMethod}://${serverToDelete.domain}${serverToDelete.path ?? ""}${serverToDelete.port != null ? ':${serverToDelete.port}' : ""}",
style: const TextStyle(
fontStyle: FontStyle.italic
style: TextStyle(
fontStyle: FontStyle.italic,
color: Theme.of(context).colorScheme.onSurface
),
),
),

View file

@ -187,7 +187,7 @@ class _ServersListState extends State<ServersList> with SingleTickerProviderStat
Container(
padding: const EdgeInsets.all(1),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
color: Theme.of(context).colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(20)
),
child: const Icon(
@ -232,9 +232,10 @@ class _ServersListState extends State<ServersList> with SingleTickerProviderStat
Text(
"${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}",
textAlign: TextAlign.center,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface
),
),
Column(
@ -246,7 +247,7 @@ class _ServersListState extends State<ServersList> with SingleTickerProviderStat
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Theme.of(context).listTileTheme.iconColor
color: Theme.of(context).colorScheme.onSurfaceVariant
),
)
],