diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index a961d70b..65fcdcc9 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -1234,129 +1234,120 @@ private extension AppManager return group } - func removeAppExtensions( - from application: ALTApplication, - existingApp: InstalledApp?, - extensions: Set, - _ presentingViewController: UIViewController?, - completion: @escaping (Result) -> Void - ) { + func removeAppExtensions(from application: ALTApplication, existingApp: InstalledApp?, extensions: Set, _ presentingViewController: UIViewController?, completion: @escaping (Result) -> Void) + { - // App-Extensions: Ensure existing app's extensions and currently installing app's extensions must match - if let existingApp { - _ = RSTAsyncBlockOperation { _ in - let existingAppEx: Set = existingApp.appExtensions - let currentAppEx: Set = application.appExtensions - - let currentAppExNames = currentAppEx.map{ appEx in appEx.bundleIdentifier} - let existingAppExNames = existingAppEx.map{ appEx in appEx.bundleIdentifier} - - let excessExtensions = currentAppEx.filter{ - !(existingAppExNames.contains($0.bundleIdentifier)) - } - - - let isMatching = (currentAppEx.count == existingAppEx.count) && excessExtensions.isEmpty - let diagnosticsMsg = "AppManager.removeAppExtensions: App Extensions in existingApp and currentApp are matching: \(isMatching)\n" - + "AppManager.removeAppExtensions: existingAppEx: \(existingAppExNames); currentAppEx: \(String(describing: currentAppExNames))\n" - print(diagnosticsMsg) - - - // if background mode, then remove only the excess extensions - guard let presentingViewController: UIViewController = presentingViewController else { - // perform silent extensions cleanup for those that aren't already present in existing app - print("\n Performing background mode Extensions removal \n") - print("AppManager.removeAppExtensions: Excess Extensions: \(excessExtensions)") - - do { - for appExtension in excessExtensions { - print("Deleting extension \(appExtension.bundleIdentifier)") - try FileManager.default.removeItem(at: appExtension.fileURL) - } - return completion(.success(())) - } catch { - return completion(.failure(error)) - } + //App-Extensions: Ensure existing app's extensions and currently installing app's extensions must match + let existingAppEx: Set = existingApp?.appExtensions ?? Set() + let currentAppEx: Set = application.appExtensions + + let currentAppExNames = currentAppEx.map{ appEx in appEx.bundleIdentifier} + let existingAppExNames = existingAppEx.map{ appEx in appEx.bundleIdentifier} + + let excessExtensions = currentAppEx.filter{ + !(existingAppExNames.contains($0.bundleIdentifier)) + } + + let isMatching = (currentAppEx.count == existingAppEx.count) && excessExtensions.isEmpty + let diagnosticsMsg = "AppManager.removeAppExtensions: App Extensions in existingApp and currentApp are matching: \(isMatching)\n" + + "AppManager.removeAppExtensions: existingAppEx: \(existingAppExNames); currentAppEx: \(String(describing: currentAppExNames))\n" + print(diagnosticsMsg) + + // if background mode, then remove only the excess extensions + guard let presentingViewController: UIViewController = presentingViewController else { + // perform silent extensions cleanup for those that aren't already present in existing app + print("\n Performing background mode Extensions removal \n") + print("AppManager.removeAppExtensions: Excess Extensions: \(excessExtensions)") + + do { + for appExtension in excessExtensions { + print("Deleting extension \(appExtension.bundleIdentifier)") + try FileManager.default.removeItem(at: appExtension.fileURL) } + return completion(.success(())) + } catch { + return completion(.failure(error)) } } guard !application.appExtensions.isEmpty else { return completion(.success(())) } - DispatchQueue.main.async { - let firstSentence: String - - if UserDefaults.standard.activeAppLimitIncludesExtensions + 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? There are \(extensions.count) Extensions", 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 { - 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? There are \(extensions.count) Extensions", 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 + for appExtension in application.appExtensions + { + print("Deleting extension \(appExtension.bundleIdentifier)") + try FileManager.default.removeItem(at: appExtension.fileURL) + } + completion(.success(())) - }) - alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove App Extensions", comment: ""), style: .destructive) { (action) in + } + catch + { + completion(.failure(error)) + } + }) + + alertController.addAction(UIAlertAction(title: NSLocalizedString("Choose App Extensions", comment: ""), style: .default) { (action) in + let popoverContentController = AppExtensionViewHostingController(extensions: extensions) { (selection) in do { - for appExtension in application.appExtensions + for appExtension in selection { print("Deleting extension \(appExtension.bundleIdentifier)") + try FileManager.default.removeItem(at: appExtension.fileURL) } - completion(.success(())) } catch { completion(.failure(error)) } - }) - - if let presentingViewController { - alertController.addAction(UIAlertAction(title: NSLocalizedString("Choose App Extensions", comment: ""), style: .default) { (action) in - let popoverContentController = AppExtensionViewHostingController(extensions: extensions) { (selection) in - do - { - for appExtension in selection - { - print("Deleting extension \(appExtension.bundleIdentifier)") - - try FileManager.default.removeItem(at: appExtension.fileURL) - } - completion(.success(())) - } - catch - { - completion(.failure(error)) - } - return nil - } - - let suiview = popoverContentController.view! - suiview.translatesAutoresizingMaskIntoConstraints = false - - popoverContentController.modalPresentationStyle = .popover - - if let popoverPresentationController = popoverContentController.popoverPresentationController { - popoverPresentationController.sourceView = presentingViewController.view - popoverPresentationController.sourceRect = CGRect(x: 50, y: 50, width: 4, height: 4) - popoverPresentationController.delegate = popoverContentController - - presentingViewController.present(popoverContentController, animated: true) - } - }) - - presentingViewController.present(alertController, animated: true) + return nil } + + let suiview = popoverContentController.view! + suiview.translatesAutoresizingMaskIntoConstraints = false + + popoverContentController.modalPresentationStyle = .popover + + if let popoverPresentationController = popoverContentController.popoverPresentationController { + popoverPresentationController.sourceView = presentingViewController.view + popoverPresentationController.sourceRect = CGRect(x: 50, y: 50, width: 4, height: 4) + popoverPresentationController.delegate = popoverContentController + + DispatchQueue.main.async { + presentingViewController.present(popoverContentController, animated: true) + } + } + + + }) + + DispatchQueue.main.async { + presentingViewController.present(alertController, animated: true) } }