[AltServer] Improves error messages

This commit is contained in:
Riley Testut
2021-06-04 13:57:40 -07:00
parent e0b50ac80c
commit 558a3fc865
6 changed files with 122 additions and 32 deletions

View File

@@ -139,7 +139,7 @@ private extension AppDelegate
switch result switch result
{ {
case .failure(let error): case .failure(let error):
self.showErrorAlert(title: String(format: NSLocalizedString("JIT compilation could not be enabled for %@.", comment: ""), app.name), error: error) self.showErrorAlert(error: error, localizedFailure: String(format: NSLocalizedString("JIT compilation could not be enabled for %@.", comment: ""), app.name))
case .success: case .success:
let alert = NSAlert() let alert = NSAlert()
@@ -234,28 +234,8 @@ private extension AppDelegate
// Ignore // Ignore
break break
case .failure(let error as NSError): case .failure(let error):
self.showErrorAlert(error: error, localizedFailure: String(format: NSLocalizedString("Could not install app to %@.", comment: ""), device.name))
let alert = NSAlert()
alert.alertStyle = .critical
alert.messageText = NSLocalizedString("Installation Failed", comment: "")
if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? Error
{
alert.informativeText = underlyingError.localizedDescription
}
else if let recoverySuggestion = error.localizedRecoverySuggestion
{
alert.informativeText = error.localizedDescription + "\n\n" + recoverySuggestion
}
else
{
alert.informativeText = error.localizedDescription
}
NSRunningApplication.current.activate(options: .activateIgnoringOtherApps)
alert.runModal()
} }
} }
} }
@@ -289,6 +269,67 @@ private extension AppDelegate
} }
} }
func showErrorAlert(error: Error, localizedFailure: String)
{
let nsError = error as NSError
let alert = NSAlert()
alert.alertStyle = .critical
alert.messageText = localizedFailure
var messageComponents = [String]()
if let errorFailure = nsError.localizedFailure
{
if let failureReason = nsError.localizedFailureReason
{
if nsError.localizedDescription.starts(with: errorFailure)
{
alert.messageText = errorFailure
messageComponents.append(failureReason)
}
else
{
alert.messageText = errorFailure
messageComponents.append(nsError.localizedDescription)
}
}
else
{
// No failure reason given.
if nsError.localizedDescription.starts(with: errorFailure)
{
// No need to duplicate errorFailure in both title and message.
alert.messageText = localizedFailure
messageComponents.append(nsError.localizedDescription)
}
else
{
alert.messageText = errorFailure
messageComponents.append(nsError.localizedDescription)
}
}
}
else
{
alert.messageText = localizedFailure
messageComponents.append(nsError.localizedDescription)
}
if let recoverySuggestion = nsError.localizedRecoverySuggestion
{
messageComponents.append(recoverySuggestion)
}
let informativeText = messageComponents.joined(separator: " ")
alert.informativeText = informativeText
NSRunningApplication.current.activate(options: .activateIgnoringOtherApps)
alert.runModal()
}
@objc func toggleLaunchAtLogin(_ item: NSMenuItem) @objc func toggleLaunchAtLogin(_ item: NSMenuItem)
{ {
LaunchAtLogin.isEnabled.toggle() LaunchAtLogin.isEnabled.toggle()

View File

@@ -38,10 +38,22 @@ extension ALTDeviceManager
{ {
let destinationDirectoryURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) let destinationDirectoryURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
var appName = (url.isFileURL) ? url.deletingPathExtension().lastPathComponent : NSLocalizedString("AltStore", comment: "")
func finish(_ result: Result<ALTApplication, Error>, title: String = "") func finish(_ result: Result<ALTApplication, Error>, title: String = "")
{ {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(result) switch result
{
case .success(let app): completion(.success(app))
case .failure(var error as NSError):
if error.localizedFailure == nil
{
error = error.withLocalizedFailure(String(format: NSLocalizedString("Could not install %@ to %@.", comment: ""), appName, altDevice.name))
}
completion(.failure(error))
}
} }
try? FileManager.default.removeItem(at: destinationDirectoryURL) try? FileManager.default.removeItem(at: destinationDirectoryURL)

View File

@@ -1126,6 +1126,11 @@ NSNotificationName const ALTDeviceManagerDeviceDidDisconnectNotification = @"ALT
idevice_free(device); idevice_free(device);
} }
if (error)
{
error = [error alt_errorWithLocalizedFailure:[NSString stringWithFormat:NSLocalizedString(@"The Developer disk image could not be installed onto %@.", @""), altDevice.name]];
}
completionHandler(error == nil, error); completionHandler(error == nil, error);
}; };

View File

@@ -31,6 +31,7 @@
BF1E312B229F474900370A3C /* RequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E3129229F474900370A3C /* RequestHandler.swift */; }; BF1E312B229F474900370A3C /* RequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E3129229F474900370A3C /* RequestHandler.swift */; };
BF1FE358251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1FE357251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift */; }; BF1FE358251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1FE357251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift */; };
BF1FE359251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1FE357251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift */; }; BF1FE359251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1FE357251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift */; };
BF265D1925F843A000080DC9 /* NSError+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6C336124197D700034FD24 /* NSError+AltStore.swift */; };
BF29012F2318F6B100D88A45 /* AppBannerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF29012E2318F6B100D88A45 /* AppBannerView.xib */; }; BF29012F2318F6B100D88A45 /* AppBannerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF29012E2318F6B100D88A45 /* AppBannerView.xib */; };
BF2901312318F7A800D88A45 /* AppBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2901302318F7A800D88A45 /* AppBannerView.swift */; }; BF2901312318F7A800D88A45 /* AppBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2901302318F7A800D88A45 /* AppBannerView.swift */; };
BF340E9A250AD39500A192CB /* ViewApp.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = BF989191250AAE86002ACF50 /* ViewApp.intentdefinition */; }; BF340E9A250AD39500A192CB /* ViewApp.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = BF989191250AAE86002ACF50 /* ViewApp.intentdefinition */; };
@@ -1556,7 +1557,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
BFF0B6992322D7D0007A79E1 /* UIScreen+CompactHeight.swift */, BFF0B6992322D7D0007A79E1 /* UIScreen+CompactHeight.swift */,
BF6C336124197D700034FD24 /* NSError+AltStore.swift */,
BF663C4E2433ED8200DAA738 /* FileManager+DirectorySize.swift */, BF663C4E2433ED8200DAA738 /* FileManager+DirectorySize.swift */,
BF8CAE4D248AEABA004D6CCE /* UIDevice+Jailbreak.swift */, BF8CAE4D248AEABA004D6CCE /* UIDevice+Jailbreak.swift */,
BFE00A1F2503097F00EB4D0C /* INInteraction+AltStore.swift */, BFE00A1F2503097F00EB4D0C /* INInteraction+AltStore.swift */,
@@ -1665,6 +1665,7 @@
BFF767CB2489AB5C0097E58C /* ALTServerError+Conveniences.swift */, BFF767CB2489AB5C0097E58C /* ALTServerError+Conveniences.swift */,
BF1FE357251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift */, BF1FE357251A9FB000C3CE09 /* NSXPCConnection+MachServices.swift */,
BFF435D7255CBDAB00DD724F /* ALTApplication+AltStoreApp.swift */, BFF435D7255CBDAB00DD724F /* ALTApplication+AltStoreApp.swift */,
BF6C336124197D700034FD24 /* NSError+AltStore.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2298,6 +2299,7 @@
BFECAC8124FD950B0077C41F /* ALTServerError+Conveniences.swift in Sources */, BFECAC8124FD950B0077C41F /* ALTServerError+Conveniences.swift in Sources */,
BFECAC7F24FD950B0077C41F /* CodableServerError.swift in Sources */, BFECAC7F24FD950B0077C41F /* CodableServerError.swift in Sources */,
BFECAC8624FD950B0077C41F /* Result+Conveniences.swift in Sources */, BFECAC8624FD950B0077C41F /* Result+Conveniences.swift in Sources */,
BF265D1925F843A000080DC9 /* NSError+AltStore.swift in Sources */,
BF904DEA265DAE9A00E86C2A /* InstalledApp.swift in Sources */, BF904DEA265DAE9A00E86C2A /* InstalledApp.swift in Sources */,
BFF435D9255CBDAB00DD724F /* ALTApplication+AltStoreApp.swift in Sources */, BFF435D9255CBDAB00DD724F /* ALTApplication+AltStoreApp.swift in Sources */,
BF718BD523C928A300A89F2D /* ALTNotificationConnection.mm in Sources */, BF718BD523C928A300A89F2D /* ALTNotificationConnection.mm in Sources */,

View File

@@ -75,7 +75,7 @@ NSErrorUserInfoKey const ALTDeviceNameErrorKey = @"deviceName";
case ALTServerErrorConnectionFailed: case ALTServerErrorConnectionFailed:
#if TARGET_OS_OSX #if TARGET_OS_OSX
return NSLocalizedString(@"Could not connect to device.", @""); return NSLocalizedString(@"There was an error connecting to the device.", @"");
#else #else
return NSLocalizedString(@"Could not connect to AltServer.", @""); return NSLocalizedString(@"Could not connect to AltServer.", @"");
#endif #endif
@@ -114,10 +114,10 @@ NSErrorUserInfoKey const ALTDeviceNameErrorKey = @"deviceName";
return NSLocalizedString(@"Received an unknown response from AltServer.", @""); return NSLocalizedString(@"Received an unknown response from AltServer.", @"");
case ALTServerErrorInvalidAnisetteData: case ALTServerErrorInvalidAnisetteData:
return NSLocalizedString(@"Invalid anisette data.", @""); return NSLocalizedString(@"The provided anisette data is invalid.", @"");
case ALTServerErrorPluginNotFound: case ALTServerErrorPluginNotFound:
return NSLocalizedString(@"Could not connect to Mail plug-in.", @""); return NSLocalizedString(@"AltServer could not connect to Mail plug-in.", @"");
case ALTServerErrorProfileNotFound: case ALTServerErrorProfileNotFound:
return [self profileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not find profile", "")]; return [self profileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not find profile", "")];

View File

@@ -16,13 +16,38 @@ extension NSError
return localizedFailure return localizedFailure
} }
@objc(alt_errorWithLocalizedFailure:)
func withLocalizedFailure(_ failure: String) -> NSError func withLocalizedFailure(_ failure: String) -> NSError
{ {
var userInfo = self.userInfo var userInfo = self.userInfo
userInfo[NSLocalizedFailureErrorKey] = failure userInfo[NSLocalizedFailureErrorKey] = failure
userInfo[NSLocalizedDescriptionKey] = self.localizedDescription
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedFailureReason if let failureReason = self.localizedFailureReason
userInfo[NSLocalizedRecoverySuggestionErrorKey] = self.localizedRecoverySuggestion {
userInfo[NSLocalizedFailureReasonErrorKey] = failureReason
}
else if self.localizedFailure == nil && self.localizedFailureReason == nil && self.localizedDescription.contains(self.localizedErrorCode)
{
// Default localizedDescription, so replace with just the localized error code portion.
userInfo[NSLocalizedFailureReasonErrorKey] = "(\(self.localizedErrorCode).)"
}
else
{
userInfo[NSLocalizedFailureReasonErrorKey] = self.localizedDescription
}
if let localizedDescription = NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSLocalizedDescriptionKey) as? String
{
userInfo[NSLocalizedDescriptionKey] = localizedDescription
}
// Don't accidentally remove localizedDescription from dictionary
// userInfo[NSLocalizedDescriptionKey] = NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSLocalizedDescriptionKey) as? String
if let recoverySuggestion = self.localizedRecoverySuggestion
{
userInfo[NSLocalizedRecoverySuggestionErrorKey] = recoverySuggestion
}
let error = NSError(domain: self.domain, code: self.code, userInfo: userInfo) let error = NSError(domain: self.domain, code: self.code, userInfo: userInfo)
return error return error
@@ -50,6 +75,11 @@ extension Error
let underlyingError = (self as NSError).userInfo[NSUnderlyingErrorKey] as? Error let underlyingError = (self as NSError).userInfo[NSUnderlyingErrorKey] as? Error
return underlyingError return underlyingError
} }
var localizedErrorCode: String {
let localizedErrorCode = String(format: NSLocalizedString("%@ error %@", comment: ""), (self as NSError).domain, (self as NSError).code as NSNumber)
return localizedErrorCode
}
} }
protocol ALTLocalizedError: LocalizedError, CustomNSError protocol ALTLocalizedError: LocalizedError, CustomNSError
@@ -86,7 +116,7 @@ extension ALTLocalizedError
return errorDescription return errorDescription
} }
var failureReason: String? { (self.underlyingError as NSError?)?.localizedFailureReason ?? (self.underlyingError as NSError?)?.localizedDescription } var failureReason: String? { (self.underlyingError as NSError?)?.localizedDescription }
var recoverySuggestion: String? { (self.underlyingError as NSError?)?.localizedRecoverySuggestion } var recoverySuggestion: String? { (self.underlyingError as NSError?)?.localizedRecoverySuggestion }
var helpAnchor: String? { (self.underlyingError as NSError?)?.helpAnchor } var helpAnchor: String? { (self.underlyingError as NSError?)?.helpAnchor }
} }