mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-20 20:23:25 +01:00
Improves 10 App ID limit error handling
This commit is contained in:
@@ -502,8 +502,8 @@ extension AppViewController
|
|||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
let toastView = ToastView(error: error)
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2)
|
toastView.show(in: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -255,8 +255,8 @@ private extension BrowseViewController
|
|||||||
{
|
{
|
||||||
case .failure(OperationError.cancelled): break // Ignore
|
case .failure(OperationError.cancelled): break // Ignore
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
let toastView = ToastView(error: error)
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2)
|
toastView.show(in: self)
|
||||||
|
|
||||||
case .success: print("Installed app:", app.bundleIdentifier)
|
case .success: print("Installed app:", app.bundleIdentifier)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,35 @@ import Roxas
|
|||||||
|
|
||||||
class ToastView: RSTToastView
|
class ToastView: RSTToastView
|
||||||
{
|
{
|
||||||
|
var preferredDuration: TimeInterval
|
||||||
|
|
||||||
override init(text: String, detailText detailedText: String?)
|
override init(text: String, detailText detailedText: String?)
|
||||||
{
|
{
|
||||||
|
if detailedText == nil
|
||||||
|
{
|
||||||
|
self.preferredDuration = 2.0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.preferredDuration = 8.0
|
||||||
|
}
|
||||||
|
|
||||||
super.init(text: text, detailText: detailedText)
|
super.init(text: text, detailText: detailedText)
|
||||||
|
|
||||||
self.layoutMargins = UIEdgeInsets(top: 6, left: 12, bottom: 6, right: 12)
|
self.layoutMargins = UIEdgeInsets(top: 6, left: 12, bottom: 6, right: 12)
|
||||||
|
self.setNeedsLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(error: Error)
|
||||||
|
{
|
||||||
|
if let error = error as? LocalizedError
|
||||||
|
{
|
||||||
|
self.init(text: error.localizedDescription, detailText: error.recoverySuggestion ?? error.failureReason)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.init(text: error.localizedDescription, detailText: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init(coder aDecoder: NSCoder) {
|
required init(coder aDecoder: NSCoder) {
|
||||||
@@ -27,4 +51,14 @@ class ToastView: RSTToastView
|
|||||||
|
|
||||||
self.layer.cornerRadius = 16
|
self.layer.cornerRadius = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func show(in viewController: UIViewController)
|
||||||
|
{
|
||||||
|
self.show(in: viewController.navigationController?.view ?? viewController.view, duration: self.preferredDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func show(in view: UIView)
|
||||||
|
{
|
||||||
|
self.show(in: view, duration: self.preferredDuration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -383,9 +383,8 @@ private extension MyAppsViewController
|
|||||||
switch result
|
switch result
|
||||||
{
|
{
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
let toastView = ToastView(error: error)
|
||||||
toastView.setNeedsLayout()
|
toastView.show(in: self)
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
|
||||||
|
|
||||||
case .success(let results):
|
case .success(let results):
|
||||||
let failures = results.compactMapValues { (result) -> Error? in
|
let failures = results.compactMapValues { (result) -> Error? in
|
||||||
@@ -399,22 +398,32 @@ private extension MyAppsViewController
|
|||||||
|
|
||||||
guard !failures.isEmpty else { break }
|
guard !failures.isEmpty else { break }
|
||||||
|
|
||||||
let localizedText: String
|
let toastView: ToastView
|
||||||
let detailText: String?
|
|
||||||
|
|
||||||
if let failure = failures.first, failures.count == 1
|
if let failure = failures.first, results.count == 1
|
||||||
{
|
{
|
||||||
localizedText = failure.value.localizedDescription
|
toastView = ToastView(error: failure.value)
|
||||||
detailText = nil
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let localizedText: String
|
||||||
|
|
||||||
|
if failures.count == 1
|
||||||
|
{
|
||||||
|
localizedText = NSLocalizedString("Failed to refresh 1 app.", comment: "")
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
localizedText = String(format: NSLocalizedString("Failed to refresh %@ apps.", comment: ""), NSNumber(value: failures.count))
|
localizedText = String(format: NSLocalizedString("Failed to refresh %@ apps.", comment: ""), NSNumber(value: failures.count))
|
||||||
detailText = failures.first?.value.localizedDescription
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let toastView = ToastView(text: localizedText, detailText: detailText)
|
let detailText = failures.first?.value.localizedDescription
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
|
||||||
|
toastView = ToastView(text: localizedText, detailText: detailText)
|
||||||
|
toastView.preferredDuration = 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
toastView.show(in: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.refreshGroup = nil
|
self.refreshGroup = nil
|
||||||
@@ -574,8 +583,8 @@ private extension MyAppsViewController
|
|||||||
self.collectionView.reloadItems(at: [indexPath])
|
self.collectionView.reloadItems(at: [indexPath])
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
let toastView = ToastView(error: error)
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2)
|
toastView.show(in: self)
|
||||||
|
|
||||||
self.collectionView.reloadItems(at: [indexPath])
|
self.collectionView.reloadItems(at: [indexPath])
|
||||||
|
|
||||||
@@ -637,8 +646,8 @@ private extension MyAppsViewController
|
|||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if let error = result.error
|
if let error = result.error
|
||||||
{
|
{
|
||||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
let toastView = ToastView(error: error)
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
toastView.show(in: self)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -666,8 +675,8 @@ private extension MyAppsViewController
|
|||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = false
|
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = false
|
||||||
|
|
||||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
let toastView = ToastView(error: error)
|
||||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
toastView.show(in: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ enum OperationError: LocalizedError
|
|||||||
case invalidParameters
|
case invalidParameters
|
||||||
|
|
||||||
case iOSVersionNotSupported(ALTApplication)
|
case iOSVersionNotSupported(ALTApplication)
|
||||||
|
case maximumAppIDLimitReached(Date)
|
||||||
|
|
||||||
case noSources
|
case noSources
|
||||||
|
|
||||||
@@ -49,6 +50,37 @@ enum OperationError: LocalizedError
|
|||||||
|
|
||||||
let localizedDescription = String(format: NSLocalizedString("%@ requires %@.", comment: ""), name, version)
|
let localizedDescription = String(format: NSLocalizedString("%@ requires %@.", comment: ""), name, version)
|
||||||
return localizedDescription
|
return localizedDescription
|
||||||
|
|
||||||
|
case .maximumAppIDLimitReached: return NSLocalizedString("Cannot register more than 10 App IDs.", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var recoverySuggestion: String? {
|
||||||
|
switch self
|
||||||
|
{
|
||||||
|
case .maximumAppIDLimitReached(let date):
|
||||||
|
let remainingTime: String
|
||||||
|
|
||||||
|
let numberOfDays = date.numberOfCalendarDays(since: Date())
|
||||||
|
switch numberOfDays {
|
||||||
|
case 0:
|
||||||
|
let components = Calendar.current.dateComponents([.hour], from: Date(), to: date)
|
||||||
|
let numberOfHours = components.hour!
|
||||||
|
|
||||||
|
switch numberOfHours
|
||||||
|
{
|
||||||
|
case 1: remainingTime = NSLocalizedString("1 hour", comment: "")
|
||||||
|
default: remainingTime = String(format: NSLocalizedString("%@ hours", comment: ""), NSNumber(value: numberOfHours))
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: remainingTime = NSLocalizedString("1 day", comment: "")
|
||||||
|
default: remainingTime = String(format: NSLocalizedString("%@ days", comment: ""), NSNumber(value: numberOfDays))
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = String(format: NSLocalizedString("Delete sideloaded apps to free up App ID slots. You can register another App ID in %@.", comment: ""), remainingTime)
|
||||||
|
return message
|
||||||
|
|
||||||
|
default: return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,31 @@ private extension ResignAppOperation
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALTAppleAPI.shared.addAppID(withName: appName, bundleIdentifier: bundleIdentifier, team: team, session: session) { (appID, error) in
|
ALTAppleAPI.shared.addAppID(withName: appName, bundleIdentifier: bundleIdentifier, team: team, session: session) { (appID, error) in
|
||||||
completionHandler(Result(appID, error))
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let appID = try Result(appID, error).get()
|
||||||
|
completionHandler(.success(appID))
|
||||||
|
}
|
||||||
|
catch ALTAppleAPIError.maximumAppIDLimitReached
|
||||||
|
{
|
||||||
|
let sortedExpirationDates = appIDs.compactMap { $0.expirationDate }.sorted(by: { $0 < $1 })
|
||||||
|
|
||||||
|
if let expirationDate = sortedExpirationDates.first
|
||||||
|
{
|
||||||
|
throw OperationError.maximumAppIDLimitReached(expirationDate)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ALTAppleAPIError(.maximumAppIDLimitReached)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(error))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
Dependencies/AltSign
vendored
2
Dependencies/AltSign
vendored
Submodule Dependencies/AltSign updated: 4b43efed0d...8afbc8a845
Reference in New Issue
Block a user