Skip to content

Commit 5c68d51

Browse files
authored
feat: Add ability to set null in patch options (#1947)
1 parent fc52560 commit 5c68d51

File tree

6 files changed

+153
-276
lines changed

6 files changed

+153
-276
lines changed

assets/i18n/strings.i18n.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,18 @@
118118
},
119119
"patchOptionsView": {
120120
"customValue": "Custom value",
121+
"setToNull": "Set to null",
122+
"nullValue": "This option value is currently null",
121123
"resetOptionsTooltip": "Reset patch options",
122124
"viewTitle": "Patch options",
123125
"saveOptions": "Save",
124126
"addOptions": "Add options",
125-
"deselectPatch": "Deselect patch",
127+
"unselectPatch": "Unselect patch",
126128
"tooltip": "More input options",
127129
"selectFilePath": "Select file path",
128130
"selectFolder": "Select folder",
129131
"selectOption": "Select option",
130-
"requiredOption": "This option is required",
132+
"requiredOption": "Setting this option is required",
131133
"unsupportedOption": "This option is not supported",
132134
"requiredOptionNull": "The following options have to be set:\n\n${options}"
133135
},

lib/services/manager_api.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class ManagerAPI {
3131
final String cliRepo = 'revanced-cli';
3232
late SharedPreferences _prefs;
3333
List<Patch> patches = [];
34-
List<Option> modifiedOptions = [];
3534
List<Option> options = [];
3635
Patch? selectedPatch;
3736
BuildContext? ctx;

lib/ui/views/patch_options/patch_options_view.dart

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -37,79 +37,35 @@ class PatchOptionsView extends StatelessWidget {
3737
color: Theme.of(context).textTheme.titleLarge!.color,
3838
),
3939
),
40-
actions: [
41-
IconButton(
42-
onPressed: () {
43-
model.resetOptions();
44-
},
45-
icon: const Icon(
46-
Icons.history,
47-
),
48-
tooltip: t.patchOptionsView.resetOptionsTooltip,
49-
),
50-
],
5140
),
5241
SliverToBoxAdapter(
5342
child: Padding(
5443
padding: const EdgeInsets.all(8.0),
5544
child: Column(
5645
children: [
57-
for (final Option option in model.visibleOptions)
46+
for (final Option option in model.modifiedOptions)
5847
if (option.valueType == 'String' ||
5948
option.valueType == 'Int')
6049
IntAndStringPatchOption(
6150
patchOption: option,
62-
removeOption: (option) {
63-
model.removeOption(option);
64-
},
65-
onChanged: (value, option) {
66-
model.modifyOptions(value, option);
67-
},
51+
model: model,
6852
)
6953
else if (option.valueType == 'Boolean')
7054
BooleanPatchOption(
7155
patchOption: option,
72-
removeOption: (option) {
73-
model.removeOption(option);
74-
},
75-
onChanged: (value, option) {
76-
model.modifyOptions(value, option);
77-
},
56+
model: model,
7857
)
7958
else if (option.valueType == 'StringArray' ||
8059
option.valueType == 'IntArray' ||
8160
option.valueType == 'LongArray')
8261
IntStringLongListPatchOption(
8362
patchOption: option,
84-
removeOption: (option) {
85-
model.removeOption(option);
86-
},
87-
onChanged: (value, option) {
88-
model.modifyOptions(value, option);
89-
},
63+
model: model,
9064
)
9165
else
9266
UnsupportedPatchOption(
9367
patchOption: option,
9468
),
95-
if (model.visibleOptions.length !=
96-
model.options.length) ...[
97-
const SizedBox(
98-
height: 8,
99-
),
100-
FilledButton(
101-
onPressed: () {
102-
model.showAddOptionDialog(context);
103-
},
104-
child: Row(
105-
mainAxisSize: MainAxisSize.min,
106-
children: [
107-
const Icon(Icons.add),
108-
Text(t.patchOptionsView.addOptions),
109-
],
110-
),
111-
),
112-
],
11369
const SizedBox(
11470
height: 80,
11571
),

lib/ui/views/patch_options/patch_options_viewmodel.dart

Lines changed: 17 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'package:revanced_manager/models/patch.dart';
55
import 'package:revanced_manager/services/manager_api.dart';
66
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
77
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
8-
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
98
import 'package:stacked/stacked.dart';
109

1110
class PatchOptionsViewModel extends BaseViewModel {
@@ -14,7 +13,7 @@ class PatchOptionsViewModel extends BaseViewModel {
1413
locator<PatcherViewModel>().selectedApp!.packageName;
1514
List<Option> options = [];
1615
List<Option> savedOptions = [];
17-
List<Option> visibleOptions = [];
16+
List<Option> modifiedOptions = [];
1817

1918
Future<void> initialize() async {
2019
options = getDefaultOptions();
@@ -28,44 +27,26 @@ class PatchOptionsViewModel extends BaseViewModel {
2827
savedOptions.add(savedOption);
2928
}
3029
}
31-
if (savedOptions.isNotEmpty) {
32-
visibleOptions = [
33-
...savedOptions,
34-
...options.where(
35-
(option) =>
36-
option.required &&
37-
!savedOptions.any((sOption) => sOption.key == option.key),
38-
),
39-
];
40-
} else {
41-
visibleOptions = [
42-
...options.where((option) => option.required),
43-
];
44-
}
45-
}
46-
47-
void addOption(Option option) {
48-
visibleOptions.add(option);
49-
notifyListeners();
50-
}
51-
52-
void removeOption(Option option) {
53-
visibleOptions.removeWhere((vOption) => vOption.key == option.key);
54-
notifyListeners();
30+
modifiedOptions = [
31+
...savedOptions,
32+
...options.where(
33+
(option) => !savedOptions.any((sOption) => sOption.key == option.key),
34+
),
35+
];
5536
}
5637

5738
bool saveOptions(BuildContext context) {
5839
final List<Option> requiredNullOptions = [];
5940
for (final Option option in options) {
60-
if (!visibleOptions.any((vOption) => vOption.key == option.key)) {
41+
if (modifiedOptions.any((mOption) => mOption.key == option.key)) {
6142
_managerAPI.clearPatchOption(
6243
selectedApp,
6344
_managerAPI.selectedPatch!.name,
6445
option.key,
6546
);
6647
}
6748
}
68-
for (final Option option in visibleOptions) {
49+
for (final Option option in modifiedOptions) {
6950
if (option.required && option.value == null) {
7051
requiredNullOptions.add(option);
7152
} else {
@@ -98,11 +79,8 @@ class PatchOptionsViewModel extends BaseViewModel {
9879
required: option.required,
9980
key: option.key,
10081
);
101-
visibleOptions[visibleOptions
102-
.indexWhere((vOption) => vOption.key == option.key)] = modifiedOption;
103-
_managerAPI.modifiedOptions
104-
.removeWhere((mOption) => mOption.key == option.key);
105-
_managerAPI.modifiedOptions.add(modifiedOption);
82+
modifiedOptions.removeWhere((mOption) => mOption.key == option.key);
83+
modifiedOptions.add(modifiedOption);
10684
}
10785

10886
List<Option> getDefaultOptions() {
@@ -122,93 +100,11 @@ class PatchOptionsViewModel extends BaseViewModel {
122100
return defaultOptions;
123101
}
124102

125-
void resetOptions() {
126-
_managerAPI.modifiedOptions.clear();
127-
visibleOptions =
128-
getDefaultOptions().where((option) => option.required).toList();
129-
notifyListeners();
130-
}
131-
132-
Future<void> showAddOptionDialog(BuildContext context) async {
133-
await showDialog(
134-
context: context,
135-
builder: (context) => AlertDialog(
136-
title: Column(
137-
crossAxisAlignment: CrossAxisAlignment.start,
138-
mainAxisSize: MainAxisSize.min,
139-
children: [
140-
Text(
141-
t.patchOptionsView.addOptions,
142-
),
143-
Text(
144-
'',
145-
style: TextStyle(
146-
fontSize: 16,
147-
color: Theme.of(context).colorScheme.onSecondaryContainer,
148-
),
149-
),
150-
],
151-
),
152-
actions: [
153-
FilledButton(
154-
onPressed: () {
155-
Navigator.of(context).pop();
156-
},
157-
child: Text(t.cancelButton),
158-
),
159-
],
160-
contentPadding: const EdgeInsets.all(8),
161-
content: Wrap(
162-
spacing: 14,
163-
runSpacing: 14,
164-
children: options
165-
.where(
166-
(option) =>
167-
!visibleOptions.any((vOption) => vOption.key == option.key),
168-
)
169-
.map((e) {
170-
return CustomCard(
171-
padding: const EdgeInsets.all(4),
172-
backgroundColor: Theme.of(context).colorScheme.surface,
173-
onTap: () {
174-
addOption(e);
175-
Navigator.pop(context);
176-
},
177-
child: Padding(
178-
padding: const EdgeInsets.all(8.0),
179-
child: Row(
180-
children: [
181-
Expanded(
182-
child: Column(
183-
crossAxisAlignment: CrossAxisAlignment.start,
184-
children: [
185-
Text(
186-
e.title,
187-
style: TextStyle(
188-
fontSize: 16,
189-
color: Theme.of(context).colorScheme.onSurface,
190-
),
191-
),
192-
const SizedBox(height: 4),
193-
Text(
194-
e.description,
195-
style: TextStyle(
196-
fontSize: 14,
197-
color: Theme.of(context).colorScheme.onSurface,
198-
),
199-
),
200-
],
201-
),
202-
),
203-
],
204-
),
205-
),
206-
);
207-
}).toList(),
208-
),
209-
),
210-
);
211-
}
103+
dynamic getDefaultValue(Option patchOption) => _managerAPI.options
104+
.firstWhere(
105+
(option) => option.key == patchOption.key,
106+
)
107+
.value;
212108
}
213109

214110
Future<void> showRequiredOptionNullDialog(
@@ -248,7 +144,7 @@ Future<void> showRequiredOptionNullDialog(
248144
PatchesSelectorViewModel().showPatchesChangeDialog(context);
249145
}
250146
},
251-
child: Text(t.patchOptionsView.deselectPatch),
147+
child: Text(t.patchOptionsView.unselectPatch),
252148
),
253149
FilledButton(
254150
onPressed: () {

lib/ui/views/patches_selector/patches_selector_viewmodel.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ class PatchesSelectorViewModel extends BaseViewModel {
6161
void navigateToPatchOptions(List<Option> setOptions, Patch patch) {
6262
_managerAPI.options = setOptions;
6363
_managerAPI.selectedPatch = patch;
64-
_managerAPI.modifiedOptions.clear();
6564
_navigationService.navigateToPatchOptionsView();
6665
}
6766

0 commit comments

Comments
 (0)