Includes more detailed info in VerificationError.addedPermission error messages

* New version
* Previous version
* Added permissions
This commit is contained in:
Riley Testut
2023-05-26 14:41:40 -05:00
committed by Magesh K
parent 0fa941e6ef
commit 8c85290c74
2 changed files with 65 additions and 34 deletions

View File

@@ -53,8 +53,8 @@ extension VerificationError
VerificationError(code: .undeclaredPermissions, app: app, permissions: permissions)
}
static func addedPermissions(_ permissions: [any ALTAppPermission], app: AppProtocol) -> VerificationError {
VerificationError(code: .addedPermissions, app: app, permissions: permissions)
static func addedPermissions(_ permissions: [any ALTAppPermission], appVersion: AppVersion) -> VerificationError {
VerificationError(code: .addedPermissions, app: appVersion, permissions: permissions)
}
}
@@ -158,8 +158,26 @@ struct VerificationError: ALTLocalizedError
return String(format: NSLocalizedString("%@ requires additional permissions not specified by the source.", comment: ""), appName)
case .addedPermissions:
let appName = self.$app.name ?? NSLocalizedString("The app", comment: "")
return String(format: NSLocalizedString("%@ requires more permissions than the version that is already installed.", comment: ""), appName)
let appName: String
let installedVersion: String?
if let appVersion = self.app as? AppVersion
{
let (name, version, previousVersion) = self.$app.perform { _ in (appVersion.name, appVersion.localizedVersion, appVersion.app?.installedApp?.localizedVersion) }
appName = name + " \(version)"
installedVersion = previousVersion.map { "(\(name) \($0))" } // Include app name because it looks weird to include build # in double parentheses without it.
}
else
{
appName = self.$app.name ?? NSLocalizedString("The app", comment: "")
installedVersion = nil
}
let baseMessage = String(format: NSLocalizedString("%@ requires more permissions than the version that is already installed", comment: ""), appName)
let failureReason = [baseMessage, installedVersion].compactMap { $0 }.joined(separator: " ") + "."
return failureReason
}
}
@@ -167,41 +185,54 @@ struct VerificationError: ALTLocalizedError
switch self.code
{
case .undeclaredPermissions:
guard let permissions, !permissions.isEmpty else { return nil }
guard let permissionsDescription else { return nil }
let baseMessage = NSLocalizedString("These permissions must be declared by the source in order for AltStore to install this app:", comment: "")
let recoverySuggestion = [baseMessage, permissionsDescription].joined(separator: "\n\n")
return recoverySuggestion
let permissionsByType = Dictionary(grouping: permissions) { $0.type }
let permissionSections = [ALTAppPermissionType.entitlement, .privacy, .backgroundMode].compactMap { (type) -> String? in
guard let permissions = permissionsByType[type] else { return nil }
// "Privacy:"
var sectionText = "\(type.localizedName ?? type.rawValue):\n"
// Sort permissions + join into single string.
let sortedList = permissions.map { permission -> String in
if let localizedName = permission.localizedName
{
// "Entitlement Name (com.apple.entitlement.name)"
return "\(localizedName) (\(permission.rawValue))"
}
else
{
// "com.apple.entitlement.name"
return permission.rawValue
}
}
.sorted { $0.localizedStandardCompare($1) == .orderedAscending } // Case-insensitive sorting
.joined(separator: "\n")
sectionText += sortedList
return sectionText
}
let recoverySuggestion = ([baseMessage] + permissionSections).joined(separator: "\n\n")
case .addedPermissions:
let recoverySuggestion = self.permissionsDescription
return recoverySuggestion
default: return nil
}
}
}
private extension VerificationError
{
var permissionsDescription: String? {
guard let permissions, !permissions.isEmpty else { return nil }
let permissionsByType = Dictionary(grouping: permissions) { $0.type }
let permissionSections = [ALTAppPermissionType.entitlement, .privacy, .backgroundMode].compactMap { (type) -> String? in
guard let permissions = permissionsByType[type] else { return nil }
// "Privacy:"
var sectionText = "\(type.localizedName ?? type.rawValue):\n"
// Sort permissions + join into single string.
let sortedList = permissions.map { permission -> String in
if let localizedName = permission.localizedName
{
// "Entitlement Name (com.apple.entitlement.name)"
return "\(localizedName) (\(permission.rawValue))"
}
else
{
// "com.apple.entitlement.name"
return permission.rawValue
}
}
.sorted { $0.localizedStandardCompare($1) == .orderedAscending } // Case-insensitive sorting
.joined(separator: "\n")
sectionText += sortedList
return sectionText
}
let permissionsDescription = permissionSections.joined(separator: "\n\n")
return permissionsDescription
}
}