// // LoggedError.swift // AltStoreCore // // Created by Riley Testut on 9/6/22. // Copyright © 2022 Riley Testut. All rights reserved. // import CoreData extension LoggedError { public enum Operation: String { case install case update case refresh case activate case deactivate case backup case restore } } @objc(LoggedError) public class LoggedError: NSManagedObject, Fetchable { /* Properties */ @NSManaged public private(set) var date: Date @nonobjc public var operation: Operation? { guard let rawOperation = self._operation else { return nil } let operation = Operation(rawValue: rawOperation) return operation } @NSManaged @objc(operation) private var _operation: String? @NSManaged public private(set) var domain: String @NSManaged public private(set) var code: Int32 @NSManaged public private(set) var userInfo: [String: Any] @NSManaged public private(set) var appName: String @NSManaged public private(set) var appBundleID: String /* Relationships */ @NSManaged public private(set) var storeApp: StoreApp? @NSManaged public private(set) var installedApp: InstalledApp? private static let dateFormatter: DateFormatter = { let dateFormatter = DateFormatter() dateFormatter.dateStyle = .long dateFormatter.timeStyle = .none return dateFormatter }() private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) { super.init(entity: entity, insertInto: context) } public init(error: Error, app: AppProtocol, date: Date = Date(), operation: Operation? = nil, context: NSManagedObjectContext) { super.init(entity: LoggedError.entity(), insertInto: context) self.date = date self._operation = operation?.rawValue let nsError = error as NSError self.domain = nsError.domain self.code = Int32(nsError.code) self.userInfo = nsError.userInfo self.appName = app.name self.appBundleID = app.bundleIdentifier switch app { case let storeApp as StoreApp: self.storeApp = storeApp case let installedApp as InstalledApp: self.installedApp = installedApp default: break } } } public extension LoggedError { var app: AppProtocol { // `as AppProtocol` needed to fix "cannot convert AnyApp to StoreApp" compiler error with Xcode 14. let app = self.installedApp ?? self.storeApp ?? AnyApp(name: self.appName, bundleIdentifier: self.appBundleID, url: nil) as AppProtocol return app } var error: Error { let nsError = NSError(domain: self.domain, code: Int(self.code), userInfo: self.userInfo) return nsError } @objc var localizedDateString: String { let localizedDateString = LoggedError.dateFormatter.string(from: self.date) return localizedDateString } var localizedFailure: String? { guard let operation = self.operation else { return nil } switch operation { case .install: return String(format: NSLocalizedString("Install %@ Failed", comment: ""), self.appName) case .update: return String(format: NSLocalizedString("Update %@ Failed", comment: ""), self.appName) case .refresh: return String(format: NSLocalizedString("Refresh %@ Failed", comment: ""), self.appName) case .activate: return String(format: NSLocalizedString("Activate %@ Failed", comment: ""), self.appName) case .deactivate: return String(format: NSLocalizedString("Deactivate %@ Failed", comment: ""), self.appName) case .backup: return String(format: NSLocalizedString("Backup %@ Failed", comment: ""), self.appName) case .restore: return String(format: NSLocalizedString("Restore %@ Failed", comment: ""), self.appName) } } } public extension LoggedError { @nonobjc class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "LoggedError") } }