Skip to content

Commit

Permalink
feat: Import and export manager settings (#2268)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAabedKhan authored Nov 5, 2024
1 parent 8c8df69 commit a45d959
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 1 deletion.
6 changes: 6 additions & 0 deletions assets/i18n/strings.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@
"deleteTempDirLabel": "Delete temporary files",
"deleteTempDirHint": "Delete unused temporary files",
"deletedTempDir": "Temporary files deleted",
"exportSettingsLabel": "Export settings",
"exportSettingsHint": "Export settings to a JSON file",
"exportedSettings": "Settings exported",
"importSettingsLabel": "Import settings",
"importSettingsHint": "Import settings from a JSON file",
"importedSettings": "Settings imported",
"exportPatchesLabel": "Export patch selection",
"exportPatchesHint": "Export patch selection to a JSON file",
"exportedPatches": "Patch selection exported",
Expand Down
1 change: 1 addition & 0 deletions docs/2_4_settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Learn how to configure ReVanced Manager.
- 🔑 Keystore used to sign patched apps
- 📄 Remembered selection of patches for each app
- ⚙️ Remembered patch options
- 🛠️ Remembered settings

> ℹ️ Note
> These can be used to backup and restore or reset settings to default in case of issues.
Expand Down
30 changes: 30 additions & 0 deletions lib/services/manager_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,36 @@ class ManagerAPI {
return jsonDecode(string);
}

String exportSettings() {
final Map<String, dynamic> settings = _prefs
.getKeys()
.fold<Map<String, dynamic>>({}, (Map<String, dynamic> map, String key) {
map[key] = _prefs.get(key);
return map;
});
return jsonEncode(settings);
}

Future<void> importSettings(String settings) async {
final Map<String, dynamic> settingsMap = jsonDecode(settings);
settingsMap.forEach((key, value) {
if (value is bool) {
_prefs.setBool(key, value);
} else if (value is int) {
_prefs.setInt(key, value);
} else if (value is double) {
_prefs.setDouble(key, value);
} else if (value is String) {
_prefs.setString(key, value);
} else if (value is List<dynamic>) {
_prefs.setStringList(
key,
value.map((a) => json.encode(a.toJson())).toList(),
);
}
});
}

void resetAllOptions() {
_prefs.getKeys().where((key) => key.startsWith('patchOption-')).forEach(
(key) {
Expand Down
47 changes: 47 additions & 0 deletions lib/ui/views/settings/settings_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,53 @@ class SettingsViewModel extends BaseViewModel {
notifyListeners();
}

Future<void> exportSettings() async {
try {
final String settings = _managerAPI.exportSettings();
final Directory tempDir = await getTemporaryDirectory();
final String filePath = '${tempDir.path}/manager_settings.json';
final File file = File(filePath);
await file.writeAsString(settings);
final String? result = await FlutterFileDialog.saveFile(
params: SaveFileDialogParams(
sourceFilePath: file.path,
fileName: 'manager_settings.json',
mimeTypesFilter: ['application/json'],
),
);
if (result != null) {
_toast.showBottom(t.settingsView.exportedSettings);
}
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
}
}

Future<void> importSettings() async {
try {
final String? result = await FlutterFileDialog.pickFile(
params: const OpenFileDialogParams(
fileExtensionsFilter: ['json'],
),
);
if (result != null) {
final File inFile = File(result);
final String settings = inFile.readAsStringSync();
inFile.delete();
_managerAPI.importSettings(settings);
_toast.showBottom(t.settingsView.importedSettings);
_toast.showBottom(t.settingsView.restartAppForChanges);
}
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
_toast.showBottom(t.settingsView.jsonSelectorErrorMessage);
}
}

Future<void> exportPatches() async {
try {
final File outFile = File(_managerAPI.storedPatchesFile);
Expand Down
25 changes: 24 additions & 1 deletion lib/ui/widgets/settingsView/settings_export_section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,30 @@ class SExportSection extends StatelessWidget {
return SettingsSection(
title: t.settingsView.exportSectionTitle,
children: <Widget>[
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: Text(
t.settingsView.exportSettingsLabel,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
subtitle: Text(t.settingsView.exportSettingsHint),
onTap: () => _settingsViewModel.exportSettings(),
),
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: Text(
t.settingsView.importSettingsLabel,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
subtitle: Text(t.settingsView.importSettingsHint),
onTap: () => _settingsViewModel.importSettings(),
),
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: Text(
Expand Down Expand Up @@ -114,7 +138,6 @@ class SExportSection extends StatelessWidget {
subtitle: Text(t.settingsView.regenerateKeystoreHint),
onTap: () => _showDeleteKeystoreDialog(context),
),
// SManageKeystorePasswordUI(),
],
);
}
Expand Down

0 comments on commit a45d959

Please sign in to comment.