2022-09-13 18:46:22 +02:00
|
|
|
import 'dart:io';
|
2022-11-09 08:36:04 +01:00
|
|
|
import 'package:cr_file_saver/file_saver.dart';
|
2022-09-08 13:09:12 +02:00
|
|
|
import 'package:device_info_plus/device_info_plus.dart';
|
2022-11-09 08:36:04 +01:00
|
|
|
import 'package:file_picker/file_picker.dart';
|
2023-03-05 10:12:46 +01:00
|
|
|
import 'package:flutter/foundation.dart';
|
2023-08-15 11:05:27 +02:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
2022-09-13 18:46:22 +02:00
|
|
|
import 'package:logcat/logcat.dart';
|
|
|
|
import 'package:path_provider/path_provider.dart';
|
2022-08-12 20:07:16 +02:00
|
|
|
import 'package:revanced_manager/app/app.locator.dart';
|
|
|
|
import 'package:revanced_manager/app/app.router.dart';
|
2022-09-05 04:32:36 +02:00
|
|
|
import 'package:revanced_manager/services/manager_api.dart';
|
2022-10-14 22:22:10 +02:00
|
|
|
import 'package:revanced_manager/services/toast.dart';
|
2022-11-09 08:36:04 +01:00
|
|
|
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
2023-08-15 11:05:27 +02:00
|
|
|
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
|
2023-02-17 12:53:23 +01:00
|
|
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_language.dart';
|
|
|
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_theme.dart';
|
2023-08-15 11:05:27 +02:00
|
|
|
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
|
2022-09-13 18:46:22 +02:00
|
|
|
import 'package:share_extend/share_extend.dart';
|
2022-08-10 14:30:28 +02:00
|
|
|
import 'package:stacked/stacked.dart';
|
2022-08-12 20:07:16 +02:00
|
|
|
import 'package:stacked_services/stacked_services.dart';
|
2022-09-08 13:09:12 +02:00
|
|
|
|
2022-08-10 14:30:28 +02:00
|
|
|
class SettingsViewModel extends BaseViewModel {
|
2023-07-10 14:36:50 +02:00
|
|
|
final NavigationService _navigationService = locator<NavigationService>();
|
2022-09-05 04:32:36 +02:00
|
|
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
2023-08-15 11:05:27 +02:00
|
|
|
final PatchesSelectorViewModel _patchesSelectorViewModel =
|
|
|
|
PatchesSelectorViewModel();
|
|
|
|
final PatcherViewModel _patcherViewModel = locator<PatcherViewModel>();
|
2022-10-14 22:22:10 +02:00
|
|
|
final Toast _toast = locator<Toast>();
|
2022-08-12 20:07:16 +02:00
|
|
|
|
2022-11-12 16:55:33 +01:00
|
|
|
final SUpdateLanguage sUpdateLanguage = SUpdateLanguage();
|
|
|
|
final SUpdateTheme sUpdateTheme = SUpdateTheme();
|
2022-08-12 20:07:16 +02:00
|
|
|
|
2022-09-05 16:30:26 +02:00
|
|
|
void navigateToContributors() {
|
|
|
|
_navigationService.navigateTo(Routes.contributorsView);
|
|
|
|
}
|
|
|
|
|
2023-08-03 22:23:56 +02:00
|
|
|
bool isPatchesAutoUpdate() {
|
|
|
|
return _managerAPI.isPatchesAutoUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void setPatchesAutoUpdate(bool value) {
|
|
|
|
_managerAPI.setPatchesAutoUpdate(value);
|
|
|
|
notifyListeners();
|
|
|
|
}
|
|
|
|
|
2023-08-15 11:05:27 +02:00
|
|
|
bool isPatchesChangeEnabled() {
|
|
|
|
return _managerAPI.isPatchesChangeEnabled();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> showPatchesChangeEnableDialog(
|
|
|
|
bool value,
|
|
|
|
BuildContext context,
|
|
|
|
) async {
|
|
|
|
if (value) {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) => AlertDialog(
|
|
|
|
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
|
|
|
title: I18nText('warning'),
|
|
|
|
content: I18nText(
|
|
|
|
'settingsView.enablePatchesSelectionWarningText',
|
|
|
|
child: const Text(
|
|
|
|
'',
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 16,
|
|
|
|
fontWeight: FontWeight.w500,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
actions: [
|
|
|
|
CustomMaterialButton(
|
|
|
|
isFilled: false,
|
2023-09-30 20:10:45 +02:00
|
|
|
label: I18nText('yesButton'),
|
2023-08-15 11:05:27 +02:00
|
|
|
onPressed: () {
|
2023-09-30 20:10:45 +02:00
|
|
|
_managerAPI.setChangingToggleModified(true);
|
|
|
|
_managerAPI.setPatchesChangeEnabled(true);
|
2023-08-15 11:05:27 +02:00
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
CustomMaterialButton(
|
2023-09-30 20:10:45 +02:00
|
|
|
label: I18nText('noButton'),
|
2023-08-15 11:05:27 +02:00
|
|
|
onPressed: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) => AlertDialog(
|
|
|
|
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
|
|
|
title: I18nText('warning'),
|
|
|
|
content: I18nText(
|
|
|
|
'settingsView.disablePatchesSelectionWarningText',
|
|
|
|
child: const Text(
|
|
|
|
'',
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 16,
|
|
|
|
fontWeight: FontWeight.w500,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
actions: [
|
|
|
|
CustomMaterialButton(
|
|
|
|
isFilled: false,
|
|
|
|
label: I18nText('noButton'),
|
|
|
|
onPressed: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
CustomMaterialButton(
|
|
|
|
label: I18nText('yesButton'),
|
|
|
|
onPressed: () {
|
|
|
|
_managerAPI.setChangingToggleModified(true);
|
|
|
|
_patchesSelectorViewModel.selectDefaultPatches();
|
|
|
|
_managerAPI.setPatchesChangeEnabled(false);
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-15 19:05:45 +01:00
|
|
|
bool areUniversalPatchesEnabled() {
|
|
|
|
return _managerAPI.areUniversalPatchesEnabled();
|
|
|
|
}
|
|
|
|
|
|
|
|
void showUniversalPatches(bool value) {
|
|
|
|
_managerAPI.enableUniversalPatchesStatus(value);
|
|
|
|
notifyListeners();
|
|
|
|
}
|
|
|
|
|
2022-11-01 10:56:15 +01:00
|
|
|
bool areExperimentalPatchesEnabled() {
|
|
|
|
return _managerAPI.areExperimentalPatchesEnabled();
|
|
|
|
}
|
|
|
|
|
|
|
|
void useExperimentalPatches(bool value) {
|
|
|
|
_managerAPI.enableExperimentalPatchesStatus(value);
|
|
|
|
notifyListeners();
|
|
|
|
}
|
|
|
|
|
2022-10-16 20:52:07 +02:00
|
|
|
void deleteKeystore() {
|
|
|
|
_managerAPI.deleteKeystore();
|
2023-07-31 16:53:23 +02:00
|
|
|
_toast.showBottom('settingsView.regeneratedKeystore');
|
2022-10-16 20:52:07 +02:00
|
|
|
notifyListeners();
|
|
|
|
}
|
|
|
|
|
2022-10-16 21:11:20 +02:00
|
|
|
void deleteTempDir() {
|
|
|
|
_managerAPI.deleteTempFolder();
|
|
|
|
_toast.showBottom('settingsView.deletedTempDir');
|
|
|
|
notifyListeners();
|
|
|
|
}
|
|
|
|
|
2022-11-09 08:36:04 +01:00
|
|
|
Future<void> exportPatches() async {
|
|
|
|
try {
|
2023-01-30 13:35:06 +01:00
|
|
|
final File outFile = File(_managerAPI.storedPatchesFile);
|
2022-11-09 08:36:04 +01:00
|
|
|
if (outFile.existsSync()) {
|
2023-07-10 14:36:50 +02:00
|
|
|
final String dateTime =
|
|
|
|
DateTime.now().toString().replaceAll(' ', '_').split('.').first;
|
2023-03-05 10:12:46 +01:00
|
|
|
await CRFileSaver.saveFileWithDialog(
|
|
|
|
SaveFileDialogParams(
|
|
|
|
sourceFilePath: outFile.path,
|
|
|
|
destinationFileName: 'selected_patches_$dateTime.json',
|
|
|
|
),
|
|
|
|
);
|
2023-01-30 13:03:55 +01:00
|
|
|
_toast.showBottom('settingsView.exportedPatches');
|
2022-11-09 08:36:04 +01:00
|
|
|
} else {
|
2023-01-30 13:03:55 +01:00
|
|
|
_toast.showBottom('settingsView.noExportFileFound');
|
2022-11-09 08:36:04 +01:00
|
|
|
}
|
2023-03-05 10:12:46 +01:00
|
|
|
} on Exception catch (e) {
|
|
|
|
if (kDebugMode) {
|
|
|
|
print(e);
|
|
|
|
}
|
2022-11-09 08:36:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-15 11:05:27 +02:00
|
|
|
Future<void> importPatches(BuildContext context) async {
|
|
|
|
if (isPatchesChangeEnabled()) {
|
|
|
|
try {
|
|
|
|
final FilePickerResult? result = await FilePicker.platform.pickFiles(
|
|
|
|
type: FileType.custom,
|
|
|
|
allowedExtensions: ['json'],
|
|
|
|
);
|
|
|
|
if (result != null && result.files.single.path != null) {
|
|
|
|
final File inFile = File(result.files.single.path!);
|
|
|
|
inFile.copySync(_managerAPI.storedPatchesFile);
|
|
|
|
inFile.delete();
|
|
|
|
if (_patcherViewModel.selectedApp != null) {
|
|
|
|
_patcherViewModel.loadLastSelectedPatches();
|
|
|
|
}
|
|
|
|
_toast.showBottom('settingsView.importedPatches');
|
2022-11-09 08:36:04 +01:00
|
|
|
}
|
2023-08-15 11:05:27 +02:00
|
|
|
} on Exception catch (e) {
|
|
|
|
if (kDebugMode) {
|
|
|
|
print(e);
|
|
|
|
}
|
|
|
|
_toast.showBottom('settingsView.jsonSelectorErrorMessage');
|
2023-03-05 10:12:46 +01:00
|
|
|
}
|
2023-08-15 11:05:27 +02:00
|
|
|
} else {
|
|
|
|
_managerAPI.showPatchesChangeWarningDialog(context);
|
2022-11-09 08:36:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-10 14:36:50 +02:00
|
|
|
Future<void> exportKeystore() async {
|
2023-04-18 11:38:10 +02:00
|
|
|
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);
|
2023-07-10 14:36:50 +02:00
|
|
|
|
2023-04-18 11:38:10 +02:00
|
|
|
_toast.showBottom('settingsView.importedKeystore');
|
|
|
|
}
|
|
|
|
} on Exception catch (e) {
|
|
|
|
if (kDebugMode) {
|
|
|
|
print(e);
|
|
|
|
}
|
|
|
|
_toast.showBottom('settingsView.keystoreSelectorErrorMessage');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-09 08:36:04 +01:00
|
|
|
void resetSelectedPatches() {
|
|
|
|
_managerAPI.resetLastSelectedPatches();
|
|
|
|
_toast.showBottom('settingsView.resetStoredPatches');
|
|
|
|
}
|
|
|
|
|
2022-09-08 13:09:12 +02:00
|
|
|
Future<int> getSdkVersion() async {
|
2023-01-30 13:35:06 +01:00
|
|
|
final AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
|
2023-04-18 16:15:29 +02:00
|
|
|
return info.version.sdkInt;
|
2022-09-08 13:09:12 +02:00
|
|
|
}
|
2022-09-13 18:46:22 +02:00
|
|
|
|
2022-10-16 22:28:50 +02:00
|
|
|
Future<void> deleteLogs() async {
|
2023-01-30 13:35:06 +01:00
|
|
|
final Directory appCacheDir = await getTemporaryDirectory();
|
|
|
|
final Directory logsDir = Directory('${appCacheDir.path}/logs');
|
2022-10-16 22:28:50 +02:00
|
|
|
if (logsDir.existsSync()) {
|
|
|
|
logsDir.deleteSync(recursive: true);
|
|
|
|
}
|
|
|
|
_toast.showBottom('settingsView.deletedLogs');
|
|
|
|
}
|
|
|
|
|
2022-09-13 18:46:22 +02:00
|
|
|
Future<void> exportLogcatLogs() async {
|
2023-01-30 13:35:06 +01:00
|
|
|
final Directory appCache = await getTemporaryDirectory();
|
|
|
|
final Directory logDir = Directory('${appCache.path}/logs');
|
2022-09-13 18:46:22 +02:00
|
|
|
logDir.createSync();
|
2023-01-30 13:35:06 +01:00
|
|
|
final String dateTime = DateTime.now()
|
2022-09-13 18:46:22 +02:00
|
|
|
.toIso8601String()
|
|
|
|
.replaceAll('-', '')
|
|
|
|
.replaceAll(':', '')
|
|
|
|
.replaceAll('T', '')
|
|
|
|
.replaceAll('.', '');
|
2023-01-30 13:35:06 +01:00
|
|
|
final File logcat =
|
|
|
|
File('${logDir.path}/revanced-manager_logcat_$dateTime.log');
|
|
|
|
final String logs = await Logcat.execute();
|
2022-09-13 18:46:22 +02:00
|
|
|
logcat.writeAsStringSync(logs);
|
|
|
|
ShareExtend.share(logcat.path, 'file');
|
|
|
|
}
|
2022-08-10 14:30:28 +02:00
|
|
|
}
|