Skip to content

Commit

Permalink
feat: Disable selection of un-suggested app version by default (#1471)
Browse files Browse the repository at this point in the history
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
  • Loading branch information
TheAabedKhan and oSumAtrIX committed Nov 8, 2023
1 parent e7d8285 commit 70b2ee0
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 28 deletions.
6 changes: 6 additions & 0 deletions assets/i18n/en_US.json
Expand Up @@ -111,6 +111,8 @@

"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",
"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"
},
Expand Down Expand Up @@ -234,8 +236,12 @@
"autoUpdatePatchesHint": "Automatically update patches to the latest version",
"universalPatchesLabel": "Show universal patches",
"universalPatchesHint": "Display all apps and universal patches (may slow down the app list)",

"versionCompatibilityCheckLabel": "Version compatibility check",
"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",
"snackbarMessage": "Copied to clipboard",
Expand Down
9 changes: 9 additions & 0 deletions lib/services/manager_api.dart
Expand Up @@ -34,6 +34,7 @@ class ManagerAPI {
Patch? selectedPatch;
BuildContext? ctx;
bool isRooted = false;
bool suggestedAppVersionSelected = true;
bool isDynamicThemeAvailable = false;
String storedPatchesFile = '/selected-patches.json';
String keystoreFile =
Expand Down Expand Up @@ -259,6 +260,14 @@ class ManagerAPI {
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 {
await _prefs.setString('keystorePassword', password);
}
Expand Down
1 change: 0 additions & 1 deletion lib/ui/views/app_selector/app_selector_view.dart
Expand Up @@ -28,7 +28,6 @@ class _AppSelectorViewState extends State<AppSelectorView> {
icon: const Icon(Icons.sd_storage),
onPressed: () {
model.selectAppFromStorage(context);
Navigator.of(context).pop();
},
),
body: CustomScrollView(
Expand Down
103 changes: 76 additions & 27 deletions lib/ui/views/app_selector/app_selector_viewmodel.dart
Expand Up @@ -70,16 +70,39 @@ class AppSelectorViewModel extends BaseViewModel {
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(
name: application.appName,
packageName: application.packageName,
version: application.versionName!,
apkFilePath: application.apkFilePath,
icon: application.icon,
patchDate: DateTime.now(),
isFromStorage: isFromStorage,
);
await locator<PatcherViewModel>().loadLastSelectedPatches();
if (context.mounted) {
Navigator.pop(context);
}
}

Future<void> canSelectInstalled(
Expand All @@ -89,23 +112,60 @@ class AppSelectorViewModel extends BaseViewModel {
final app =
await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?;
if (app != null) {
if (await checkSplitApk(packageName) && !isRooted) {
if (context.mounted) {
return showSelectFromStorageDialog(context);
}
} else if (!await checkSplitApk(packageName) || isRooted) {
await selectApp(app);
final bool isSplitApk = await checkSplitApk(packageName);
if (isRooted || !isSplitApk) {
if (context.mounted) {
Navigator.pop(context);
await selectApp(context, app);
}
final List<Option> requiredNullOptions = getNullRequiredOptions(locator<PatcherViewModel>().selectedPatches, packageName);
if(requiredNullOptions.isNotEmpty){
final List<Option> requiredNullOptions = getNullRequiredOptions(
locator<PatcherViewModel>().selectedPatches,
packageName,
);
if (requiredNullOptions.isNotEmpty) {
locator<PatcherViewModel>().showRequiredOptionDialog();
}
} else {
if (context.mounted) {
return showSelectFromStorageDialog(context);
}
}
}
}

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 {
return showDialog(
context: context,
Expand Down Expand Up @@ -145,12 +205,10 @@ class AppSelectorViewModel extends BaseViewModel {
),
const SizedBox(height: 30),
CustomMaterialButton(
onPressed: () => selectAppFromStorage(context).then(
(_) {
Navigator.pop(context);
Navigator.pop(context);
},
),
onPressed: () async {
Navigator.pop(context);
await selectAppFromStorage(context);
},
label: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expand Down Expand Up @@ -203,17 +261,8 @@ class AppSelectorViewModel extends BaseViewModel {
apkFile.path,
true,
) as ApplicationWithIcon?;
if (application != null) {
locator<PatcherViewModel>().selectedApp = PatchedApplication(
name: application.appName,
packageName: application.packageName,
version: application.versionName!,
apkFilePath: result,
icon: application.icon,
patchDate: DateTime.now(),
isFromStorage: true,
);
locator<PatcherViewModel>().loadLastSelectedPatches();
if (application != null && context.mounted) {
await selectApp(context, application, true);
}
}
} on Exception catch (e) {
Expand Down
51 changes: 51 additions & 0 deletions lib/ui/views/settings/settings_viewmodel.dart
Expand Up @@ -140,6 +140,57 @@ class SettingsViewModel extends BaseViewModel {
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() {
_managerAPI.deleteKeystore();
_toast.showBottom('settingsView.regeneratedKeystore');
Expand Down
2 changes: 2 additions & 0 deletions lib/ui/widgets/settingsView/settings_advanced_section.dart
Expand Up @@ -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/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_require_suggested_app_version.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_version_compatibility_check.dart';
Expand All @@ -20,6 +21,7 @@ class SAdvancedSection extends StatelessWidget {
children: const <Widget>[
SAutoUpdatePatches(),
SEnablePatchesSelection(),
SRequireSuggestedAppVersion(),
SVersionCompatibilityCheck(),
SUniversalPatches(),
SManageSourcesUI(),
Expand Down
@@ -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(() {});
},
);
}
}

0 comments on commit 70b2ee0

Please sign in to comment.