mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-22 23:09:12 +00:00
Added add and remove custom rules
This commit is contained in:
parent
6800c6f20f
commit
d12a1134f0
8 changed files with 359 additions and 14 deletions
|
@ -207,5 +207,14 @@
|
||||||
"customRules": "Custom rules",
|
"customRules": "Custom rules",
|
||||||
"enabledRules": "Enabled rules",
|
"enabledRules": "Enabled rules",
|
||||||
"enabled": "Enabled",
|
"enabled": "Enabled",
|
||||||
"disabled": "Disabled"
|
"disabled": "Disabled",
|
||||||
|
"rule": "Rule",
|
||||||
|
"addCustomRule": "Add custom rule",
|
||||||
|
"removeCustomRule": "Remove custom rule",
|
||||||
|
"removeCustomRuleMessage": "Are you sure you want to remove this custom rule?",
|
||||||
|
"updatingRules": "Updating custom rules...",
|
||||||
|
"ruleRemovedSuccessfully": "Rule removed successfully",
|
||||||
|
"ruleNotRemoved": "Couldn't remove the rule",
|
||||||
|
"ruleAddedSuccessfully": "Rule added successfully",
|
||||||
|
"ruleNotAdded": "Couldn't add the rule,"
|
||||||
}
|
}
|
|
@ -207,5 +207,14 @@
|
||||||
"customRules": "Reglas personalizadas",
|
"customRules": "Reglas personalizadas",
|
||||||
"enabledRules": "Reglas activas",
|
"enabledRules": "Reglas activas",
|
||||||
"enabled": "Activada",
|
"enabled": "Activada",
|
||||||
"disabled": "Desactivada"
|
"disabled": "Desactivada",
|
||||||
|
"rule": "Regla",
|
||||||
|
"addCustomRule": "Añadir regla personalizada",
|
||||||
|
"removeCustomRule": "Eliminar regla personalizada",
|
||||||
|
"removeCustomRuleMessage": "¿Estás seguro que deseas eliminar esta regla personalizada?",
|
||||||
|
"updatingRules": "Updating custom rules...",
|
||||||
|
"ruleRemovedSuccessfully": "Regla eliminada correctamente",
|
||||||
|
"ruleNotRemoved": "No se ha podido eliminar la regla",
|
||||||
|
"ruleAddedSuccessfully": "Regla añadida correctamente",
|
||||||
|
"ruleNotAdded": "No se ha podido añadir la regla"
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ class Filtering {
|
||||||
class FilteringData {
|
class FilteringData {
|
||||||
final List<Filter> filters;
|
final List<Filter> filters;
|
||||||
final List<Filter> whitelistFilters;
|
final List<Filter> whitelistFilters;
|
||||||
final List<String> userRules;
|
List<String> userRules;
|
||||||
final int interval;
|
final int interval;
|
||||||
final bool enabled;
|
final bool enabled;
|
||||||
|
|
||||||
|
|
112
lib/screens/filters/add_custom_rule.dart
Normal file
112
lib/screens/filters/add_custom_rule.dart
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
class AddCustomRule extends StatefulWidget {
|
||||||
|
final void Function(String) onConfirm;
|
||||||
|
|
||||||
|
const AddCustomRule({
|
||||||
|
Key? key,
|
||||||
|
required this.onConfirm
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AddCustomRule> createState() => _AddCustomRuleState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AddCustomRuleState extends State<AddCustomRule> {
|
||||||
|
TextEditingController ruleController = TextEditingController();
|
||||||
|
|
||||||
|
bool validValues = false;
|
||||||
|
|
||||||
|
void checkValidValues() {
|
||||||
|
if (ruleController.text != '') {
|
||||||
|
setState(() => validValues = true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setState(() => validValues = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: MediaQuery.of(context).viewInsets,
|
||||||
|
child: Container(
|
||||||
|
height: 300,
|
||||||
|
padding: const EdgeInsets.all(28),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).dialogBackgroundColor,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(28),
|
||||||
|
topRight: Radius.circular(28)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.shield_rounded,
|
||||||
|
size: 26,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!.addCustomRule,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 24
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
TextFormField(
|
||||||
|
controller: ruleController,
|
||||||
|
onChanged: (_) => checkValidValues(),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: const Icon(Icons.rule),
|
||||||
|
border: const OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(10)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
labelText: AppLocalizations.of(context)!.rule,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text(AppLocalizations.of(context)!.cancel)
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
TextButton(
|
||||||
|
onPressed: validValues == true
|
||||||
|
? () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
widget.onConfirm(ruleController.text);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!.confirm,
|
||||||
|
style: TextStyle(
|
||||||
|
color: validValues == true
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: Colors.grey
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,17 @@
|
||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:flutter/material.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/filters/fab.dart';
|
||||||
|
import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/models/filtering.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/app_config_provider.dart';
|
||||||
|
import 'package:adguard_home_manager/services/http_requests.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||||
|
import 'package:adguard_home_manager/classes/process_modal.dart';
|
||||||
|
|
||||||
class CustomRulesList extends StatelessWidget {
|
class CustomRulesList extends StatelessWidget {
|
||||||
final List<String> data;
|
final List<String> data;
|
||||||
|
@ -10,17 +23,69 @@ class CustomRulesList extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView.builder(
|
final serversProvider = Provider.of<ServersProvider>(context);
|
||||||
padding: const EdgeInsets.only(top: 0),
|
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||||
itemCount: data.length,
|
|
||||||
itemBuilder: (context, index) => ListTile(
|
void removeCustomRule(String rule) async {
|
||||||
onLongPress: () => {},
|
ProcessModal processModal = ProcessModal(context: context);
|
||||||
title: Text(data[index]),
|
processModal.open(AppLocalizations.of(context)!.updatingRules);
|
||||||
trailing: IconButton(
|
|
||||||
onPressed: () => {},
|
final List<String> newRules = serversProvider.filtering.data!.userRules.where((r) => r != rule).toList();
|
||||||
icon: const Icon(Icons.delete)
|
|
||||||
|
final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules);
|
||||||
|
|
||||||
|
processModal.close();
|
||||||
|
|
||||||
|
if (result['result'] == 'success') {
|
||||||
|
FilteringData filteringData = serversProvider.filtering.data!;
|
||||||
|
filteringData.userRules = newRules;
|
||||||
|
serversProvider.setFilteringData(filteringData);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(AppLocalizations.of(context)!.ruleRemovedSuccessfully),
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appConfigProvider.addLog(result['log']);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(AppLocalizations.of(context)!.ruleNotRemoved),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void openRemoveCustomRuleModal(String rule) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => RemoveCustomRule(
|
||||||
|
onConfirm: () => removeCustomRule(rule),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
ListView.builder(
|
||||||
|
padding: const EdgeInsets.only(top: 0),
|
||||||
|
itemCount: data.length,
|
||||||
|
itemBuilder: (context, index) => ListTile(
|
||||||
|
title: Text(data[index]),
|
||||||
|
trailing: IconButton(
|
||||||
|
onPressed: () => openRemoveCustomRuleModal(data[index]),
|
||||||
|
icon: const Icon(Icons.delete)
|
||||||
|
),
|
||||||
|
)
|
||||||
),
|
),
|
||||||
)
|
const Positioned(
|
||||||
|
bottom: 20,
|
||||||
|
right: 20,
|
||||||
|
child: FiltersFab()
|
||||||
|
)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
72
lib/screens/filters/fab.dart
Normal file
72
lib/screens/filters/fab.dart
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
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/add_custom_rule.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/services/http_requests.dart';
|
||||||
|
import 'package:adguard_home_manager/classes/process_modal.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/app_config_provider.dart';
|
||||||
|
import 'package:adguard_home_manager/models/filtering.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||||
|
|
||||||
|
class FiltersFab extends StatelessWidget {
|
||||||
|
const FiltersFab({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final serversProvider = Provider.of<ServersProvider>(context);
|
||||||
|
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
||||||
|
|
||||||
|
void confirmAddRule(String rule) async {
|
||||||
|
ProcessModal processModal = ProcessModal(context: context);
|
||||||
|
processModal.open(AppLocalizations.of(context)!.updatingRules);
|
||||||
|
|
||||||
|
final List<String> newRules = serversProvider.filtering.data!.userRules;
|
||||||
|
newRules.add(rule);
|
||||||
|
|
||||||
|
final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules);
|
||||||
|
|
||||||
|
processModal.close();
|
||||||
|
|
||||||
|
if (result['result'] == 'success') {
|
||||||
|
FilteringData filteringData = serversProvider.filtering.data!;
|
||||||
|
filteringData.userRules = newRules;
|
||||||
|
serversProvider.setFilteringData(filteringData);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(AppLocalizations.of(context)!.ruleAddedSuccessfully),
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appConfigProvider.addLog(result['log']);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(AppLocalizations.of(context)!.ruleNotAdded),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void openAddClient() {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => AddCustomRule(
|
||||||
|
onConfirm: confirmAddRule
|
||||||
|
),
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FloatingActionButton(
|
||||||
|
onPressed: openAddClient,
|
||||||
|
child: const Icon(Icons.add),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
44
lib/screens/filters/remove_custom_rule_modal.dart
Normal file
44
lib/screens/filters/remove_custom_rule_modal.dart
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
class RemoveCustomRule extends StatelessWidget {
|
||||||
|
final void Function() onConfirm;
|
||||||
|
|
||||||
|
const RemoveCustomRule({
|
||||||
|
Key? key,
|
||||||
|
required this.onConfirm
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Column(
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.shield_rounded,
|
||||||
|
size: 26,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!.removeCustomRule,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Text(AppLocalizations.of(context)!.removeCustomRuleMessage),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text(AppLocalizations.of(context)!.cancel)
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
onConfirm();
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(AppLocalizations.of(context)!.confirm)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -676,7 +676,7 @@ Future postDeleteClient({
|
||||||
required Server server,
|
required Server server,
|
||||||
required String name,
|
required String name,
|
||||||
}) async {
|
}) async {
|
||||||
final result = await apiRequest(
|
final result = await apiRequest(
|
||||||
urlPath: '/clients/delete',
|
urlPath: '/clients/delete',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
server: server,
|
server: server,
|
||||||
|
@ -740,3 +740,37 @@ Future getFiltering({
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future setCustomRules({
|
||||||
|
required Server server,
|
||||||
|
required List<String> rules,
|
||||||
|
}) async {
|
||||||
|
final result = await apiRequest(
|
||||||
|
urlPath: '/filtering/set_rules',
|
||||||
|
method: 'post',
|
||||||
|
server: server,
|
||||||
|
body: {'rules': rules},
|
||||||
|
type: 'set_custom_rules'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result['hasResponse'] == true) {
|
||||||
|
if (result['statusCode'] == 200) {
|
||||||
|
return {'result': 'success'};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
'result': 'error',
|
||||||
|
'log': AppLog(
|
||||||
|
type: 'set_custom_rules',
|
||||||
|
dateTime: DateTime.now(),
|
||||||
|
message: 'error_code_not_expected',
|
||||||
|
statusCode: result['statusCode'].toString(),
|
||||||
|
resBody: result['body']
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue