diff --git a/assets/i18n/en_US.json b/assets/i18n/en_US.json index 86b2713176..47b35a4a08 100644 --- a/assets/i18n/en_US.json +++ b/assets/i18n/en_US.json @@ -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" }, @@ -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", diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 17a3644611..7a9e091d56 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -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 = @@ -259,6 +260,14 @@ class ManagerAPI { await _prefs.setBool('versionCompatibilityCheckEnabled', value); } + bool isRequireSuggestedAppVersionEnabled() { + return _prefs.getBool('requireSuggestedAppVersionEnabled') ?? true; + } + + Future enableRequireSuggestedAppVersionStatus(bool value) async { + await _prefs.setBool('requireSuggestedAppVersionEnabled', value); + } + Future setKeystorePassword(String password) async { await _prefs.setString('keystorePassword', password); } diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart index bca6df76ce..3d1d92ca93 100644 --- a/lib/ui/views/app_selector/app_selector_view.dart +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -28,7 +28,6 @@ class _AppSelectorViewState extends State { icon: const Icon(Icons.sd_storage), onPressed: () { model.selectAppFromStorage(context); - Navigator.of(context).pop(); }, ), body: CustomScrollView( diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index 53c7a23957..00a094dd32 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -70,7 +70,26 @@ class AppSelectorViewModel extends BaseViewModel { return true; } - Future selectApp(ApplicationWithIcon application) async { + Future 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().selectedApp = PatchedApplication( name: application.appName, packageName: application.packageName, @@ -78,8 +97,12 @@ class AppSelectorViewModel extends BaseViewModel { apkFilePath: application.apkFilePath, icon: application.icon, patchDate: DateTime.now(), + isFromStorage: isFromStorage, ); await locator().loadLastSelectedPatches(); + if (context.mounted) { + Navigator.pop(context); + } } Future canSelectInstalled( @@ -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