diff --git a/assets/i18n/en_US.json b/assets/i18n/en_US.json index 6e9d7d46..56021267 100644 --- a/assets/i18n/en_US.json +++ b/assets/i18n/en_US.json @@ -6,6 +6,10 @@ "disabledLabel": "Disabled", "yesButton": "Yes", "noButton": "No", + "rootLabel": "Root", + "nonRootLabel": "Non-root", + "selectInstallMethod": "Select install method", + "selectInstallMethodHint": "Selected patches are compatible with {installMethod} install only. {option} MicroG patch for {otherInstallMethod} install.", "warning": "Warning", "navigationView": { "dashboardTab": "Dashboard", @@ -104,8 +108,8 @@ "exportApkMenuOption": "Export APK", "shareLogMenuOption": "Share log", "installErrorDialogTitle": "Error", - "installErrorDialogText1": "Root install is not possible with the current patches selection.\nRepatch your app or choose non-root install.", - "installErrorDialogText2": "Non-root install is not possible with the current patches selection.\nRepatch your app or choose root install if you have your device rooted.", + "installErrorDialogText1": "Root install is not possible with the current patches selection.\nUnselect MicroG patch to continue.", + "installErrorDialogText2": "Non-root install is not possible with the current patches selection.\nSelect MicroG patch to continue.", "installErrorDialogText3": "Root install is not possible as the original APK was selected from storage.\nSelect an installed app or choose non-root install.", "noExit": "Installer is still running, cannot exit..." }, diff --git a/lib/ui/views/patcher/patcher_viewmodel.dart b/lib/ui/views/patcher/patcher_viewmodel.dart index 4b7bdddd..60fb00d5 100644 --- a/lib/ui/views/patcher/patcher_viewmodel.dart +++ b/lib/ui/views/patcher/patcher_viewmodel.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:injectable/injectable.dart'; @@ -7,6 +9,7 @@ import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/patcher_api.dart'; +import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; @@ -16,8 +19,12 @@ class PatcherViewModel extends BaseViewModel { final NavigationService _navigationService = locator(); final ManagerAPI _managerAPI = locator(); final PatcherAPI _patcherAPI = locator(); + final Toast _toast = locator(); PatchedApplication? selectedApp; List selectedPatches = []; + late bool hasMicroGPatch = selectedPatches.any( + (patch) => patch.name.endsWith('microg-support'), + ); void navigateToAppSelector() { _navigationService.navigateTo(Routes.appSelectorView); @@ -52,9 +59,14 @@ class PatcherViewModel extends BaseViewModel { Future showPatchConfirmationDialog(BuildContext context) async { final bool isValid = await isValidPatchConfig(); + + hasMicroGPatch = selectedPatches.any( + (patch) => patch.name.endsWith('microg-support'), + ); + if (context.mounted) { if (isValid) { - navigateToInstaller(); + askForInstallationMethod(context); } else { return showDialog( context: context, @@ -72,7 +84,7 @@ class PatcherViewModel extends BaseViewModel { label: I18nText('yesButton'), onPressed: () { Navigator.of(context).pop(); - navigateToInstaller(); + askForInstallationMethod(context); }, ) ], @@ -82,6 +94,102 @@ class PatcherViewModel extends BaseViewModel { } } + Future askForInstallationMethod(BuildContext context) { + if (selectedApp!.packageName.contains('youtube')) { + final width = MediaQuery.of(context).size.width; + return showDialog( + context: context, + builder: (context) => AlertDialog( + title: I18nText('selectInstallMethod'), + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + content: I18nText( + !hasMicroGPatch + ? FlutterI18n.translate( + context, + 'selectInstallMethodHint', + translationParams: { + 'installMethod': 'root', + 'option': 'Select', + 'otherInstallMethod': 'non-root', + }, + ) + : FlutterI18n.translate( + context, + 'selectInstallMethodHint', + translationParams: { + 'installMethod': 'non-root', + 'option': 'Unselect', + 'otherInstallMethod': 'root', + }, + ), + ), + actions: [ + TextButton( + onPressed: () { + if (hasMicroGPatch) { + _toast.show( + 'installerView.installErrorDialogText1', + ); + hasMicroGPatch = true; + } else { + Navigator.of(context).pop(); + navigateToInstaller(); + } + }, + style: ButtonStyle( + minimumSize: MaterialStateProperty.all(Size(width, 48)), + foregroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.primary, + ), + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.primary.withOpacity(0.1), + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + ), + ), + ), + child: I18nText('rootLabel'), + ), + const SizedBox(height: 8), + TextButton( + style: ButtonStyle( + minimumSize: MaterialStateProperty.all(Size(width, 48)), + foregroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.primary, + ), + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.primary.withOpacity(0.1), + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + ), + ), + ), + child: I18nText('nonRootLabel'), + onPressed: () { + if (!hasMicroGPatch) { + _toast.show( + 'installerView.installErrorDialogText2', + ); + hasMicroGPatch = false; + } else { + Navigator.of(context).pop(); + navigateToInstaller(); + } + }, + ) + ], + ), + ); + } else { + navigateToInstaller(); + return Future.value(); + } + } + String getAppSelectionString() { String text = '${selectedApp!.name} (${selectedApp!.packageName})'; if (text.length > 32) {