[Both] Improves error messages

This commit is contained in:
Riley Testut
2020-03-11 13:35:14 -07:00
parent 4f00018164
commit 5e25593c3d
6 changed files with 141 additions and 43 deletions

View File

@@ -16,6 +16,8 @@ extern NSErrorUserInfoKey const ALTProvisioningProfileBundleIDErrorKey;
typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
{
ALTServerErrorUnderlyingError = -1,
ALTServerErrorUnknown = 0,
ALTServerErrorConnectionFailed = 1,
ALTServerErrorLostConnection = 2,
@@ -37,9 +39,7 @@ typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
ALTServerErrorInvalidAnisetteData = 13,
ALTServerErrorPluginNotFound = 14,
ALTServerErrorProfileInstallFailed = 15,
ALTServerErrorProfileCopyFailed = 16,
ALTServerErrorProfileRemoveFailed = 17,
ALTServerErrorProfileNotFound = 15
};
NS_ASSUME_NONNULL_BEGIN

View File

@@ -19,19 +19,35 @@ NSErrorUserInfoKey const ALTProvisioningProfileBundleIDErrorKey = @"bundleIdenti
+ (void)load
{
[NSError setUserInfoValueProviderForDomain:AltServerErrorDomain provider:^id _Nullable(NSError * _Nonnull error, NSErrorUserInfoKey _Nonnull userInfoKey) {
if ([userInfoKey isEqualToString:NSLocalizedDescriptionKey])
if ([userInfoKey isEqualToString:NSLocalizedFailureReasonErrorKey])
{
return [error alt_localizedDescription];
return [error alt_localizedFailureReason];
}
if ([userInfoKey isEqualToString:NSLocalizedRecoverySuggestionErrorKey])
{
return [error alt_localizedRecoverySuggestion];
}
return nil;
}];
}
- (nullable NSString *)alt_localizedDescription
- (nullable NSString *)alt_localizedFailureReason
{
switch ((ALTServerError)self.code)
{
case ALTServerErrorUnderlyingError:
{
NSString *underlyingErrorCode = self.userInfo[ALTUnderlyingErrorCodeErrorKey];
if (underlyingErrorCode == nil)
{
return NSLocalizedString(@"An unknown error occured.", @"");
}
return [NSString stringWithFormat:NSLocalizedString(@"Error code: %@", @""), underlyingErrorCode];
}
case ALTServerErrorUnknown:
return NSLocalizedString(@"An unknown error occured.", @"");
@@ -60,7 +76,7 @@ NSErrorUserInfoKey const ALTProvisioningProfileBundleIDErrorKey = @"bundleIdenti
return NSLocalizedString(@"An error occured while installing the app.", @"");
case ALTServerErrorMaximumFreeAppLimitReached:
return NSLocalizedString(@"You have reached the limit of 3 apps per device.", @"");
return NSLocalizedString(@"Cannot activate more than 3 apps and app extensions.", @"");
case ALTServerErrorUnsupportediOSVersion:
return NSLocalizedString(@"Your device must be running iOS 12.2 or later to install AltStore.", @"");
@@ -75,41 +91,43 @@ NSErrorUserInfoKey const ALTProvisioningProfileBundleIDErrorKey = @"bundleIdenti
return NSLocalizedString(@"Invalid anisette data.", @"");
case ALTServerErrorPluginNotFound:
return NSLocalizedString(@"Could not connect to Mail plug-in. Please make sure Mail is running and that you've enabled the plug-in in Mail's preferences, then try again.", @"");
return NSLocalizedString(@"Could not connect to Mail plug-in.", @"");
case ALTServerErrorProfileInstallFailed:
return [self underlyingProfileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not install profile", "")];
case ALTServerErrorProfileCopyFailed:
return [self underlyingProfileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not copy provisioning profiles", "")];
case ALTServerErrorProfileRemoveFailed:
return [self underlyingProfileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not remove profile", "")];
case ALTServerErrorProfileNotFound:
return [self profileErrorLocalizedDescriptionWithBaseDescription:NSLocalizedString(@"Could not find profile", "")];
}
}
- (NSString *)underlyingProfileErrorLocalizedDescriptionWithBaseDescription:(NSString *)baseDescription
- (nullable NSString *)alt_localizedRecoverySuggestion
{
NSMutableString *localizedDescription = [NSMutableString string];
switch ((ALTServerError)self.code)
{
case ALTServerErrorConnectionFailed:
case ALTServerErrorDeviceNotFound:
return NSLocalizedString(@"Make sure you have trusted this phone with your computer and WiFi sync is enabled.", @"");
case ALTServerErrorPluginNotFound:
return NSLocalizedString(@"Make sure Mail is running and the plug-in is enabled in Mail's preferences.", @"");
default:
return nil;
}
}
- (NSString *)profileErrorLocalizedDescriptionWithBaseDescription:(NSString *)baseDescription
{
NSString *localizedDescription = nil;
NSString *bundleID = self.userInfo[ALTProvisioningProfileBundleIDErrorKey];
if (bundleID)
{
[localizedDescription appendFormat:NSLocalizedString(@"%@ “%@”", @""), baseDescription, bundleID];
localizedDescription = [NSString stringWithFormat:@"%@ “%@”", baseDescription, bundleID];
}
else
{
[localizedDescription appendString:baseDescription];
localizedDescription = [NSString stringWithFormat:@"%@.", baseDescription];
}
NSString *underlyingErrorCode = self.userInfo[ALTUnderlyingErrorCodeErrorKey];
if (underlyingErrorCode)
{
[localizedDescription appendFormat:@" (%@)", underlyingErrorCode];
}
[localizedDescription appendString:@"."];
return localizedDescription;
}

View File

@@ -702,22 +702,35 @@ NSNotificationName const ALTDeviceManagerDeviceDidDisconnectNotification = @"ALT
if (result == MISAGENT_E_SUCCESS)
{
NSLog(@"Installed profile: %@ (Team: %@)", provisioningProfile.bundleIdentifier, provisioningProfile.teamIdentifier);
NSLog(@"Installed profile: %@ (%@)", provisioningProfile.bundleIdentifier, provisioningProfile.UUID);
return YES;
}
else
{
NSLog(@"Failed to install provisioning profile %@ (Team: %@). Error Code: %@", provisioningProfile.bundleIdentifier, provisioningProfile.teamIdentifier, @(result));
int statusCode = misagent_get_status_code(mis);
NSLog(@"Failed to install provisioning profile %@ (%@). Error Code: %@", provisioningProfile.bundleIdentifier, provisioningProfile.UUID, @(statusCode));
if (error)
{
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorProfileInstallFailed userInfo:@{ALTUnderlyingErrorCodeErrorKey: [@(result) description], ALTProvisioningProfileBundleIDErrorKey: provisioningProfile.bundleIdentifier}];
switch (statusCode)
{
case -402620383:
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorMaximumFreeAppLimitReached userInfo:nil];
break;
default:
NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"Could not install profile “%@”", @""), provisioningProfile.bundleIdentifier];
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorUnderlyingError userInfo:@{
NSLocalizedFailureErrorKey: localizedFailure,
ALTUnderlyingErrorCodeErrorKey: [@(statusCode) description],
ALTProvisioningProfileBundleIDErrorKey: provisioningProfile.bundleIdentifier
}];
}
}
return NO;
}
return NO;
}
- (BOOL)removeProvisioningProfile:(ALTProvisioningProfile *)provisioningProfile misagent:(misagent_client_t)mis error:(NSError **)error
@@ -725,16 +738,33 @@ NSNotificationName const ALTDeviceManagerDeviceDidDisconnectNotification = @"ALT
misagent_error_t result = misagent_remove(mis, provisioningProfile.UUID.UUIDString.lowercaseString.UTF8String);
if (result == MISAGENT_E_SUCCESS)
{
NSLog(@"Removed provisioning profile: %@ (Team: %@)", provisioningProfile.bundleIdentifier, provisioningProfile.teamIdentifier);
NSLog(@"Removed provisioning profile: %@ (%@)", provisioningProfile.bundleIdentifier, provisioningProfile.UUID);
return YES;
}
else
{
NSLog(@"Failed to remove provisioning profile %@ (Team: %@). Error Code: %@", provisioningProfile.bundleIdentifier, provisioningProfile.teamIdentifier, @(result));
int statusCode = misagent_get_status_code(mis);
NSLog(@"Failed to remove provisioning profile %@ (%@). Error Code: %@", provisioningProfile.bundleIdentifier, provisioningProfile.UUID, @(statusCode));
if (error)
{
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorProfileRemoveFailed userInfo:@{ALTUnderlyingErrorCodeErrorKey: [@(result) description], ALTProvisioningProfileBundleIDErrorKey: provisioningProfile.bundleIdentifier}];
switch (statusCode)
{
case -402620405:
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorProfileNotFound userInfo:nil];
break;
default:
{
NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"Could not remove profile “%@”", @""), provisioningProfile.bundleIdentifier];
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorUnderlyingError userInfo:@{
NSLocalizedFailureErrorKey: localizedFailure,
ALTUnderlyingErrorCodeErrorKey: [@(statusCode) description],
ALTProvisioningProfileBundleIDErrorKey: provisioningProfile.bundleIdentifier
}];
}
}
}
return NO;
@@ -747,9 +777,14 @@ NSNotificationName const ALTDeviceManagerDeviceDidDisconnectNotification = @"ALT
misagent_error_t result = misagent_copy_all(mis, &rawProfiles);
if (result != MISAGENT_E_SUCCESS)
{
int statusCode = misagent_get_status_code(mis);
if (error)
{
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorProfileCopyFailed userInfo:@{ALTUnderlyingErrorCodeErrorKey: [@(result) description]}];
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorUnderlyingError userInfo:@{
NSLocalizedFailureErrorKey: NSLocalizedString(@"Could not copy provisioning profiles.", @""),
ALTUnderlyingErrorCodeErrorKey: [@(statusCode) description]
}];
}
return nil;

View File

@@ -122,6 +122,7 @@
BF56D2AC23DF8E170006506D /* FetchAppIDsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF56D2AB23DF8E170006506D /* FetchAppIDsOperation.swift */; };
BF56D2AF23DF9E310006506D /* AppIDsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF56D2AE23DF9E310006506D /* AppIDsViewController.swift */; };
BF5C5FCF237DF69100EDD0C6 /* ALTPluginService.m in Sources */ = {isa = PBXBuildFile; fileRef = BF5C5FCE237DF69100EDD0C6 /* ALTPluginService.m */; };
BF6C336224197D700034FD24 /* NSError+LocalizedFailure.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6C336124197D700034FD24 /* NSError+LocalizedFailure.swift */; };
BF6F439223644C6E00A0B879 /* RefreshAltStoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6F439123644C6E00A0B879 /* RefreshAltStoreViewController.swift */; };
BF718BC923C919E300A89F2D /* CFNotificationName+AltStore.m in Sources */ = {isa = PBXBuildFile; fileRef = BF718BC823C919E300A89F2D /* CFNotificationName+AltStore.m */; };
BF718BD123C91BD300A89F2D /* ALTWiredConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = BF718BD023C91BD300A89F2D /* ALTWiredConnection.m */; };
@@ -433,6 +434,7 @@
BF5C5FC7237DF5AE00EDD0C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BF5C5FCD237DF69100EDD0C6 /* ALTPluginService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALTPluginService.h; sourceTree = "<group>"; };
BF5C5FCE237DF69100EDD0C6 /* ALTPluginService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALTPluginService.m; sourceTree = "<group>"; };
BF6C336124197D700034FD24 /* NSError+LocalizedFailure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSError+LocalizedFailure.swift"; sourceTree = "<group>"; };
BF6F439123644C6E00A0B879 /* RefreshAltStoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshAltStoreViewController.swift; sourceTree = "<group>"; };
BF718BC723C919CC00A89F2D /* CFNotificationName+AltStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CFNotificationName+AltStore.h"; sourceTree = "<group>"; };
BF718BC823C919E300A89F2D /* CFNotificationName+AltStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CFNotificationName+AltStore.m"; sourceTree = "<group>"; };
@@ -1098,6 +1100,7 @@
BF9ABA4E22DD41A9008935CF /* UIColor+Hex.swift */,
BFDB5B1522EE90D300F74113 /* Date+RelativeDate.swift */,
BFF0B6992322D7D0007A79E1 /* UIScreen+CompactHeight.swift */,
BF6C336124197D700034FD24 /* NSError+LocalizedFailure.swift */,
);
path = Extensions;
sourceTree = "<group>";
@@ -1697,6 +1700,7 @@
BFF0B68E23219520007A79E1 /* PatreonViewController.swift in Sources */,
BFD5D6EA230CCAE5007955AB /* PatreonAccount.swift in Sources */,
BFE6326822A858F300F30809 /* Account.swift in Sources */,
BF6C336224197D700034FD24 /* NSError+LocalizedFailure.swift in Sources */,
BFE6326622A857C200F30809 /* Team.swift in Sources */,
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */,
BF41B806233423AE00C593A3 /* TabBarController.swift in Sources */,

View File

@@ -16,7 +16,7 @@ class ToastView: RSTToastView
{
if detailedText == nil
{
self.preferredDuration = 2.0
self.preferredDuration = 4.0
}
else
{
@@ -25,20 +25,41 @@ class ToastView: RSTToastView
super.init(text: text, detailText: detailedText)
self.layoutMargins = UIEdgeInsets(top: 6, left: 12, bottom: 6, right: 12)
self.layoutMargins = UIEdgeInsets(top: 8, left: 12, bottom: 8, right: 12)
self.setNeedsLayout()
if let stackView = self.textLabel.superview as? UIStackView
{
// RSTToastView does not expose stack view containing labels,
// so we access it indirectly as the labels' superview.
stackView.spacing = 4.0
}
}
convenience init(error: Error)
{
if let error = error as? LocalizedError
let error = error as NSError
let text: String
let detailText: String?
if let failure = error.localizedFailure
{
self.init(text: error.localizedDescription, detailText: error.recoverySuggestion ?? error.failureReason)
text = failure
detailText = error.localizedFailureReason ?? error.localizedRecoverySuggestion
}
else if let reason = error.localizedFailureReason
{
text = reason
detailText = error.localizedRecoverySuggestion
}
else
{
self.init(text: error.localizedDescription, detailText: nil)
text = error.localizedDescription
detailText = nil
}
self.init(text: text, detailText: detailText)
}
required init(coder aDecoder: NSCoder) {
@@ -49,7 +70,9 @@ class ToastView: RSTToastView
{
super.layoutSubviews()
self.layer.cornerRadius = 16
// Rough calculation to determine height of ToastView with one-line textLabel.
let minimumHeight = self.textLabel.font.lineHeight.rounded() + 20
self.layer.cornerRadius = minimumHeight/2
}
func show(in viewController: UIViewController)

View File

@@ -0,0 +1,18 @@
//
// NSError+LocalizedFailure.swift
// AltStore
//
// Created by Riley Testut on 3/11/20.
// Copyright © 2020 Riley Testut. All rights reserved.
//
import Foundation
extension NSError
{
@objc(alt_localizedFailure)
var localizedFailure: String? {
let localizedFailure = (self.userInfo[NSLocalizedFailureErrorKey] as? String) ?? (NSError.userInfoValueProvider(forDomain: self.domain)?(self, NSLocalizedFailureErrorKey) as? String)
return localizedFailure
}
}