diff --git a/assets/i18n/en.json b/assets/i18n/en.json index 80dab204e3..8b15f38eb7 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -42,7 +42,9 @@ }, "patcherView": { "widgetTitle": "Patcher", - "patchButton": "Patch" + "patchButton": "Patch", + "patchDialogTitle": "Warning", + "patchDialogText": "You have selected a resource patch and a split APK installation was detected so patching errors can occur.\nAre you sure you want to proceed with patching a split base APK?" }, "appSelectorCard": { "widgetTitle": "Select application", diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index 74f5e1a0ad..970a7e2d2c 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -82,6 +82,24 @@ class PatcherAPI { .toList(); } + Future needsIntegrations(List selectedPatches) async { + return selectedPatches.any( + (patch) => patch.dependencies.contains('integrations'), + ); + } + + Future needsResourcePatching(List selectedPatches) async { + return selectedPatches.any( + (patch) => patch.dependencies.any((dep) => dep.contains('resource-')), + ); + } + + Future needsSettingsPatch(List selectedPatches) async { + return selectedPatches.any( + (patch) => patch.dependencies.contains('settings'), + ); + } + Future getOriginalFilePath( String packageName, String originalFilePath, @@ -101,15 +119,9 @@ class PatcherAPI { String originalFilePath, List selectedPatches, ) async { - bool mergeIntegrations = selectedPatches.any( - (patch) => patch.dependencies.contains('integrations'), - ); - bool resourcePatching = selectedPatches.any( - (patch) => patch.dependencies.any((dep) => dep.contains('resource-')), - ); - bool includeSettings = selectedPatches.any( - (patch) => patch.dependencies.contains('settings'), - ); + bool mergeIntegrations = await needsIntegrations(selectedPatches); + bool resourcePatching = await needsResourcePatching(selectedPatches); + bool includeSettings = await needsSettingsPatch(selectedPatches); if (includeSettings) { try { Patch? settingsPatch = _patches.firstWhereOrNull( diff --git a/lib/ui/views/patcher/patcher_view.dart b/lib/ui/views/patcher/patcher_view.dart index c7a678830a..edc286a065 100644 --- a/lib/ui/views/patcher/patcher_view.dart +++ b/lib/ui/views/patcher/patcher_view.dart @@ -22,7 +22,7 @@ class PatcherView extends StatelessWidget { child: FloatingActionButton.extended( label: I18nText('patcherView.patchButton'), icon: const Icon(Icons.build), - onPressed: () => model.navigateToInstaller(), + onPressed: () => model.showPatchConfirmationDialog(context), ), ), body: CustomScrollView( diff --git a/lib/ui/views/patcher/patcher_viewmodel.dart b/lib/ui/views/patcher/patcher_viewmodel.dart index 2fc9ffe9e2..a6ca8ceda9 100644 --- a/lib/ui/views/patcher/patcher_viewmodel.dart +++ b/lib/ui/views/patcher/patcher_viewmodel.dart @@ -1,14 +1,20 @@ +import 'package:device_apps/device_apps.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:injectable/injectable.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; +import 'package:revanced_manager/services/patcher_api.dart'; +import 'package:revanced_manager/ui/widgets/installerView/custom_material_button.dart'; import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; @lazySingleton class PatcherViewModel extends BaseViewModel { final NavigationService _navigationService = locator(); + final PatcherAPI _patcherAPI = locator(); PatchedApplication? selectedApp; List selectedPatches = []; @@ -31,4 +37,46 @@ class PatcherViewModel extends BaseViewModel { bool dimPatchesCard() { return selectedApp == null; } + + Future isValidPatchConfig() async { + bool needsResourcePatching = + await _patcherAPI.needsResourcePatching(selectedPatches); + if (needsResourcePatching && selectedApp != null) { + Application? app = await DeviceApps.getApp(selectedApp!.packageName); + if (app != null && app.isSplit) { + return false; + } + } + return true; + } + + Future showPatchConfirmationDialog(BuildContext context) async { + bool isValid = await isValidPatchConfig(); + if (isValid) { + navigateToInstaller(); + } else { + return showDialog( + context: context, + builder: (context) => AlertDialog( + title: I18nText('patcherView.patchDialogTitle'), + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + content: I18nText('patcherView.patchDialogText'), + actions: [ + CustomMaterialButton( + isFilled: false, + label: I18nText('cancelButton'), + onPressed: () => Navigator.of(context).pop(), + ), + CustomMaterialButton( + label: I18nText('okButton'), + onPressed: () { + Navigator.of(context).pop(); + navigateToInstaller(); + }, + ) + ], + ), + ); + } + } } diff --git a/pubspec.yaml b/pubspec.yaml index 99efc7038e..6cf75cc512 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: device_apps: git: url: https://github.com/ponces/flutter_plugin_device_apps - ref: appinfo-from-storage + ref: revanced-manager device_info_plus: ^4.1.2 dio: ^4.0.6 dio_http_cache_lts: ^0.4.1