feat: Disable selection of un-suggested app version by default (#1471)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
aAbed 2023-11-08 04:37:14 +05:45 committed by oSumAtrIX
parent e7d82850c9
commit 70b2ee0a84
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
7 changed files with 182 additions and 29 deletions

View File

@ -111,6 +111,8 @@
"downloadToast": "Download function is not available yet", "downloadToast": "Download function is not available yet",
"requireSuggestedAppVersionDialogText": "The version of the app you have selected does not match the suggested version. Please select the app that matches the suggested version.\n\nSelected version: v{selected}\nSuggested version: v{suggested}\n\n.To proceed anyway, disable \"Require suggested app version\" in the settings.",
"featureNotAvailable": "Feature not implemented", "featureNotAvailable": "Feature not implemented",
"featureNotAvailableText": "This application is a split APK and cannot be selected. Unfortunately, this feature is only available for rooted users at the moment. However, you can still install the application by selecting its APK files from your device's storage instead" "featureNotAvailableText": "This application is a split APK and cannot be selected. Unfortunately, this feature is only available for rooted users at the moment. However, you can still install the application by selecting its APK files from your device's storage instead"
}, },
@ -234,8 +236,12 @@
"autoUpdatePatchesHint": "Automatically update patches to the latest version", "autoUpdatePatchesHint": "Automatically update patches to the latest version",
"universalPatchesLabel": "Show universal patches", "universalPatchesLabel": "Show universal patches",
"universalPatchesHint": "Display all apps and universal patches (may slow down the app list)", "universalPatchesHint": "Display all apps and universal patches (may slow down the app list)",
"versionCompatibilityCheckLabel": "Version compatibility check", "versionCompatibilityCheckLabel": "Version compatibility check",
"versionCompatibilityCheckHint": "Restricts patches to supported app versions", "versionCompatibilityCheckHint": "Restricts patches to supported app versions",
"requireSuggestedAppVersionLabel": "Require suggested app version",
"requireSuggestedAppVersionHint": "Enforce selection of suggested app version",
"requireSuggestedAppVersionDialogText": "Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?",
"aboutLabel": "About", "aboutLabel": "About",
"snackbarMessage": "Copied to clipboard", "snackbarMessage": "Copied to clipboard",

View File

@ -34,6 +34,7 @@ class ManagerAPI {
Patch? selectedPatch; Patch? selectedPatch;
BuildContext? ctx; BuildContext? ctx;
bool isRooted = false; bool isRooted = false;
bool suggestedAppVersionSelected = true;
bool isDynamicThemeAvailable = false; bool isDynamicThemeAvailable = false;
String storedPatchesFile = '/selected-patches.json'; String storedPatchesFile = '/selected-patches.json';
String keystoreFile = String keystoreFile =
@ -259,6 +260,14 @@ class ManagerAPI {
await _prefs.setBool('versionCompatibilityCheckEnabled', value); await _prefs.setBool('versionCompatibilityCheckEnabled', value);
} }
bool isRequireSuggestedAppVersionEnabled() {
return _prefs.getBool('requireSuggestedAppVersionEnabled') ?? true;
}
Future<void> enableRequireSuggestedAppVersionStatus(bool value) async {
await _prefs.setBool('requireSuggestedAppVersionEnabled', value);
}
Future<void> setKeystorePassword(String password) async { Future<void> setKeystorePassword(String password) async {
await _prefs.setString('keystorePassword', password); await _prefs.setString('keystorePassword', password);
} }

View File

@ -28,7 +28,6 @@ class _AppSelectorViewState extends State<AppSelectorView> {
icon: const Icon(Icons.sd_storage), icon: const Icon(Icons.sd_storage),
onPressed: () { onPressed: () {
model.selectAppFromStorage(context); model.selectAppFromStorage(context);
Navigator.of(context).pop();
}, },
), ),
body: CustomScrollView( body: CustomScrollView(

View File

@ -70,7 +70,26 @@ class AppSelectorViewModel extends BaseViewModel {
return true; return true;
} }
Future<void> selectApp(ApplicationWithIcon application) async { Future<void> selectApp(
BuildContext context,
ApplicationWithIcon application, [
bool isFromStorage = false,
]) async {
final String suggestedVersion =
getSuggestedVersion(application.packageName);
if (application.versionName != suggestedVersion && suggestedVersion.isNotEmpty) {
_managerAPI.suggestedAppVersionSelected = false;
if (_managerAPI.isRequireSuggestedAppVersionEnabled() &&
context.mounted) {
return showRequireSuggestedAppVersionDialog(
context,
application.versionName!,
suggestedVersion,
);
}
} else {
_managerAPI.suggestedAppVersionSelected = true;
}
locator<PatcherViewModel>().selectedApp = PatchedApplication( locator<PatcherViewModel>().selectedApp = PatchedApplication(
name: application.appName, name: application.appName,
packageName: application.packageName, packageName: application.packageName,
@ -78,8 +97,12 @@ class AppSelectorViewModel extends BaseViewModel {
apkFilePath: application.apkFilePath, apkFilePath: application.apkFilePath,
icon: application.icon, icon: application.icon,
patchDate: DateTime.now(), patchDate: DateTime.now(),
isFromStorage: isFromStorage,
); );
await locator<PatcherViewModel>().loadLastSelectedPatches(); await locator<PatcherViewModel>().loadLastSelectedPatches();
if (context.mounted) {
Navigator.pop(context);
}
} }
Future<void> canSelectInstalled( Future<void> canSelectInstalled(
@ -89,23 +112,60 @@ class AppSelectorViewModel extends BaseViewModel {
final app = final app =
await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?; await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?;
if (app != null) { if (app != null) {
if (await checkSplitApk(packageName) && !isRooted) { final bool isSplitApk = await checkSplitApk(packageName);
if (isRooted || !isSplitApk) {
if (context.mounted) {
await selectApp(context, app);
}
final List<Option> requiredNullOptions = getNullRequiredOptions(
locator<PatcherViewModel>().selectedPatches,
packageName,
);
if (requiredNullOptions.isNotEmpty) {
locator<PatcherViewModel>().showRequiredOptionDialog();
}
} else {
if (context.mounted) { if (context.mounted) {
return showSelectFromStorageDialog(context); return showSelectFromStorageDialog(context);
} }
} else if (!await checkSplitApk(packageName) || isRooted) {
await selectApp(app);
if (context.mounted) {
Navigator.pop(context);
}
final List<Option> requiredNullOptions = getNullRequiredOptions(locator<PatcherViewModel>().selectedPatches, packageName);
if(requiredNullOptions.isNotEmpty){
locator<PatcherViewModel>().showRequiredOptionDialog();
}
} }
} }
} }
Future showRequireSuggestedAppVersionDialog(
BuildContext context,
String selectedVersion,
String suggestedVersion,
) async {
return showDialog(
context: context,
builder: (context) => AlertDialog(
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
title: I18nText('warning'),
content: I18nText(
'appSelectorView.requireSuggestedAppVersionDialogText',
translationParams: {
'suggested': suggestedVersion,
'selected': selectedVersion,
},
child: const Text(
'',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
actions: [
CustomMaterialButton(
label: I18nText('okButton'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
}
Future showSelectFromStorageDialog(BuildContext context) async { Future showSelectFromStorageDialog(BuildContext context) async {
return showDialog( return showDialog(
context: context, context: context,
@ -145,12 +205,10 @@ class AppSelectorViewModel extends BaseViewModel {
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
CustomMaterialButton( CustomMaterialButton(
onPressed: () => selectAppFromStorage(context).then( onPressed: () async {
(_) { Navigator.pop(context);
Navigator.pop(context); await selectAppFromStorage(context);
Navigator.pop(context); },
},
),
label: Row( label: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -203,17 +261,8 @@ class AppSelectorViewModel extends BaseViewModel {
apkFile.path, apkFile.path,
true, true,
) as ApplicationWithIcon?; ) as ApplicationWithIcon?;
if (application != null) { if (application != null && context.mounted) {
locator<PatcherViewModel>().selectedApp = PatchedApplication( await selectApp(context, application, true);
name: application.appName,
packageName: application.packageName,
version: application.versionName!,
apkFilePath: result,
icon: application.icon,
patchDate: DateTime.now(),
isFromStorage: true,
);
locator<PatcherViewModel>().loadLastSelectedPatches();
} }
} }
} on Exception catch (e) { } on Exception catch (e) {

View File

@ -140,6 +140,57 @@ class SettingsViewModel extends BaseViewModel {
notifyListeners(); notifyListeners();
} }
bool isRequireSuggestedAppVersionEnabled() {
return _managerAPI.isRequireSuggestedAppVersionEnabled();
}
Future<void>? showRequireSuggestedAppVersionDialog(
BuildContext context, bool value) {
if (!value) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
title: I18nText('warning'),
content: I18nText(
'settingsView.requireSuggestedAppVersionDialogText',
child: const Text(
'',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
actions: [
CustomMaterialButton(
isFilled: false,
label: I18nText('yesButton'),
onPressed: () {
_managerAPI.enableRequireSuggestedAppVersionStatus(false);
Navigator.of(context).pop();
},
),
CustomMaterialButton(
label: I18nText('noButton'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
} else {
_managerAPI.enableRequireSuggestedAppVersionStatus(true);
if (!_managerAPI.suggestedAppVersionSelected) {
_patcherViewModel.selectedApp = null;
}
return null;
}
}
void deleteKeystore() { void deleteKeystore() {
_managerAPI.deleteKeystore(); _managerAPI.deleteKeystore();
_toast.showBottom('settingsView.regeneratedKeystore'); _toast.showBottom('settingsView.regeneratedKeystore');

View File

@ -5,6 +5,7 @@ import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_man
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_enable_patches_selection.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_enable_patches_selection.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_require_suggested_app_version.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_universal_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_universal_patches.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_version_compatibility_check.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_version_compatibility_check.dart';
@ -20,6 +21,7 @@ class SAdvancedSection extends StatelessWidget {
children: const <Widget>[ children: const <Widget>[
SAutoUpdatePatches(), SAutoUpdatePatches(),
SEnablePatchesSelection(), SEnablePatchesSelection(),
SRequireSuggestedAppVersion(),
SVersionCompatibilityCheck(), SVersionCompatibilityCheck(),
SUniversalPatches(), SUniversalPatches(),
SManageSourcesUI(), SManageSourcesUI(),

View File

@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
class SRequireSuggestedAppVersion extends StatefulWidget {
const SRequireSuggestedAppVersion({super.key});
@override
State<SRequireSuggestedAppVersion> createState() => _SRequireSuggestedAppVersionState();
}
final _settingsViewModel = SettingsViewModel();
class _SRequireSuggestedAppVersionState extends State<SRequireSuggestedAppVersion> {
@override
Widget build(BuildContext context) {
return SwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.requireSuggestedAppVersionLabel',
child: const Text(
'',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
),
subtitle: I18nText('settingsView.requireSuggestedAppVersionHint'),
value: _settingsViewModel.isRequireSuggestedAppVersionEnabled(),
onChanged: (value) async {
await _settingsViewModel.showRequireSuggestedAppVersionDialog(context, value);
setState(() {});
},
);
}
}