From 1397389f95fe47451193ecec9e5f69a8d8fe3135 Mon Sep 17 00:00:00 2001 From: June Date: Fri, 16 Aug 2024 12:57:42 +0900 Subject: [PATCH] Make app extensions optional across the board --- AltStore/Managing Apps/AppManager.swift | 83 ++++++++++++++++++++- AltStore/My Apps/MyAppsViewController.swift | 82 ++------------------ 2 files changed, 85 insertions(+), 80 deletions(-) diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index 46480934..44148daa 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -1014,6 +1014,51 @@ private extension AppManager return group } + func removeAppExtensions(from application: ALTApplication, _ presentingViewController: UIViewController, completion: @escaping (Result) -> Void) + { + guard !application.appExtensions.isEmpty else { return completion(.success(())) } + + let firstSentence: String + + if UserDefaults.standard.activeAppLimitIncludesExtensions + { + firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to 3 active apps and app extensions.", comment: "") + } + else + { + firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to creating 10 App IDs per week.", comment: "") + } + + let message = firstSentence + " " + NSLocalizedString("Would you like to remove this app's extensions so they don't count towards your limit?", comment: "") + + let alertController = UIAlertController(title: NSLocalizedString("App Contains Extensions", comment: ""), message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style, handler: { (action) in + completion(.failure(OperationError.cancelled)) + })) + alertController.addAction(UIAlertAction(title: NSLocalizedString("Keep App Extensions", comment: ""), style: .default) { (action) in + completion(.success(())) + }) + alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove App Extensions", comment: ""), style: .destructive) { (action) in + do + { + for appExtension in application.appExtensions + { + try FileManager.default.removeItem(at: appExtension.fileURL) + } + + completion(.success(())) + } + catch + { + completion(.failure(error)) + } + }) + + DispatchQueue.main.async { + presentingViewController.present(alertController, animated: true) + } + } + private func _install(_ app: AppProtocol, operation appOperation: AppOperation, group: RefreshGroup, context: InstallAppOperationContext? = nil, additionalEntitlements: [ALTEntitlement: Any]? = nil, cacheApp: Bool = true, completionHandler: @escaping (Result) -> Void) -> Progress { let progress = Progress.discreteProgress(totalUnitCount: 100) @@ -1086,6 +1131,39 @@ private extension AppManager } verifyOperation.addDependency(downloadOperation) + /* Remove App Extensions */ + + let removeAppExtensionsOperation = RSTAsyncBlockOperation { [weak self] (operation) in + do + { + if let error = context.error + { + throw error + } + + guard let extensions = context.app?.appExtensions else { throw OperationError.invalidParameters } + + guard let app = context.app, let presentingViewController = context.authenticatedContext.presentingViewController else { throw OperationError.invalidParameters } + + + self?.removeAppExtensions(from: app, presentingViewController) { result in + switch result { + case .success(): break + case .failure(let error): context.error = error + } + operation.finish() + } + + } + catch + { + group.context.error = error + operation.finish() + } + } + + removeAppExtensionsOperation.addDependency(verifyOperation) + /* Refresh Anisette Data */ let refreshAnisetteDataOperation = FetchAnisetteDataOperation(context: group.context) @@ -1096,7 +1174,7 @@ private extension AppManager case .success(let anisetteData): group.context.session?.anisetteData = anisetteData } } - refreshAnisetteDataOperation.addDependency(verifyOperation) + refreshAnisetteDataOperation.addDependency(removeAppExtensionsOperation) /* Fetch Provisioning Profiles */ @@ -1157,7 +1235,6 @@ private extension AppManager } deactivateAppsOperation.addDependency(fetchProvisioningProfilesOperation) - /* Patch App */ let patchAppOperation = RSTAsyncBlockOperation { operation in do @@ -1282,7 +1359,7 @@ private extension AppManager progress.addChild(installOperation.progress, withPendingUnitCount: 30) installOperation.addDependency(sendAppOperation) - let operations = [downloadOperation, verifyOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, deactivateAppsOperation, patchAppOperation, resignAppOperation, sendAppOperation, installOperation] + let operations = [downloadOperation, verifyOperation, removeAppExtensionsOperation, refreshAnisetteDataOperation, fetchProvisioningProfilesOperation, deactivateAppsOperation, patchAppOperation, resignAppOperation, sendAppOperation, installOperation] group.add(operations) self.run(operations, context: group.context) diff --git a/AltStore/My Apps/MyAppsViewController.swift b/AltStore/My Apps/MyAppsViewController.swift index 59d9a4fc..af268563 100644 --- a/AltStore/My Apps/MyAppsViewController.swift +++ b/AltStore/My Apps/MyAppsViewController.swift @@ -783,7 +783,7 @@ private extension MyAppsViewController } let unzipProgress = Progress.discreteProgress(totalUnitCount: 1) - let unzipAppOperation = BlockOperation { + let unzipAppOperation = BlockOperation { do { if let error = context.error @@ -815,38 +815,7 @@ private extension MyAppsViewController { unzipAppOperation.addDependency(downloadOperation) } - - let removeAppExtensionsProgress = Progress.discreteProgress(totalUnitCount: 1) - let removeAppExtensionsOperation = RSTAsyncBlockOperation { [weak self] (operation) in - do - { - if let error = context.error - { - throw error - } - guard let application = context.application else { throw OperationError.invalidParameters } - - DispatchQueue.main.async { - self?.removeAppExtensions(from: application) { (result) in - switch result - { - case .success: removeAppExtensionsProgress.completedUnitCount = 1 - case .failure(let error): context.error = error - } - operation.finish() - } - } - } - catch - { - context.error = error - operation.finish() - } - } - removeAppExtensionsOperation.addDependency(unzipAppOperation) - progress.addChild(removeAppExtensionsProgress, withPendingUnitCount: 5) - let installProgress = Progress.discreteProgress(totalUnitCount: 100) let installAppOperation = RSTAsyncBlockOperation { (operation) in do @@ -901,15 +870,17 @@ private extension MyAppsViewController } } } + + installAppOperation.addDependency(unzipAppOperation) + progress.addChild(installProgress, withPendingUnitCount: 65) - installAppOperation.addDependency(removeAppExtensionsOperation) self.sideloadingProgress = progress self.sideloadingProgressView.progress = 0 self.sideloadingProgressView.isHidden = false self.sideloadingProgressView.observedProgress = self.sideloadingProgress - let operations = [downloadOperation, unzipAppOperation, removeAppExtensionsOperation, installAppOperation].compactMap { $0 } + let operations = [downloadOperation, unzipAppOperation, installAppOperation].compactMap { $0 } self.operationQueue.addOperations(operations, waitUntilFinished: false) } @@ -958,49 +929,6 @@ private extension MyAppsViewController cell.bannerView.iconImageView.isIndicatingActivity = false } - - func removeAppExtensions(from application: ALTApplication, completion: @escaping (Result) -> Void) - { - guard !application.appExtensions.isEmpty else { return completion(.success(())) } - - let firstSentence: String - - if UserDefaults.standard.activeAppLimitIncludesExtensions - { - firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to 3 active apps and app extensions.", comment: "") - } - else - { - firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to creating 10 App IDs per week.", comment: "") - } - - let message = firstSentence + " " + NSLocalizedString("Would you like to remove this app's extensions so they don't count towards your limit?", comment: "") - - let alertController = UIAlertController(title: NSLocalizedString("App Contains Extensions", comment: ""), message: message, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style, handler: { (action) in - completion(.failure(OperationError.cancelled)) - })) - alertController.addAction(UIAlertAction(title: NSLocalizedString("Keep App Extensions", comment: ""), style: .default) { (action) in - completion(.success(())) - }) - alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove App Extensions", comment: ""), style: .destructive) { (action) in - do - { - for appExtension in application.appExtensions - { - try FileManager.default.removeItem(at: appExtension.fileURL) - } - - completion(.success(())) - } - catch - { - completion(.failure(error)) - } - }) - - self.present(alertController, animated: true, completion: nil) - } } private extension MyAppsViewController