feat: add option to import/export keystore (#776)

* feat: add option to import/export keystore

* change the order of import/export keystore buttons

* feat: add option to change the keystore password
This commit is contained in:
Sebok Andras
2023-04-18 11:38:10 +02:00
committed by GitHub
parent 3b677f8ae3
commit dca2d4fe12
8 changed files with 193 additions and 6 deletions

View File

@ -0,0 +1,84 @@
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/ui/widgets/settingsView/custom_text_field.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
import 'package:stacked/stacked.dart';
class SManageKeystorePassword extends BaseViewModel {
final ManagerAPI _managerAPI = locator<ManagerAPI>();
final TextEditingController _keystorePasswordController = TextEditingController();
Future<void> showKeystoreDialog(BuildContext context) async {
final String keystorePasswordText = _managerAPI.getKeystorePassword();
_keystorePasswordController.text = keystorePasswordText;
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: Row(
children: <Widget>[
I18nText('settingsView.selectKeystorePassword'),
const Spacer(),
IconButton(
icon: const Icon(Icons.manage_history_outlined),
onPressed: () =>_keystorePasswordController.text = _managerAPI.defaultKeystorePassword,
color: Theme.of(context).colorScheme.secondary,
)
],
),
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
content: SingleChildScrollView(
child: Column(
children: <Widget>[
CustomTextField(
inputController: _keystorePasswordController,
label: I18nText('settingsView.selectKeystorePassword'),
hint: "",
onChanged: (value) => notifyListeners(),
),
],
),
),
actions: <Widget>[
CustomMaterialButton(
isFilled: false,
label: I18nText('cancelButton'),
onPressed: () {
_keystorePasswordController.clear();
Navigator.of(context).pop();
},
),
CustomMaterialButton(
label: I18nText('okButton'),
onPressed: () {
String passwd = _keystorePasswordController.text;
_managerAPI.setKeystorePassword(passwd);
Navigator.of(context).pop();
},
)
],
),
);
}
}
final sManageKeystorePassword = SManageKeystorePassword();
class SManageKeystorePasswordUI extends StatelessWidget {
const SManageKeystorePasswordUI({super.key});
@override
Widget build(BuildContext context) {
return SettingsTileDialog(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
title: 'settingsView.selectKeystorePassword',
subtitle: 'settingsView.selectKeystorePasswordHint',
onTap: () => sManageKeystorePassword.showKeystoreDialog(context),
);
}
}

View File

@ -104,6 +104,46 @@ class SettingsViewModel extends BaseViewModel {
}
}
Future<void> exportKeystore() async {
try {
final File outFile = File(_managerAPI.keystoreFile);
if (outFile.existsSync()) {
final String dateTime =
DateTime.now().toString().replaceAll(' ', '_').split('.').first;
await CRFileSaver.saveFileWithDialog(
SaveFileDialogParams(
sourceFilePath: outFile.path,
destinationFileName: 'keystore_$dateTime.keystore',
),
);
_toast.showBottom('settingsView.exportedKeystore');
} else {
_toast.showBottom('settingsView.noKeystoreExportFileFound');
}
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<void> importKeystore() async {
try {
final FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null && result.files.single.path != null) {
final File inFile = File(result.files.single.path!);
inFile.copySync(_managerAPI.keystoreFile);
_toast.showBottom('settingsView.importedKeystore');
}
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
_toast.showBottom('settingsView.keystoreSelectorErrorMessage');
}
}
void resetSelectedPatches() {
_managerAPI.resetLastSelectedPatches();
_toast.showBottom('settingsView.resetStoredPatches');

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_patches.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_universal_patches.dart';
@ -22,6 +23,7 @@ class SAdvancedSection extends StatelessWidget {
children: <Widget>[
SManageApiUrlUI(),
SManageSourcesUI(),
// SManageKeystorePasswordUI(),
SExperimentalUniversalPatches(),
SExperimentalPatches(),
ListTile(

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
final _settingsViewModel = SettingsViewModel();
@ -43,6 +44,40 @@ class SExportSection extends StatelessWidget {
subtitle: I18nText('settingsView.importPatchesHint'),
onTap: () => _settingsViewModel.importPatches(),
),
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.exportKeystoreLabel',
child: const Text(
'',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
),
subtitle: I18nText('settingsView.exportKeystoreHint'),
onTap: () => _settingsViewModel.exportKeystore(),
),
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.importKeystoreLabel',
child: const Text(
'',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
),
subtitle: I18nText('settingsView.importKeystoreHint'),
onTap: () {
_settingsViewModel.importKeystore();
final sManageKeystorePassword = SManageKeystorePassword();
sManageKeystorePassword.showKeystoreDialog(context);
},
),
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(