2023-05-15 15:38:54 -05:00
//
// S o u r c e E r r o r . s w i f t
// A l t S t o r e C o r e
//
// C r e a t e d b y R i l e y T e s t u t o n 5 / 3 / 2 3 .
// C o p y r i g h t © 2 0 2 3 R i l e y T e s t u t . A l l r i g h t s r e s e r v e d .
//
import AltStoreCore
extension SourceError
{
enum Code : Int , ALTErrorCode
{
typealias Error = SourceError
case unsupported
case duplicateBundleID
case duplicateVersion
2023-05-15 16:25:25 -05:00
case blocked
2023-05-15 15:38:54 -05:00
case changedID
case duplicate
case missingPermissionUsageDescription
}
static func unsupported ( _ source : Source ) -> SourceError { SourceError ( code : . unsupported , source : source ) }
static func duplicateBundleID ( _ bundleID : String , source : Source ) -> SourceError { SourceError ( code : . duplicateBundleID , source : source , bundleID : bundleID ) }
static func duplicateVersion ( _ version : String , for app : StoreApp , source : Source ) -> SourceError { SourceError ( code : . duplicateVersion , source : source , app : app , version : version ) }
2023-05-15 16:25:25 -05:00
static func blocked ( _ source : Source ) -> SourceError { SourceError ( code : . blocked , source : source ) }
2023-05-15 15:38:54 -05:00
static func changedID ( _ identifier : String , previousID : String , source : Source ) -> SourceError { SourceError ( code : . changedID , source : source , sourceID : identifier , previousSourceID : previousID ) }
static func duplicate ( _ source : Source , previousSourceName : String ? ) -> SourceError { SourceError ( code : . duplicate , source : source , previousSourceName : previousSourceName ) }
static func missingPermissionUsageDescription ( for permission : any ALTAppPermission , app : StoreApp , source : Source ) -> SourceError {
SourceError ( code : . missingPermissionUsageDescription , source : source , app : app , permission : permission )
}
}
struct SourceError : ALTLocalizedError
{
let code : Code
var errorTitle : String ?
var errorFailure : String ?
@ Managed var source : Source
@ Managed var app : StoreApp ?
var bundleID : String ?
var version : String ?
@ UserInfoValue var previousSourceName : String ?
// S t o r e i n u s e r I n f o s o t h e y c a n b e v i e w e d f r o m E r r o r L o g .
@ UserInfoValue var sourceID : String ?
@ UserInfoValue var previousSourceID : String ?
@ UserInfoValue
var permission : ( any ALTAppPermission ) ?
var errorFailureReason : String {
switch self . code
{
case . unsupported : return String ( format : NSLocalizedString ( " The source “%@” is not supported by this version of AltStore. " , comment : " " ) , self . $ source . name )
case . duplicateBundleID :
let bundleIDFragment = self . bundleID . map { String ( format : NSLocalizedString ( " the bundle identifier %@ " , comment : " " ) , $0 ) } ? ? NSLocalizedString ( " the same bundle identifier " , comment : " " )
let failureReason = String ( format : NSLocalizedString ( " The source “%@” contains multiple apps with %@. " , comment : " " ) , self . $ source . name , bundleIDFragment )
return failureReason
case . duplicateVersion :
var versionFragment = NSLocalizedString ( " duplicate versions " , comment : " " )
if let version
{
versionFragment += " ( \( version ) ) "
}
let appFragment : String
if let name = self . $ app . name , let bundleID = self . $ app . bundleIdentifier
{
appFragment = name + " ( \( bundleID ) ) "
}
else
{
appFragment = NSLocalizedString ( " one or more apps " , comment : " " )
}
let failureReason = String ( format : NSLocalizedString ( " The source “%@” contains %@ for %@. " , comment : " " ) , self . $ source . name , versionFragment , appFragment )
return failureReason
2023-05-15 16:25:25 -05:00
case . blocked :
let failureReason = String ( format : NSLocalizedString ( " The source “%@” has been blocked by AltStore for security reasons. " , comment : " " ) , self . $ source . name )
return failureReason
2023-05-15 15:38:54 -05:00
case . changedID :
let failureReason = String ( format : NSLocalizedString ( " The identifier of the source “%@” has changed. " , comment : " " ) , self . $ source . name )
return failureReason
case . duplicate :
let baseMessage = String ( format : NSLocalizedString ( " A source with the identifier '%@' already exists " , comment : " " ) , self . $ source . identifier )
guard let previousSourceName else { return baseMessage + " . " }
let failureReason = baseMessage + " (“ \( previousSourceName ) ”). "
return failureReason
case . missingPermissionUsageDescription :
let appName = self . $ app . name ? ? String ( format : NSLocalizedString ( " an app in source “%@” " , comment : " " ) , self . $ source . name )
guard let permission else {
return String ( format : NSLocalizedString ( " A permission for %@ is missing a usage description. " , comment : " " ) , appName )
}
let permissionType = permission . type . localizedName ? ? NSLocalizedString ( " Permission " , comment : " " )
let failureReason = String ( format : NSLocalizedString ( " The %@ '%@' for %@ is missing a usage description. " , comment : " " ) , permissionType . lowercased ( ) , permission . rawValue , appName )
return failureReason
}
}
var recoverySuggestion : String ? {
switch self . code
{
2023-05-15 16:25:25 -05:00
case . blocked : return NSLocalizedString ( " For your protection, please remove the source and uninstall all apps downloaded from it. " , comment : " " )
2023-05-15 15:38:54 -05:00
case . changedID : return NSLocalizedString ( " A source cannot change its identifier once added. This source can no longer be updated. " , comment : " " )
case . duplicate :
let failureReason = NSLocalizedString ( " Please remove the existing source in order to add this one. " , comment : " " )
return failureReason
default : return nil
}
}
}