Downloads latest _available_ version when updating from AppViewController

Asks user to fall back to latest supported verson if version is not compatible with device’s iOS version.
This commit is contained in:
Riley Testut
2023-12-01 16:03:06 -06:00
parent 2c1ffedfe3
commit 92f3be07f6
3 changed files with 47 additions and 30 deletions

View File

@@ -17,7 +17,9 @@ import Roxas
@objc(DownloadAppOperation)
class DownloadAppOperation: ResultOperation<ALTApplication>
{
let app: AppProtocol
@Managed
private(set) var app: AppProtocol
let context: InstallAppOperationContext
private let appName: String
@@ -59,22 +61,36 @@ class DownloadAppOperation: ResultOperation<ALTApplication>
// Set _after_ checking self.context.error to prevent overwriting localized failure for previous errors.
self.localizedFailure = String(format: NSLocalizedString("%@ could not be downloaded.", comment: ""), self.appName)
guard let storeApp = self.app as? StoreApp else {
// Only StoreApp allows falling back to previous versions.
// AppVersion can only install itself, and ALTApplication doesn't have previous versions.
return self.download(self.app)
}
// Verify storeApp
storeApp.managedObjectContext?.perform {
self.$app.perform { app in
do
{
let latestVersion = try self.verify(storeApp)
self.download(latestVersion)
var appVersion: AppVersion?
if let version = app as? AppVersion
{
appVersion = version
}
else if let storeApp = app as? StoreApp
{
guard let latestVersion = storeApp.latestAvailableVersion else {
let failureReason = String(format: NSLocalizedString("The latest version of %@ could not be determined.", comment: ""), self.appName)
throw OperationError.unknown(failureReason: failureReason)
}
// Attempt to download latest _available_ version, and fall back to older versions if necessary.
appVersion = latestVersion
}
if let appVersion
{
try self.verify(appVersion)
}
self.download(appVersion ?? app)
}
catch let error as VerificationError where error.code == .iOSVersionNotSupported
{
guard let presentingViewController = self.context.presentingViewController, let latestSupportedVersion = storeApp.latestSupportedVersion
guard let presentingViewController = self.context.presentingViewController, let storeApp = app.storeApp, let latestSupportedVersion = storeApp.latestSupportedVersion
else { return self.finish(.failure(error)) }
if let installedApp = storeApp.installedApp
@@ -85,7 +101,7 @@ class DownloadAppOperation: ResultOperation<ALTApplication>
let title = NSLocalizedString("Unsupported iOS Version", comment: "")
let message = error.localizedDescription + "\n\n" + NSLocalizedString("Would you like to download the last version compatible with this device instead?", comment: "")
let localizedVersion = latestSupportedVersion.localizedVersion
DispatchQueue.main.async {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style) { _ in
@@ -121,23 +137,16 @@ class DownloadAppOperation: ResultOperation<ALTApplication>
private extension DownloadAppOperation
{
func verify(_ storeApp: StoreApp) throws -> AppVersion
func verify(_ version: AppVersion) throws
{
guard let version = storeApp.latestAvailableVersion else {
let failureReason = String(format: NSLocalizedString("The latest version of %@ could not be determined.", comment: ""), self.appName)
throw OperationError.unknown(failureReason: failureReason)
}
if let minOSVersion = version.minOSVersion, !ProcessInfo.processInfo.isOperatingSystemAtLeast(minOSVersion)
{
throw VerificationError.iOSVersionNotSupported(app: storeApp, requiredOSVersion: minOSVersion)
throw VerificationError.iOSVersionNotSupported(app: version, requiredOSVersion: minOSVersion)
}
else if let maxOSVersion = version.maxOSVersion, ProcessInfo.processInfo.operatingSystemVersion > maxOSVersion
{
throw VerificationError.iOSVersionNotSupported(app: storeApp, requiredOSVersion: maxOSVersion)
throw VerificationError.iOSVersionNotSupported(app: version, requiredOSVersion: maxOSVersion)
}
return version
}
func download(@Managed _ app: AppProtocol)