diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e661e013..4b4b561e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -168,7 +168,8 @@ 526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */; }; 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */; }; 52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */; }; - 5823ADF62AB0F7BA006045A7 /* ReplacementMoleculeBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5823ADF52AB0F7BA006045A7 /* ReplacementMoleculeBehavior.swift */; }; + 5870636F2ACF238E00CA18D5 /* ReadableDecodingErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */; }; + 58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; }; 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */; }; 8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */; }; 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */; }; @@ -755,7 +756,8 @@ 526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnCompareChanges.swift; sourceTree = ""; }; 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethod.swift; sourceTree = ""; }; 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethodModel.swift; sourceTree = ""; }; - 5823ADF52AB0F7BA006045A7 /* ReplacementMoleculeBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplacementMoleculeBehavior.swift; sourceTree = ""; }; + 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadableDecodingErrors.swift; sourceTree = ""; }; + 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = ""; }; 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = ""; }; 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = ""; }; 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = ""; }; @@ -1387,12 +1389,12 @@ 27F973512466071600CAB5C5 /* Behaviors */ = { isa = PBXGroup; children = ( + 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */, 0A1C30972620F61A00B47F3B /* Protocols */, 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */, D23A900826125FFB007E14CE /* GetContactBehavior.swift */, D270E5662642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift */, 22B678F829E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift */, - 5823ADF52AB0F7BA006045A7 /* ReplacementMoleculeBehavior.swift */, ); path = Behaviors; sourceTree = ""; @@ -1566,6 +1568,7 @@ D202AFE2242A5F1400E5BEDF /* Extensions */ = { isa = PBXGroup; children = ( + 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */, D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */, 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */, D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */, @@ -2755,7 +2758,6 @@ 525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */, D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */, D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */, - 5823ADF62AB0F7BA006045A7 /* ReplacementMoleculeBehavior.swift in Sources */, D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */, AA37CBD3251907200027344C /* StarsModel.swift in Sources */, 8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */, @@ -2766,6 +2768,7 @@ 0A0FEC7425D42A5E00AF2548 /* BaseItemPickerEntryField.swift in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */, + 5870636F2ACF238E00CA18D5 /* ReadableDecodingErrors.swift in Sources */, 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */, 943820842432382400B43AF3 /* WebView.swift in Sources */, 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */, @@ -2915,6 +2918,7 @@ AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */, AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */, + 58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Extensions/ReadableDecodingErrors.swift b/MVMCoreUI/Atomic/Extensions/ReadableDecodingErrors.swift new file mode 100644 index 00000000..4b48b0a4 --- /dev/null +++ b/MVMCoreUI/Atomic/Extensions/ReadableDecodingErrors.swift @@ -0,0 +1,63 @@ +// +// ReadableDecodingErrors.swift +// MVMCore +// +// Created by Kyle Hedden on 10/5/23. +// Copyright © 2023 myverizon. All rights reserved. +// + +import Foundation + +protocol HumanReadableDecodingErrorProtocol { + var readableDescription: String { get } +} + +extension JSONError: HumanReadableDecodingErrorProtocol { + var readableDescription: String { + switch (self) { + case .other(let other): + if let other = other as? HumanReadableDecodingErrorProtocol { + return other.readableDescription + } + return description + default: + return description + } + } +} + +extension ModelRegistry.Error: HumanReadableDecodingErrorProtocol { + var readableDescription: String { + switch (self) { + case .decoderErrorModelNotMapped(let identifier, let codingKey, let codingPath) where identifier != nil && codingKey != nil && codingPath != nil: + return "Model identifier \"\(identifier!)\" is not mapped for \"\(codingKey!.stringValue)\" @ \(codingPath!.map { return $0.stringValue })" + + case .decoderErrorObjectNotPresent(let codingKey, let codingPath): + return "Required model \"\(codingKey.stringValue)\" was not found @ \(codingPath.map { return $0.stringValue })" + + default: + return "Registry error: \((self as NSError).localizedFailureReason ?? self.localizedDescription)" + } + } +} + +extension DecodingError: HumanReadableDecodingErrorProtocol { + var readableDescription: String { + switch (self) { + case .keyNotFound(let codingKey, let context): + return "Required key \(codingKey.stringValue) was not found @ \(context.codingPath.map { return $0.stringValue })" + + case .valueNotFound(_, let context): + return "Value not found @ \(context.codingPath.map { return $0.stringValue })" + + case .typeMismatch(_, let context): + return "Value type mismatch @ \(context.codingPath.map { return $0.stringValue })" + + case .dataCorrupted(let context): + return "Data corrupted @ \(context.codingPath.map { return $0.stringValue })" + + @unknown default: + return (self as NSError).localizedFailureReason ?? self.localizedDescription + } + } +} diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 73bba7b9..fdeeeed9 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -171,35 +171,8 @@ import MVMCore } func describe(parsingError: Error) -> String { - if let registryError = parsingError as? ModelRegistry.Error { - switch (registryError) { - case .decoderErrorModelNotMapped(let identifier, let codingKey, let codingPath) where identifier != nil && codingKey != nil && codingPath != nil: - return "Error parsing template. Model identifier \"\(identifier!)\" is not mapped for \"\(codingKey!.stringValue)\" @ \(codingPath!.map { return $0.stringValue })" - - case .decoderErrorObjectNotPresent(let codingKey, let codingPath): - return "Error parsing template. Required model \"\(codingKey.stringValue)\" was not found @ \(codingPath.map { return $0.stringValue })" - - default: - return "Error parsing template. Registry error: \((registryError as NSError).localizedFailureReason ?? registryError.localizedDescription)" - } - } - if let decodingError = parsingError as? DecodingError { - switch (decodingError) { - case .keyNotFound(let codingKey, let context): - return "Error parsing template. Required key \(codingKey.stringValue) was not found @ \(context.codingPath.map { return $0.stringValue })" - - case .valueNotFound(_, let context): - return "Error parsing template. Value not found @ \(context.codingPath.map { return $0.stringValue })" - - case .typeMismatch(_, let context): - return "Error parsing template. Value type mismatch @ \(context.codingPath.map { return $0.stringValue })" - - case .dataCorrupted(let context): - return "Error parsing template. Data corrupted @ \(context.codingPath.map { return $0.stringValue })" - - @unknown default: - return "Error parsing template. \((parsingError as NSError).localizedFailureReason ?? parsingError.localizedDescription)" - } + if let error = parsingError as? HumanReadableDecodingErrorProtocol { + return "Error parsing template. \(error.readableDescription)" } return "Error parsing template. \((parsingError as NSError).localizedFailureReason ?? parsingError.localizedDescription)" } diff --git a/MVMCoreUI/Behaviors/ReplacementMoleculeBehavior.swift b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift similarity index 71% rename from MVMCoreUI/Behaviors/ReplacementMoleculeBehavior.swift rename to MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift index 3773e717..d4d17c0d 100644 --- a/MVMCoreUI/Behaviors/ReplacementMoleculeBehavior.swift +++ b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift @@ -18,8 +18,12 @@ public class ReplaceableMoleculeBehaviorModel: PageBehaviorModelProtocol { public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior { var moleculeIds: [String] + public var transcendsPageUpdates: Bool { true } + public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { moleculeIds = (model as! ReplaceableMoleculeBehaviorModel).moleculeIds + guard let pageType = delegateObject?.moleculeDelegate?.getTemplateModel()?.pageType else { return } + MVMCoreViewControllerMappingObject.shared()?.addOptionalModules(toMapping: moleculeIds, forPageType: pageType) } public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) { @@ -36,7 +40,11 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior { MVMCoreLoggingHandler.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Failed to find '\(moleculeId)' in the current screen.", code: ErrorCode.viewControllerProcessingJSON.rawValue, domain: ErrorDomainSystem, location: String(describing: type(of: self)))!) } } catch { - MVMCoreLoggingHandler.addError(toLog: MVMCoreErrorObject.createErrorObject(for: error, location: String(describing: type(of: self)))!) + let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: String(describing: type(of: self)))! + if let error = error as? HumanReadableDecodingErrorProtocol { + coreError.messageToLog = "Error decoding replacement \"\(moleculeId)\": \(error.readableDescription)" + } + MVMCoreLoggingHandler.addError(toLog: coreError) } } }