From bfc2ea2c3a7d97861bcb4b9dbb891ca976b7da56 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Tue, 8 Sep 2020 16:44:36 -0700 Subject: [PATCH] Adds button to add Refresh All Apps shortcut to Siri --- AltStore/Settings/Settings.storyboard | 85 ++++++++++++------ .../Settings/SettingsViewController.swift | 90 +++++++++++++++++-- 2 files changed, 139 insertions(+), 36 deletions(-) diff --git a/AltStore/Settings/Settings.storyboard b/AltStore/Settings/Settings.storyboard index c4f22706..d215b64a 100644 --- a/AltStore/Settings/Settings.storyboard +++ b/AltStore/Settings/Settings.storyboard @@ -1,9 +1,9 @@ - + - + @@ -20,7 +20,7 @@ diff --git a/AltStore/Settings/SettingsViewController.swift b/AltStore/Settings/SettingsViewController.swift index 28924c89..bfff6c76 100644 --- a/AltStore/Settings/SettingsViewController.swift +++ b/AltStore/Settings/SettingsViewController.swift @@ -9,6 +9,8 @@ import UIKit import SafariServices import MessageUI +import Intents +import IntentsUI import AltStoreCore @@ -19,13 +21,26 @@ extension SettingsViewController case signIn case account case patreon - case backgroundRefresh + case appRefresh case jailbreak case instructions case credits case debug } + fileprivate enum AppRefreshRow: Int, CaseIterable + { + case backgroundRefresh + + @available(iOS 14, *) + case addToSiri + + static var allCases: [AppRefreshRow] { + guard #available(iOS 14, *) else { return [.backgroundRefresh] } + return [.backgroundRefresh, .addToSiri] + } + } + fileprivate enum CreditsRow: Int, CaseIterable { case developer @@ -167,8 +182,15 @@ private extension SettingsViewController settingsHeaderFooterView.button.addTarget(self, action: #selector(SettingsViewController.signOut(_:)), for: .primaryActionTriggered) settingsHeaderFooterView.button.isHidden = false - case .backgroundRefresh: - settingsHeaderFooterView.secondaryLabel.text = NSLocalizedString("Automatically refresh apps in the background when connected to the same WiFi as AltServer.", comment: "") + case .appRefresh: + if isHeader + { + settingsHeaderFooterView.primaryLabel.text = NSLocalizedString("REFRESHING APPS", comment: "") + } + else + { + settingsHeaderFooterView.secondaryLabel.text = NSLocalizedString("Enable Background Refresh to automatically refresh apps in the background when connected to the same WiFi as AltServer.", comment: "") + } case .jailbreak: if isHeader @@ -256,6 +278,17 @@ private extension SettingsViewController UserDefaults.standard.isBackgroundRefreshEnabled = sender.isOn } + @available(iOS 14, *) + @IBAction func addRefreshAppsShortcut() + { + guard let shortcut = INShortcut(intent: INInteraction.refreshAllApps().intent) else { return } + + let viewController = INUIAddVoiceShortcutViewController(shortcut: shortcut) + viewController.delegate = self + viewController.modalPresentationStyle = .formSheet + self.present(viewController, animated: true, completion: nil) + } + @IBAction func handleDebugModeGesture(_ gestureRecognizer: UISwipeGestureRecognizer) { self.debugGestureCounter += 1 @@ -333,6 +366,7 @@ extension SettingsViewController { case .signIn: return (self.activeTeam == nil) ? 1 : 0 case .account: return (self.activeTeam == nil) ? 0 : 3 + case .appRefresh: return AppRefreshRow.allCases.count case .jailbreak: return UIDevice.current.isJailbroken ? 1 : 0 default: return super.tableView(tableView, numberOfRowsInSection: section.rawValue) } @@ -347,12 +381,12 @@ extension SettingsViewController case .account where self.activeTeam == nil: return nil case .jailbreak where !UIDevice.current.isJailbroken: return nil - case .signIn, .account, .patreon, .jailbreak, .credits, .debug: + case .signIn, .account, .patreon, .appRefresh, .jailbreak, .credits, .debug: let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderFooterView") as! SettingsHeaderFooterView self.prepare(headerView, for: section, isHeader: true) return headerView - case .backgroundRefresh, .instructions: return nil + case .instructions: return nil } } @@ -364,7 +398,7 @@ extension SettingsViewController case .signIn where self.activeTeam != nil: return nil case .jailbreak where !UIDevice.current.isJailbroken: return nil - case .signIn, .patreon, .backgroundRefresh, .jailbreak: + case .signIn, .patreon, .appRefresh, .jailbreak: let footerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderFooterView") as! SettingsHeaderFooterView self.prepare(footerView, for: section, isHeader: false) return footerView @@ -382,11 +416,11 @@ extension SettingsViewController case .account where self.activeTeam == nil: return 1.0 case .jailbreak where !UIDevice.current.isJailbroken: return 1.0 - case .signIn, .account, .patreon, .jailbreak, .credits, .debug: + case .signIn, .account, .patreon, .appRefresh, .jailbreak, .credits, .debug: let height = self.preferredHeight(for: self.prototypeHeaderFooterView, in: section, isHeader: true) return height - case .backgroundRefresh, .instructions: return 0.0 + case .instructions: return 0.0 } } @@ -399,7 +433,7 @@ extension SettingsViewController case .account where self.activeTeam == nil: return 1.0 case .jailbreak where !UIDevice.current.isJailbroken: return 1.0 - case .signIn, .patreon, .backgroundRefresh, .jailbreak: + case .signIn, .patreon, .appRefresh, .jailbreak: let height = self.preferredHeight(for: self.prototypeHeaderFooterView, in: section, isHeader: false) return height @@ -417,6 +451,16 @@ extension SettingsViewController { case .signIn: self.signIn() case .instructions: break + case .appRefresh: + let row = AppRefreshRow.allCases[indexPath.row] + switch row + { + case .backgroundRefresh: break + case .addToSiri: + guard #available(iOS 14, *) else { return } + self.addRefreshAppsShortcut() + } + case .jailbreak: let fileURL = Bundle.main.url(forResource: "AltDaemon", withExtension: "deb")! @@ -491,3 +535,31 @@ extension SettingsViewController: UIGestureRecognizerDelegate return true } } + +extension SettingsViewController: INUIAddVoiceShortcutViewControllerDelegate +{ + func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) + { + if let indexPath = self.tableView.indexPathForSelectedRow + { + self.tableView.deselectRow(at: indexPath, animated: true) + } + + controller.dismiss(animated: true, completion: nil) + + guard let error = error else { return } + + let toastView = ToastView(error: error) + toastView.show(in: self) + } + + func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) + { + if let indexPath = self.tableView.indexPathForSelectedRow + { + self.tableView.deselectRow(at: indexPath, animated: true) + } + + controller.dismiss(animated: true, completion: nil) + } +}