From 5b83adf751b4bb29dc4eca984e764bed62b6280f Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Fri, 16 Jun 2023 14:04:42 -0400 Subject: [PATCH 01/61] Accessibility Traits Coddle --- .../Atomic/Atoms/Views/Label/Label.swift | 3 + .../Atomic/Atoms/Views/Label/LabelModel.swift | 4 + .../UIAccessibilityTraits+Codable.swift | 125 ++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 MVMCoreUI/Atomic/Extensions/UIAccessibilityTraits+Codable.swift diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 62dab9c2..01614f31 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -276,6 +276,9 @@ public typealias ActionBlock = () -> () guard let labelModel = model as? LabelModel else { return } text = labelModel.text + if let accessibilityTraits = labelModel.accessibilityTraits { + self.accessibilityTraits = accessibilityTraits + } resetAttributeStyle() diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift index d1995d19..70f1cc62 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift @@ -28,6 +28,7 @@ public var makeWholeViewClickable: Bool? public var numberOfLines: Int? public var shouldMaskRecordedView: Bool? = false + public var accessibilityTraits: UIAccessibilityTraits? //-------------------------------------------------- // MARK: - Keys @@ -50,6 +51,7 @@ case makeWholeViewClickable case numberOfLines case shouldMaskRecordedView + case accessibilityTraits } enum AttributeTypeKey: String, CodingKey { @@ -96,6 +98,7 @@ makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable) numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines) shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? false + accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) // Later make protocol based validate outside of decoding? if let attributes = attributes { @@ -121,5 +124,6 @@ try container.encodeIfPresent(makeWholeViewClickable, forKey: .makeWholeViewClickable) try container.encodeIfPresent(numberOfLines, forKey: .numberOfLines) try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView) + try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits) } } diff --git a/MVMCoreUI/Atomic/Extensions/UIAccessibilityTraits+Codable.swift b/MVMCoreUI/Atomic/Extensions/UIAccessibilityTraits+Codable.swift new file mode 100644 index 00000000..4eb1ea2a --- /dev/null +++ b/MVMCoreUI/Atomic/Extensions/UIAccessibilityTraits+Codable.swift @@ -0,0 +1,125 @@ +// +// UIAccessibilityTraits+Codable.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 6/16/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation + +extension UIAccessibilityTraits: Codable { + private static func trait(from string: String) throws -> UIAccessibilityTraits { + switch string { + case "none": + return .none + case "button": + return .button + case "link": + return .link + case "image": + return .image + case "searchField": + return .searchField + case "keyboardKey": + return .keyboardKey + case "staticText": + return .staticText + case "header": + return .header + case "tabBar": + return .tabBar + case "summaryElement": + return .summaryElement + case "selected": + return .selected + case "notEnabled": + return .notEnabled + case "adjustable": + return .adjustable + case "allowsDirectInteraction": + return .allowsDirectInteraction + case "updatesFrequently": + return .updatesFrequently + case "causesPageTurn": + return .causesPageTurn + case "playsSound": + return .playsSound + case "startsMediaSession": + return .startsMediaSession + default: + throw ModelRegistry.Error.decoderOther(message: "Unsupported accessibility trait: \(string)") + } + } + + public init(from decoder: Decoder) throws { + var container = try decoder.unkeyedContainer() + + // Iterate and decode each. + var accessibilityTrait: UIAccessibilityTraits = [] + while !container.isAtEnd { + let traitString = try container.decode(String.self) + let trait = try UIAccessibilityTraits.trait(from: traitString) + accessibilityTrait.insert(trait) + } + self = accessibilityTrait + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.unkeyedContainer() + if self.contains(.none) { + try container.encode("none") + } + if self.contains(.button) { + try container.encode("button") + } + if self.contains(.link) { + try container.encode("link") + } + if self.contains(.image) { + try container.encode("image") + } + if self.contains(.searchField) { + try container.encode("searchField") + } + if self.contains(.keyboardKey) { + try container.encode("keyboardKey") + } + if self.contains(.staticText) { + try container.encode("staticText") + } + if self.contains(.header) { + try container.encode("header") + } + if self.contains(.tabBar) { + try container.encode("tabBar") + } + if self.contains(.summaryElement) { + try container.encode("summaryElement") + } + if self.contains(.selected) { + try container.encode("selected") + } + if self.contains(.notEnabled) { + try container.encode("notEnabled") + } + if self.contains(.adjustable) { + try container.encode("adjustable") + } + if self.contains(.allowsDirectInteraction) { + try container.encode("allowsDirectInteraction") + } + if self.contains(.updatesFrequently) { + try container.encode("updatesFrequently") + } + if self.contains(.causesPageTurn) { + try container.encode("causesPageTurn") + } + if self.contains(.playsSound) { + try container.encode("playsSound") + } + if self.contains(.startsMediaSession) { + try container.encode("startsMediaSession") + } + } +} From 396635eee8a7cb4203b3842fae1d959f712dc43f Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Fri, 16 Jun 2023 14:10:04 -0400 Subject: [PATCH 02/61] Adding header example --- .../Headers/H2/HeadersH2NoButtonsBodyTextModel.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift index 96d30730..2a7994dd 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift @@ -33,6 +33,9 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } super.setDefaults() } From 89a87d597fcc4afb67612acd4da8c5b9e7bb32e0 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Tue, 27 Jun 2023 15:38:59 -0400 Subject: [PATCH 03/61] proj file --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0f339285..645d162f 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -288,6 +288,7 @@ AF1C33732885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */; }; AF60A7F62892D2E300919EEB /* ActionDismissNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */; }; AF60A7F82892D34D00919EEB /* ActionDismissNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */; }; + AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */; }; AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509629E477C0009DC2AD /* AlertHandler.swift */; }; AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509729E477C0009DC2AD /* AlertController.swift */; }; AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931F29E5CA73001A9663 /* AlertOperation.swift */; }; @@ -895,6 +896,7 @@ AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIActionOpenPageHandler.swift; sourceTree = ""; }; AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDismissNotificationModel.swift; sourceTree = ""; }; AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDismissNotificationHandler.swift; sourceTree = ""; }; + AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAccessibilityTraits+Codable.swift"; sourceTree = ""; }; AF7E509629E477C0009DC2AD /* AlertHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertHandler.swift; sourceTree = ""; }; AF7E509729E477C0009DC2AD /* AlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertController.swift; sourceTree = ""; }; AFA4931F29E5CA73001A9663 /* AlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertOperation.swift; sourceTree = ""; }; @@ -1623,6 +1625,7 @@ EA985C862981AB0F00F2FF2E /* VDS-Tilelet+Codable.swift */, EA985C882981AB7100F2FF2E /* VDS-TextStyle.swift */, EA985C8A2983259900F2FF2E /* VDS-LabelAttributeModel.swift */, + AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */, ); path = Extensions; sourceTree = ""; @@ -2916,6 +2919,7 @@ 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, 444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */, D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */, + AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */, D260105323CEA61600764D80 /* ToggleModel.swift in Sources */, 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */, 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */, From ad0087b88a2993645856bf8e742f12d6f83395fe Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 31 Jul 2023 14:33:20 -0400 Subject: [PATCH 04/61] Header traits --- .../Headers/H1/HeadersH1ButtonModel.swift | 18 +++++++++++++++++- .../H1/HeadersH1LandingPageHeaderModel.swift | 17 ++++++++++++++++- .../H1/HeadersH1NoButtonsBodyTextModel.swift | 17 ++++++++++++++++- .../Headers/H2/HeadersH2ButtonsModel.swift | 9 ++++++++- .../Headers/H2/HeadersH2CaretLinkModel.swift | 9 ++++++++- .../Headers/H2/HeadersH2LinkModel.swift | 9 ++++++++- .../H2/HeadersH2NoButtonsBodyTextModel.swift | 6 +++++- .../H2/HeadersH2PricingTwoRowsModel.swift | 9 ++++++++- .../Headers/H2/HeadersH2TinyButtonModel.swift | 9 ++++++++- ...eColumnFullWidthTextDividerSubsection.swift | 1 + ...mnFullWidthTextDividerSubsectionModel.swift | 6 +++++- ...eColumnTextWithWhitespaceDividerShort.swift | 1 + ...mnTextWithWhitespaceDividerShortModel.swift | 6 +++++- ...neColumnTextWithWhitespaceDividerTall.swift | 1 + ...umnTextWithWhitespaceDividerTallModel.swift | 6 +++++- 15 files changed, 112 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift index 25f59539..cdb61a4d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift @@ -7,7 +7,8 @@ // -public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -15,6 +16,10 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol { public var headlineBody: HeadlineBodyModel public var buttons: TwoButtonViewModel + public var children: [MoleculeModelProtocol] { + [headlineBody, buttons] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -25,6 +30,17 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol { super.init() } + //-------------------------------------------------- + // MARK: - Subclass + //-------------------------------------------------- + + public override func setDefaults() { + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } + super.setDefaults() + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1LandingPageHeaderModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1LandingPageHeaderModel.swift index d7603886..79705fd9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1LandingPageHeaderModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1LandingPageHeaderModel.swift @@ -8,7 +8,7 @@ import Foundation -public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -20,6 +20,10 @@ public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol public var link: LinkModel public var buttons: TwoButtonViewModel + public var children: [MoleculeModelProtocol] { + [headline, headline2, subHeadline, body, link, buttons] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -32,6 +36,17 @@ public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol self.buttons = buttons super.init() } + + //-------------------------------------------------- + // MARK: - Subclass + //-------------------------------------------------- + + public override func setDefaults() { + if headline.accessibilityTraits == nil { + headline.accessibilityTraits = .header + } + super.setDefaults() + } //-------------------------------------------------- // MARK: - Keys diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift index 864d88f1..9d246d98 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift @@ -8,7 +8,7 @@ -public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -16,6 +16,10 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol public static var identifier: String = "headerH1" public var headlineBody: HeadlineBodyModel + public var children: [MoleculeModelProtocol] { + [headlineBody] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -25,6 +29,17 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol super.init() } + //-------------------------------------------------- + // MARK: - Subclass + //-------------------------------------------------- + + public override func setDefaults() { + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } + super.setDefaults() + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift index d3ea7497..77bc25c1 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift @@ -9,7 +9,7 @@ import Foundation -public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -18,6 +18,10 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol { public var headlineBody: HeadlineBodyModel public var buttons: TwoButtonViewModel + public var children: [MoleculeModelProtocol] { + [headlineBody, buttons] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -39,6 +43,9 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol { if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } super.setDefaults() } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift index 9d56118e..e0831a40 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift @@ -7,7 +7,7 @@ // import Foundation -public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -15,6 +15,10 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol { public var headlineBody: HeadlineBodyModel public var caretLink: CaretLinkModel + public var children: [MoleculeModelProtocol] { + [headlineBody, caretLink] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -34,6 +38,9 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol { if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } super.setDefaults() } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift index 66189f99..20d6afe2 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift @@ -8,7 +8,7 @@ import Foundation -public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -17,6 +17,10 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol { public var headlineBody: HeadlineBodyModel public var link: LinkModel + public var children: [MoleculeModelProtocol] { + [headlineBody, link] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -38,6 +42,9 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol { if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } super.setDefaults() } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift index 2a7994dd..86d38707 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift @@ -9,7 +9,7 @@ import Foundation -public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -17,6 +17,10 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol public static var identifier: String = "headerH2" public var headlineBody: HeadlineBodyModel + public var children: [MoleculeModelProtocol] { + [headlineBody] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRowsModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRowsModel.swift index 5ca1eae1..ebca7e25 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRowsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRowsModel.swift @@ -8,7 +8,7 @@ import Foundation -public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -21,6 +21,10 @@ public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol { public var body3: LabelModel public var subBody3: LabelModel? + public var children: [MoleculeModelProtocol] { + [headline, body, subBody, body2, subBody2, body3, subBody3].compactMap({$0}) + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -45,6 +49,9 @@ public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol { if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } + if headline.accessibilityTraits == nil { + headline.accessibilityTraits = .header + } super.setDefaults() subBody?.attributes = [LabelAttributeStrikeThroughModel(0, subBody?.text.count ?? 0)] subBody2?.attributes = [LabelAttributeStrikeThroughModel(0, subBody2?.text.count ?? 0)] diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift index ce27740b..e04ab07f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift @@ -9,7 +9,7 @@ import Foundation -public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol { +public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -18,6 +18,10 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol { public var headlineBody: HeadlineBodyModel public var button: ButtonModel + public var children: [MoleculeModelProtocol] { + [headlineBody, button] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -39,6 +43,9 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol { if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } + if headlineBody.headline?.accessibilityTraits == nil { + headlineBody.headline?.accessibilityTraits = .header + } super.setDefaults() button.style = .secondary button.size = .small diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift index 3f48c3d8..b73b7129 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift @@ -84,5 +84,6 @@ import Foundation } accessibilityLabel = message + accessibilityTraits.update(with: .header) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift index 5040fbd4..8a039144 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift @@ -9,7 +9,7 @@ import Foundation -public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, MoleculeModelProtocol { +public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -18,6 +18,10 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo public var headline: LabelModel public var body: LabelModel? + public var children: [MoleculeModelProtocol] { + [headline, body].compactMap({$0}) + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift index 2f023b78..72dc78c0 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift @@ -84,5 +84,6 @@ import Foundation } accessibilityLabel = message + accessibilityTraits.update(with: .header) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift index 66025760..6a40ebf7 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift @@ -9,7 +9,7 @@ import Foundation -public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, MoleculeModelProtocol { +public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -18,6 +18,10 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo public var headline: LabelModel public var body: LabelModel? + public var children: [MoleculeModelProtocol] { + [headline, body].compactMap({$0}) + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift index 772ec5ac..169c33c9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift @@ -84,5 +84,6 @@ import Foundation } accessibilityLabel = message + accessibilityTraits.update(with: .header) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift index c713b0d2..09b462fe 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift @@ -9,7 +9,7 @@ import Foundation -public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, MoleculeModelProtocol { +public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -18,6 +18,10 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol public var headline: LabelModel public var body: LabelModel? + public var children: [MoleculeModelProtocol] { + [headline, body].compactMap({$0}) + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- From d02b346d39589cd5edd1725159502e63eb4027e6 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 31 Jul 2023 15:00:41 -0400 Subject: [PATCH 05/61] update dependency --- Scripts/download_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/download_dependencies.sh b/Scripts/download_dependencies.sh index ec05cfd8..ecfdb627 100755 --- a/Scripts/download_dependencies.sh +++ b/Scripts/download_dependencies.sh @@ -22,6 +22,6 @@ fi ./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDS.xcframework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/VDS/1.0/VDS-1.0-Debug-SNAPSHOT.zip -./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSColorTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSColorTokens.1.0.6.xcframework.zip +./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSColorTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSColorTokens.2.0.0.xcframework.zip ./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSFormControlsTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSFormControlsTokens.1.0.7.xcframework.zip From e7f21b980fd3f022226df0d1bd9260c61febcb69 Mon Sep 17 00:00:00 2001 From: Kyle Hedden Date: Wed, 9 Aug 2023 16:37:03 -0400 Subject: [PATCH 06/61] serialize timer updates to prevent cold dispatch collisions --- MVMCoreUI/Notification/NotificationHandler.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index ff9d90ad..c1e064d7 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -562,7 +562,9 @@ extension NotificationOperation { guard isExecuting, !isCancelled else { return } self.log(message: "Operation Updated") - updateStopTimer() + displayableQueue.async(flags: .barrier) { [self] in + updateStopTimer() + } Task { await transitionDelegate.update(with: notificationModel, delegateObject: delegateObject) NotificationHandler.shared()?.onNotificationUpdated.send((notification, notificationModel)) From d3fe47522cf4db0b4d348c50a08746deaea9a7b1 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Tue, 15 Aug 2023 16:23:13 -0400 Subject: [PATCH 07/61] Swiftification of Navigation Handler --- MVMCoreUI/Alerts/AlertOperation.swift | 58 +++++++------- .../FormFields/TextFields/MdnEntryField.swift | 4 +- .../CollapsableNotification.swift | 2 +- .../NavigationController.swift | 75 ++++++++++--------- .../UINavigationController+Extension.swift | 3 +- ...MCoreUISplitViewController+Extension.swift | 65 ++++++++++++---- .../MVMCoreUISplitViewController.m | 3 +- .../SubNav/SubNavManagerController.swift | 6 +- .../Notification/NotificationHandler.swift | 45 +++++------ MVMCoreUI/Utility/MVMCoreUIUtility.m | 1 - 10 files changed, 156 insertions(+), 106 deletions(-) diff --git a/MVMCoreUI/Alerts/AlertOperation.swift b/MVMCoreUI/Alerts/AlertOperation.swift index bbffbd32..088a6ff5 100644 --- a/MVMCoreUI/Alerts/AlertOperation.swift +++ b/MVMCoreUI/Alerts/AlertOperation.swift @@ -51,30 +51,33 @@ public class AlertOperation: MVMCoreOperation { // Observe for when it is removed. observeForCurrentAlertViewDismissal() - // Adds the presentation to the animation queue. - let blockingOperation = MVMCoreOperation() - self.blockingOperation = blockingOperation - Task { @MainActor in - MVMCoreNavigationHandler.shared()?.present(alertController, animated: true, delegate: nil) { [weak self] in - guard let self = self else { - blockingOperation.markAsFinished() - return - } - Task { - // We finished but it was not displayed yet. It's possible that it was cancelled. Finish this task - if await !self.properties.getIsDisplayed() { - self.markAsFinished() - } else { - (CoreUIObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject) - if self.isCancelled { - await self.dismissAlertView() - } - } - } + Task(priority: .high) { + guard let viewControllerToPresentOn = await NavigationHandler.shared().getViewControllerToPresentOn() else { + markAsFinished() + return } - // Block navigations until this alert is removed. - MVMCoreNavigationHandler.shared()?.addNavigationOperation(blockingOperation) + // Presents the alert. + let presentationOperation = await NavigationOperation(with: .present(viewController: alertController, onController: viewControllerToPresentOn), tryToReplace: false) + + let blockingOperation = MVMCoreOperation() + blockingOperation.addDependency(presentationOperation) + self.blockingOperation = blockingOperation + + // Block other navigation until this alert is removed. + NavigationHandler.shared().navigationQueue.addOperation(blockingOperation) + + await NavigationHandler.shared().navigate(with: presentationOperation) + + // We finished but it was not displayed yet. It's possible that it was cancelled. Finish this task + if await !self.properties.getIsDisplayed() { + self.markAsFinished() + } else { + (CoreUIObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject) + if self.isCancelled { + await self.dismissAlertView() + } + } } } @@ -89,10 +92,13 @@ public class AlertOperation: MVMCoreOperation { private func dismissAlertView() async { guard await properties.getIsDisplayed() else { return } await withCheckedContinuation { continuation in - Task { @MainActor in - MVMCoreNavigationHandler.shared()?.dismiss(alertController, animated: true, delegate: nil) { - continuation.resume() - } + Task { + let dismissOperation = await NavigationOperation(with: .dismiss(viewController: alertController)) + dismissOperation.queuePriority = .veryHigh + let task = Task(priority: .high) { await NavigationHandler.shared().navigate(with: dismissOperation) } + blockingOperation?.markAsFinished() + _ = await task.result + continuation.resume() } } } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/MdnEntryField.swift index 502682c2..910712d5 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/MdnEntryField.swift @@ -144,7 +144,9 @@ import MVMCore picker.displayedPropertyKeys = ["phoneNumbers"] picker.predicateForEnablingContact = NSPredicate(format: "phoneNumbers.@count > 0") picker.predicateForSelectionOfProperty = NSPredicate(format: "key == 'phoneNumbers'") - MVMCoreNavigationHandler.shared()?.present(picker, animated: true) + Task(priority: .userInitiated) { + await NavigationHandler.shared().present(viewController: picker, animated: true) + } } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 9e11ac02..4c677029 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -114,7 +114,7 @@ import MVMCore open func performBlockOperation(with block: @escaping (MVMCoreBlockOperation) -> Void) { let operation = MVMCoreBlockOperation(block: block)! - MVMCoreNavigationHandler.shared()?.addNavigationOperation(operation) + NavigationHandler.shared().navigationQueue.addOperation(operation) } /// Collapses after a delay diff --git a/MVMCoreUI/Containers/NavigationController/NavigationController.swift b/MVMCoreUI/Containers/NavigationController/NavigationController.swift index eb43201a..c613d3a7 100644 --- a/MVMCoreUI/Containers/NavigationController/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController/NavigationController.swift @@ -7,9 +7,12 @@ // import UIKit +import MVMCore +import Combine @objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol { public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)? + private var cancellables: Set = [] /// Getter for the main navigation controller public static func navigationController() -> Self? { @@ -20,9 +23,9 @@ import UIKit public static func setupNavigationController() -> Self? { let navigationController = self.init() MVMCoreUISession.sharedGlobal()?.navigationController = navigationController - MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController - MVMCoreNavigationHandler.shared()?.navigationController = navigationController - MVMCoreNavigationHandler.shared()?.addDelegate(navigationController) + NavigationHandler.shared().viewControllerToPresentOn = navigationController + NavigationHandler.shared().navigationController = navigationController + navigationController.subscribe() navigationController.setNavigationBarUI(with: NavigationItemModel()) return navigationController } @@ -34,14 +37,44 @@ import UIKit return navigationController } - /// Convenience function to return the navigation model of the lowest controller traversing managers if applicable. + /** Subscribes for events. + Updates the navigation item of the new view controller when one is pushed. + Based on ``NavigationItemModelProtocol`` of ``PageProtocol/pageModel``. Traverses the manager for the view controller if necessary. + */ + @MainActor + public func subscribe() { + NavigationHandler.shared().onNavigationWillBegin.sink { [weak self] navigationType in + guard let self = self, + self == navigationType.getNavigationController(), + let viewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last, + let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } + if let model = getNavigationModel(from: newViewController) { + self.setNavigationItem(with: model, for: viewController) + self.setNavigationBarUI(with: model) + } + self.manager?.willDisplay?(newViewController) + }.store(in: &cancellables) + + NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] navigationType in + guard let self = self, + self == navigationType.getNavigationController(), + let viewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last, + let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } + self.manager?.displayedViewController?(newViewController) + if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { + controller.viewControllerReady?(inManager: self) + } + }.store(in: &cancellables) + } + + /// Convenience function to return the navigation model of the view controller. public func getNavigationModel(from viewController: UIViewController) -> NavigationItemModelProtocol? { return (viewController as? PageProtocol)?.pageModel?.navigationBar } /// Verifies the controller is the currently displayed controller. public func isDisplayed(viewController: UIViewController) -> Bool { - guard let topViewController = topViewController, + guard let topViewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last, viewController == MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { return false } @@ -84,8 +117,10 @@ extension NavigationController: MVMCoreViewManagerProtocol { manager?.willDisplay?(viewController) } + /// Updates the navigation item/bar of the current view controller based on the passed in model and view controller. + @MainActor private func updateNavigationView(with model: NavigationItemModelProtocol, for viewController: UIViewController) { - guard let topViewController = topViewController else { return } + guard let topViewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last else { return } setNavigationItem(with: model, for: topViewController, coordinatingWith: viewController as? PageBehaviorHandlerProtocol) setNavigationBarUI(with: model) @@ -99,34 +134,6 @@ extension NavigationController: MVMCoreViewManagerProtocol { } } -extension NavigationController: MVMCorePresentationDelegateProtocol { - public func navigationController(_ navigationController: UINavigationController, prepareDisplayFor viewController: UIViewController) { - if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { - MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller) - } - guard self == navigationController, - let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController), - let model = getNavigationModel(from: newViewController) else { return } - setNavigationItem(with: model, for: viewController) - setNavigationBarUI(with: model) - } - - public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) { - guard self == navigationController, - let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } - manager?.willDisplay?(newViewController) - } - - public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) { - guard self == navigationController, - let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } - manager?.displayedViewController?(newViewController) - if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { - controller.viewControllerReady?(inManager: self) - } - } -} - extension UIColor { func image(_ size: CGSize = CGSize(width: 1, height: 1)) -> UIImage { return UIGraphicsImageRenderer(size: size).image { rendererContext in diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index e1d3a247..5ffe202c 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -7,6 +7,7 @@ // import Foundation +import MVMCore public extension UINavigationController { @@ -38,7 +39,7 @@ public extension UINavigationController { if model.hidesSystemBackButton, model.alwaysShowBackButton != false { if let backButtonModel = model.backButton, - MVMCoreNavigationHandler.shared()?.getViewControllers(for: self)?.count ?? 0 > 1 || model.alwaysShowBackButton ?? false { + MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).count ?? 0 > 1 || model.alwaysShowBackButton ?? false { leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) } if let leftItemModels = model.additionalLeftButtons { diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index 8b509827..dadd5025 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -20,7 +20,8 @@ public protocol StatusBarUI { // Navigation bar update functions public extension MVMCoreUISplitViewController { - /// Updates the state for various controls (navigation, tab, progress) for the controller. + /// Updates the state for various controls (top navigation controller item, tab, progress) for the controller. + @MainActor func updateState(with viewController: UIViewController) { guard let navigationController = navigationController, navigationController.isDisplayed(viewController: viewController) else { return } @@ -30,7 +31,9 @@ public extension MVMCoreUISplitViewController { } // MARK: - Progress Bar - /// Updates the progress bar based on the page json for the view controller. + /** Updates the progress bar based on the page json for the view controller. + Uses a string value between 0 and 100 from key progressPercent in the MVMCoreViewControllerProtocol.loadObject.pageJSON. + */ func updateProgressBar(for viewController: UIViewController) { guard let viewController = viewController as? MVMCoreViewControllerProtocol else { return } var progress: Float = 0.0 @@ -42,12 +45,16 @@ public extension MVMCoreUISplitViewController { } // MARK: - Tab Bar - /// Updates the tab bar based on the page json for the view controller. + /** Updates the tab bar based on the page json for the view controller. + For the index: checks the view controller's pageModel (``PageProtocol``) property ``TabPageModelProtocol/tabBarIndex``, else tabBarIndex in action map that led to this page, else the previous tab bar index of this page. + For hidden: checks the view controller's pageModel (``PageProtocol``) property ``TabPageModelProtocol/tabBarHidden``, else tabBarHidden in action map that led to this page, else it is visibile. + */ + @MainActor func updateTabBar(for viewController: UIViewController) { let mvmViewController = viewController as? MVMCoreViewControllerProtocol tabBar?.delegateObject = mvmViewController?.delegateObject?() as? MVMCoreUIDelegateObject - let navigationIndex = (MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 1) - 1 + let navigationIndex = (navigationController != nil ? (MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController!).count ?? 1) : 1) - 1 // Set the highlighted index. In terms of priority, Page > Action > Previous. if let index = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarIndex { @@ -80,10 +87,13 @@ public extension MVMCoreUISplitViewController { } // MARK: - Navigation Bar - /// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol. + /** Convenience function. Sets the navigation and split view properties for the view controller. + Panel access is determined if view controller is a ``MVMCoreUIDetailViewProtocol`` + */ + @MainActor func setNavigationBar(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) { guard navigationController == self.navigationController, - viewController == getCurrentDetailViewController() else { + self.navigationController?.isDisplayed(viewController: viewController) == true else { /// Not the split view navigation controller, skip split functions. return } @@ -97,9 +107,13 @@ public extension MVMCoreUISplitViewController { setNavigationIconColor(navigationItemModel.tintColor.uiColor) } - /// Sets the left navigation items for the view controller based on model and splitview. + /** Sets the left navigation items for the top view controller based on the model and viewController. + Panel access is determined if view controller is a ``MVMCoreUIDetailViewProtocol`` + */ + @MainActor func setLeftNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) { - guard let topViewController = navigationController.topViewController else { return } + guard let viewControllers = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController), + let topViewController = viewControllers.last else { return } var leftItems: [UIBarButtonItem] = [] let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject @@ -110,7 +124,7 @@ public extension MVMCoreUISplitViewController { if let forceBackButton = navigationItemModel?.alwaysShowBackButton { showBackButton = forceBackButton } else { - showBackButton = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 0 > 1 + showBackButton = viewControllers.count > 1 } if showBackButton { if let backButtonModel = navigationItemModel?.backButton { @@ -144,9 +158,12 @@ public extension MVMCoreUISplitViewController { topViewController.navigationItem.setLeftBarButtonItems(leftItems.count > 0 ? leftItems : nil, animated: !DisableAnimations.boolValue) } - /// Sets the right navigation items for the view controller based on model and splitview. + /** Sets the right navigation items for the top view controller based on the model and viewController. + Panel access is determined if view controller is a ``MVMCoreUIDetailViewProtocol`` + */ + @MainActor func setRightNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) { - guard let topViewController = navigationController.topViewController else { return } + guard let topViewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController).last else { return } let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject var rightItems: [UIBarButtonItem] = [] @@ -173,6 +190,9 @@ public extension MVMCoreUISplitViewController { topViewController.navigationItem.setRightBarButtonItems(rightItems.count > 0 ? rightItems : nil, animated: !DisableAnimations.boolValue) } + /** If the current detail view controller has a navigation model. + ``NavigationController/getNavigationModel(from:)`` from ``getCurrentDetailViewController()`` + */ @objc func navigationBarModelExists() -> Bool { // Legacy Navigation guard let currentViewController = getCurrentDetailViewController(), @@ -180,8 +200,9 @@ public extension MVMCoreUISplitViewController { return true } - /// Convenience function to update the navigation bar if the controller is the current lowest controller. - @objc func updateNavigationBarFor(viewController: UIViewController) { + /// Convenience function to update the navigation bar if the controller is the current detail controller. + @MainActor @objc + func updateNavigationBarFor(viewController: UIViewController) { guard let navigationController = navigationController, navigationController.isDisplayed(viewController: viewController), let model = navigationController.getNavigationModel(from: viewController) else { return } @@ -201,9 +222,13 @@ public extension MVMCoreUISplitViewController { return .default } - /// Updates the status bar background color and style. - @objc func setStatusBarForCurrentViewController() { - let viewController = getCurrentViewController() as? MVMCoreUIDetailViewProtocol + /** Updates the status bar background color and style for the passed view controller. + The background color is fetched from ``MVMCoreUIDetailViewProtocol/defaultStatusBarBackgroundColor()``, else the current navigation bar background, else the current status bar background color. + The backgroundStytle is fetched from ``MVMCoreUIDetailViewProtocol/defaultStatusBarStyle()`` else ``getStatusBarStyle(for:)`` + */ + @MainActor + func setStatusBar(for viewController: UIViewController?) { + let viewController = viewController as? MVMCoreUIDetailViewProtocol let backgroundColor = viewController?.defaultStatusBarBackgroundColor?() ?? navigationController?.navigationBar.standardAppearance.backgroundColor ?? statusBarView?.backgroundColor @@ -213,6 +238,14 @@ public extension MVMCoreUISplitViewController { setStatusBarBackgroundColor(backgroundColor, style: style) } + + /** Updates the status bar background color and style for the current view controller. + See ``setStatusBar(for:)`` + */ + @MainActor + @objc func setStatusBarForCurrentViewController() { + setStatusBar(for: getCurrentViewController()) + } } extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol { diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index 045dd0bf..c499596a 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -7,7 +7,6 @@ // #import "MVMCoreUISplitViewController.h" -@import MVMCore.MVMCoreNavigationHandler; @import MVMCore.MVMCoreDispatchUtility; @import MVMCore.MVMCoreViewManagerProtocol; @import MVMCore.MVMCoreActionUtility; @@ -1074,7 +1073,7 @@ CGFloat const PanelAnimationDuration = 0.2; // Returns the desired view or falls back. Hot fix until we can get away from using these functions... + (CGRect)getBounds:(UIView *)desiredView { - UIView *view = desiredView ?: [MVMCoreNavigationHandler sharedNavigationHandler].navigationController.view ?: [MVMCoreGetterUtility getKeyWindow].rootViewController.view; + UIView *view = desiredView ?: [self mainSplitViewController].navigationController.view ?: [MVMCoreGetterUtility getKeyWindow].rootViewController.view; return view ? view.bounds : [UIScreen mainScreen].bounds; } diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index db339cf8..c2c01c1b 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -205,7 +205,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } } - public func navigationController(_ navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { + public func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { // Only percent interact if we've already loaded the view controller guard let customInteractor = customInteractor, let index = index, @@ -272,7 +272,9 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, if let controller = viewControllers[indexPath.row] { // Load controller from the cache needToTrackTabSelect = true - MVMCoreNavigationHandler.shared()?.replaceTopViewController(with: controller, navigationController: subNavigationController, animated: true, delegate: self, replaceInStack: false, completionHandler: nil) + Task(priority: .userInitiated) { + await NavigationHandler.shared().replace(viewController: controller, navigationController: subNavigationController, tryToReplace: false, animated: true) + } } else if let tabsModel = tabs.tabsModel, let action = tabsModel.tabs[indexPath.row].action { // Perform the tab action diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index ff9d90ad..2c367f90 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -268,7 +268,7 @@ public class NotificationOperation: MVMCoreOperation { } })! transitionOperation.completionBlock = completionBlock - MVMCoreNavigationHandler.shared()?.addNavigationOperation(transitionOperation) + NavigationHandler.shared().navigationQueue.addOperation(transitionOperation) return transitionOperation } @@ -314,6 +314,8 @@ open class NotificationHandler { private var transitionDelegate: NotificationTransitionDelegateProtocol + private var cancellable: Cancellable? + // MARK: - Publishers /// Publishes when a notification will show. @@ -354,7 +356,26 @@ open class NotificationHandler { /// Registers to know when pages change. private func registerForPageChanges() { - MVMCoreNavigationHandler.shared()?.addDelegate(self) + cancellable = NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] navigationType in + // Update displayable for each top alert operation when page type changes, in top queue priority order. + guard let self = self, + self.queue.operations.count > 0, + let navigationController = navigationType.getNavigationController(), + navigationController == MVMCoreUISplitViewController.main()?.navigationController, + let viewController = navigationController.viewControllers.last, + let traversedController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } + let pageType = (traversedController as? MVMCoreViewControllerProtocol)?.pageType + Task { + self.queue.operations.compactMap { + $0 as? NotificationOperation + }.sorted { + $0.notificationModel.priority.rawValue > $1.notificationModel.priority.rawValue + }.forEach { + $0.updateDisplayable(by: pageType) + } + self.reevaluteQueue() + } + } } /// Checks for new top alert json @@ -534,26 +555,6 @@ open class NotificationHandler { } } -extension NotificationHandler: MVMCorePresentationDelegateProtocol { - // Update displayable for each top alert operation when page type changes, in top queue priority order. - public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) { - guard queue.operations.count > 0 else { return } - let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) - guard viewController == MVMCoreUISplitViewController.main()?.getCurrentViewController() else { return } - let pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType - Task { - queue.operations.compactMap { - $0 as? NotificationOperation - }.sorted { - $0.notificationModel.priority.rawValue > $1.notificationModel.priority.rawValue - }.forEach { - $0.updateDisplayable(by: pageType) - } - reevaluteQueue() - } - } -} - extension NotificationOperation { /// Updates the operation and notification with the new model. public func update(with model: NotificationModel, delegateObject: MVMCoreUIDelegateObject?) { diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility.m b/MVMCoreUI/Utility/MVMCoreUIUtility.m index 01a8c435..e99a6383 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility.m +++ b/MVMCoreUI/Utility/MVMCoreUIUtility.m @@ -11,7 +11,6 @@ #import "MVMCoreUISession.h" #import "MVMCoreUISplitViewController.h" #import -@import MVMCore.MVMCoreNavigationHandler; @import MVMCore.MVMCoreGetterUtility; @implementation MVMCoreUIUtility From ba8aa92994ed1111adce1723d3185a9f8edbcf02 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 21 Aug 2023 17:03:49 -0400 Subject: [PATCH 08/61] ONEAPP-5208: Swiftify the navigation handler --- .../NavigationController.swift | 20 +++++++++------- .../UINavigationController+Extension.swift | 9 ++++++- ...MCoreUISplitViewController+Extension.swift | 19 +++++++++++---- .../MVMCoreUISplitViewController.m | 23 +++--------------- .../SubNav/SubNavInteractor.swift.swift | 10 ++++++-- .../SubNav/SubNavManagerController.swift | 4 ++-- .../Notification/NotificationHandler.swift | 4 ++-- .../MVMCoreUIActionHandler.swift | 4 +++- .../Utility/MVMCoreUIUtility+Extension.swift | 24 ++++++++++++++++++- MVMCoreUI/Utility/MVMCoreUIUtility.m | 17 ++++--------- 10 files changed, 79 insertions(+), 55 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController/NavigationController.swift b/MVMCoreUI/Containers/NavigationController/NavigationController.swift index c613d3a7..36be6d45 100644 --- a/MVMCoreUI/Containers/NavigationController/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController/NavigationController.swift @@ -43,11 +43,14 @@ import Combine */ @MainActor public func subscribe() { - NavigationHandler.shared().onNavigationWillBegin.sink { [weak self] navigationType in + NavigationHandler.shared().onNavigationWillBegin.sink { [weak self] operation in guard let self = self, - self == navigationType.getNavigationController(), - let viewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last, + self == operation.navigationType.getNavigationController(), + let viewController = NavigationHandler.shared().getViewControllers(for: self).last, let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } + if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { + MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller) + } if let model = getNavigationModel(from: newViewController) { self.setNavigationItem(with: model, for: viewController) self.setNavigationBarUI(with: model) @@ -55,10 +58,10 @@ import Combine self.manager?.willDisplay?(newViewController) }.store(in: &cancellables) - NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] navigationType in + NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] operation in guard let self = self, - self == navigationType.getNavigationController(), - let viewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last, + self == operation.navigationType.getNavigationController(), + let viewController = NavigationHandler.shared().getViewControllers(for: self).last, let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } self.manager?.displayedViewController?(newViewController) if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { @@ -74,8 +77,7 @@ import Combine /// Verifies the controller is the currently displayed controller. public func isDisplayed(viewController: UIViewController) -> Bool { - guard let topViewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last, - viewController == MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { + guard viewController == getViewController() else { return false } return true @@ -120,7 +122,7 @@ extension NavigationController: MVMCoreViewManagerProtocol { /// Updates the navigation item/bar of the current view controller based on the passed in model and view controller. @MainActor private func updateNavigationView(with model: NavigationItemModelProtocol, for viewController: UIViewController) { - guard let topViewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).last else { return } + guard let topViewController = NavigationHandler.shared().getViewControllers(for: self).last else { return } setNavigationItem(with: model, for: topViewController, coordinatingWith: viewController as? PageBehaviorHandlerProtocol) setNavigationBarUI(with: model) diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index 5ffe202c..625f0a25 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -39,7 +39,7 @@ public extension UINavigationController { if model.hidesSystemBackButton, model.alwaysShowBackButton != false { if let backButtonModel = model.backButton, - MVMCoreNavigationHandler.shared()?.getViewControllers(for: self).count ?? 0 > 1 || model.alwaysShowBackButton ?? false { + NavigationHandler.shared().getViewControllers(for: self).count > 1 || model.alwaysShowBackButton ?? false { leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) } if let leftItemModels = model.additionalLeftButtons { @@ -114,4 +114,11 @@ public extension UINavigationController { setNavigationBarHidden(model.hidden, animated: true) } + + @MainActor + func getViewController() -> UIViewController? { + guard let topViewController = getViewControllers().last, + let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { return nil } + return viewController + } } diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index dadd5025..20f4449c 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -54,7 +54,7 @@ public extension MVMCoreUISplitViewController { let mvmViewController = viewController as? MVMCoreViewControllerProtocol tabBar?.delegateObject = mvmViewController?.delegateObject?() as? MVMCoreUIDelegateObject - let navigationIndex = (navigationController != nil ? (MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController!).count ?? 1) : 1) - 1 + let navigationIndex = (navigationController != nil ? NavigationHandler.shared().getViewControllers(for: navigationController!).count : 1) - 1 // Set the highlighted index. In terms of priority, Page > Action > Previous. if let index = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarIndex { @@ -112,8 +112,8 @@ public extension MVMCoreUISplitViewController { */ @MainActor func setLeftNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) { - guard let viewControllers = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController), - let topViewController = viewControllers.last else { return } + let viewControllers = NavigationHandler.shared().getViewControllers(for: navigationController) + guard let topViewController = viewControllers.last else { return } var leftItems: [UIBarButtonItem] = [] let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject @@ -163,7 +163,7 @@ public extension MVMCoreUISplitViewController { */ @MainActor func setRightNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) { - guard let topViewController = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController).last else { return } + guard let topViewController = NavigationHandler.shared().getViewControllers(for: navigationController).last else { return } let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject var rightItems: [UIBarButtonItem] = [] @@ -268,6 +268,17 @@ extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol { } @objc public extension MVMCoreUISplitViewController { + @objc func goBack() { + Task(priority: .userInitiated) { @MainActor in + if let viewController = getCurrentDetailViewController() as? MVMCoreUIDetailViewProtocol, + let backButtonPressed = viewController.backButtonPressed { + backButtonPressed() + } else { + await NavigationHandler.shared().popTopViewController() + } + } + } + /// Subscribes for notification events. @objc func subscribeForNotifications() { guard cancellables == nil else { return } diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index c499596a..c43d17d9 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -191,14 +191,7 @@ CGFloat const PanelAnimationDuration = 0.2; } - (IBAction)backButtonPressed:(id)sender { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - UIViewController *detailViewController = [self getCurrentDetailViewController]; - if ([detailViewController conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)] && [detailViewController respondsToSelector:@selector(backButtonPressed)]) { - [((UIViewController *)detailViewController) backButtonPressed]; - } else { - [[MVMCoreNavigationHandler sharedNavigationHandler] popTopViewControllerAnimated:YES]; - } - }]; + [self goBack]; } - (IBAction)rightPanelButtonPressed:(id)sender { @@ -257,7 +250,7 @@ CGFloat const PanelAnimationDuration = 0.2; - (void)setLeftNavigationItemForViewController:(UIViewController * _Nonnull)viewController accessible:(BOOL)accessible extended:(BOOL)extended { NSMutableArray *leftBarButtonItems = [NSMutableArray array]; - if (self.navigationController && [MVMCoreNavigationHandler.sharedNavigationHandler getViewControllersForNavigationController:self.navigationController].count > 1) { + if (self.navigationController && [self.navigationController getViewControllers].count > 1) { [leftBarButtonItems addObject:self.backButton]; } if ((accessible && !extended) && self.leftPanelButton) { @@ -1098,17 +1091,7 @@ CGFloat const PanelAnimationDuration = 0.2; } - (UIViewController *)getCurrentVisibleController { - UIViewController *baseViewController = [MVMCoreNavigationHandler sharedNavigationHandler].viewControllerToPresentOn ?: [MVMCoreGetterUtility getKeyWindow].rootViewController; - UIViewController *viewController = nil; - while (baseViewController.presentedViewController && !baseViewController.presentedViewController.isBeingDismissed) { - viewController = baseViewController.presentedViewController; - baseViewController = viewController; - } - // if it is not presented viewcontroller, existing BAU logic will be working - if (!viewController) { - viewController = [MVMCoreUIUtility getViewControllerTraversingManagers:self.navigationController.topViewController]; - } - return viewController; + return [MVMCoreUIUtility getCurrentVisibleController]; } - (UIViewController *)getCurrentDetailViewController { diff --git a/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift b/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift index 233a1f57..eb4dcdda 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift @@ -90,6 +90,8 @@ fileprivate enum SubNavPanningDirection : Int { switch (pan.state) { case .began: + print("sssss \(#function) began") + // Begin the transition to the next page. panning = true if velocityX < 0 && pannableFrameRight.contains(locationInView) { @@ -117,11 +119,15 @@ fileprivate enum SubNavPanningDirection : Int { shouldCompleteTransition = percentage > 0.65; update(percentage) delegate?.update(percentage: percentage) - + print("sssss \(#function) changed \(percentage)") + case .cancelled: cancel() - + print("sssss \(#function) cancelled") + case .ended: + print("sssss \(#function) ended") + if ((percentage < 0) != (velocityX < 0)) && abs(velocityX) > 50 { // If we are moving back toward the previous view we want to cancel. (the speed threshold is for shaky hands) cancel() diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index c2c01c1b..7bdee349 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -229,7 +229,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, hideNavigationBarLine(true) } - public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) { + public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { guard navigationController == subNavigationController else { return } if let viewController = viewController as? UIViewController & MVMCoreViewManagerViewControllerProtocol & MVMCoreViewControllerProtocol { @@ -247,7 +247,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, commitTo(controller: viewController) } - public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) { + public func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { guard navigationController == subNavigationController else { return } // Need to track swipe action. if needToTrackTabSelect { diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index c031ac77..627d611a 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -356,11 +356,11 @@ open class NotificationHandler { /// Registers to know when pages change. private func registerForPageChanges() { - cancellable = NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] navigationType in + cancellable = NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] operation in // Update displayable for each top alert operation when page type changes, in top queue priority order. guard let self = self, self.queue.operations.count > 0, - let navigationController = navigationType.getNavigationController(), + let navigationController = operation.navigationType.getNavigationController(), navigationController == MVMCoreUISplitViewController.main()?.navigationController, let viewController = navigationController.viewControllers.last, let traversedController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIActionHandler.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIActionHandler.swift index b2c3d42c..49a3d5e9 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIActionHandler.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIActionHandler.swift @@ -57,6 +57,8 @@ import SafariServices @MainActor open func openURL(inSafariWebView url: URL) { let safariViewController = SFSafariViewController(url: url) - MVMCoreNavigationHandler.shared()?.present(safariViewController, animated: true) + Task(priority: .high) { + await NavigationHandler.shared().present(viewController: safariViewController) + } } } diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift index ffb74ef9..e04de6bb 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift +++ b/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift @@ -7,7 +7,7 @@ // import UIKit - +import MVMCore public extension MVMCoreUIUtility { @@ -66,3 +66,25 @@ public extension MVMCoreUIUtility { return nil } } + +@objc +public extension MVMCoreUIUtility { + @objc @MainActor + static func getVisibleViewController() -> UIViewController? { + var viewController = NavigationHandler.shared().getViewControllerToPresentOn() + while let presentedController = viewController?.presentedViewController, + !presentedController.isBeingDismissed { + viewController = presentedController + } + if let navigationController = viewController as? UINavigationController { + viewController = navigationController.topViewController + } + if let viewController = viewController { + return getViewControllerTraversingManagers(viewController) + } else if let viewController = MVMCoreUISession.sharedGlobal()?.navigationController?.topViewController { + return getViewControllerTraversingManagers(viewController) + } else { + return nil + } + } +} diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility.m b/MVMCoreUI/Utility/MVMCoreUIUtility.m index e99a6383..ad7366df 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility.m +++ b/MVMCoreUI/Utility/MVMCoreUIUtility.m @@ -51,19 +51,10 @@ } + (UIViewController *)getCurrentVisibleController { - UIViewController *baseViewController = [MVMCoreNavigationHandler sharedNavigationHandler].viewControllerToPresentOn ?: [MVMCoreGetterUtility getKeyWindow].rootViewController; - UIViewController *viewController = nil; - while (baseViewController.presentedViewController && !baseViewController.presentedViewController.isBeingDismissed) { - viewController = baseViewController.presentedViewController; - baseViewController = viewController; - } - if ([viewController isKindOfClass:[UINavigationController class]]) { - viewController = ((UINavigationController *)viewController).topViewController; - } - // if it is not presented viewcontroller, existing BAU logic will be working - if (!viewController) { - viewController = [self getViewControllerTraversingManagers:[MVMCoreUISession sharedGlobal].navigationController.topViewController]; - } + __block UIViewController *viewController = nil; + [MVMCoreDispatchUtility performSyncBlockOnMainThread:^{ + viewController = [self getVisibleViewController]; + }]; return viewController; } From 07fcca17fc269044fc849f40510b90fdd64ded9d Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 21 Aug 2023 17:20:27 -0400 Subject: [PATCH 09/61] Remove debug comments --- MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift b/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift index eb4dcdda..233a1f57 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavInteractor.swift.swift @@ -90,8 +90,6 @@ fileprivate enum SubNavPanningDirection : Int { switch (pan.state) { case .began: - print("sssss \(#function) began") - // Begin the transition to the next page. panning = true if velocityX < 0 && pannableFrameRight.contains(locationInView) { @@ -119,15 +117,11 @@ fileprivate enum SubNavPanningDirection : Int { shouldCompleteTransition = percentage > 0.65; update(percentage) delegate?.update(percentage: percentage) - print("sssss \(#function) changed \(percentage)") - + case .cancelled: cancel() - print("sssss \(#function) cancelled") - + case .ended: - print("sssss \(#function) ended") - if ((percentage < 0) != (velocityX < 0)) && abs(velocityX) > 50 { // If we are moving back toward the previous view we want to cancel. (the speed threshold is for shaky hands) cancel() From caab123781f92eeb958514c19308bf88922ce7e4 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 21 Aug 2023 18:03:05 -0400 Subject: [PATCH 10/61] update check for notification handler --- MVMCoreUI/Notification/NotificationHandler.swift | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index 627d611a..8971bd5a 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -357,15 +357,14 @@ open class NotificationHandler { /// Registers to know when pages change. private func registerForPageChanges() { cancellable = NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] operation in - // Update displayable for each top alert operation when page type changes, in top queue priority order. - guard let self = self, - self.queue.operations.count > 0, - let navigationController = operation.navigationType.getNavigationController(), - navigationController == MVMCoreUISplitViewController.main()?.navigationController, - let viewController = navigationController.viewControllers.last, - let traversedController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } - let pageType = (traversedController as? MVMCoreViewControllerProtocol)?.pageType + guard let self = self else { return } Task { + // Update displayable for each top alert operation when page type changes, in top queue priority order. + guard self.queue.operations.count > 0, + let navigationController = await operation.navigationType.getNavigationController(), + await navigationController == MVMCoreUISplitViewController.main()?.navigationController, + let viewController = await navigationController.getViewController() else { return } + let pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType self.queue.operations.compactMap { $0 as? NotificationOperation }.sorted { From e8fcf1ac5ddc5f6961223d9dbd1f0ce068beb707 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 28 Aug 2023 11:13:40 -0400 Subject: [PATCH 11/61] ONEAPP-5208: Review feedback --- .../NavigationController.swift | 36 +++++++++---------- .../Notification/NotificationHandler.swift | 4 ++- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController/NavigationController.swift b/MVMCoreUI/Containers/NavigationController/NavigationController.swift index 36be6d45..8f72a792 100644 --- a/MVMCoreUI/Containers/NavigationController/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController/NavigationController.swift @@ -43,29 +43,27 @@ import Combine */ @MainActor public func subscribe() { - NavigationHandler.shared().onNavigationWillBegin.sink { [weak self] operation in + NavigationHandler.shared().onNavigation.sink { [weak self] (event, operation) in guard let self = self, self == operation.navigationType.getNavigationController(), let viewController = NavigationHandler.shared().getViewControllers(for: self).last, let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } - if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { - MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller) - } - if let model = getNavigationModel(from: newViewController) { - self.setNavigationItem(with: model, for: viewController) - self.setNavigationBarUI(with: model) - } - self.manager?.willDisplay?(newViewController) - }.store(in: &cancellables) - - NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] operation in - guard let self = self, - self == operation.navigationType.getNavigationController(), - let viewController = NavigationHandler.shared().getViewControllers(for: self).last, - let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } - self.manager?.displayedViewController?(newViewController) - if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { - controller.viewControllerReady?(inManager: self) + switch event { + case .willNavigate: + if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { + MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller) + } + if let model = getNavigationModel(from: newViewController) { + self.setNavigationItem(with: model, for: viewController) + self.setNavigationBarUI(with: model) + } + self.manager?.willDisplay?(newViewController) + case .didNavigate: + self.manager?.displayedViewController?(newViewController) + if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { + controller.viewControllerReady?(inManager: self) + } + @unknown default: break } }.store(in: &cancellables) } diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index 8971bd5a..9ecc2efb 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -356,7 +356,9 @@ open class NotificationHandler { /// Registers to know when pages change. private func registerForPageChanges() { - cancellable = NavigationHandler.shared().onNavigationDidFinish.sink { [weak self] operation in + cancellable = NavigationHandler.shared().onNavigation + .filter({ $0.0 == .didNavigate }) + .sink { [weak self] (event, operation) in guard let self = self else { return } Task { // Update displayable for each top alert operation when page type changes, in top queue priority order. From 0e68df5624f056ab3401d77ac699a8588e15fa93 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 30 Aug 2023 15:58:21 -0500 Subject: [PATCH 12/61] fixed refactor bug Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift b/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift index c87e091c..41d68493 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift @@ -37,8 +37,11 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{ padding = viewModel.padding aspectRatio = viewModel.aspectRatio width = viewModel.width - textWidth = viewModel.textWidth - textPercentage = viewModel.textPercentage + if let value = viewModel.textWidth { + textWidth = .value(value) + } else if let percentage = viewModel.textPercentage { + textWidth = .percentage(percentage) + } titleModel = viewModel.titleModel(delegateObject: delegateObject, additionalData: additionalData) subTitleModel = viewModel.subTitleModel(delegateObject: delegateObject, additionalData: additionalData) badgeModel = viewModel.badge From 7da47bb77a1bfeb97e1fcfb748e21acfde40eadf Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Tue, 5 Sep 2023 21:02:24 -0400 Subject: [PATCH 13/61] Add an optional ID field to every molecule. --- .../Atomic/Atoms/Buttons/ButtonModel.swift | 5 ++++ .../Atomic/Atoms/Buttons/CaretLinkModel.swift | 4 +++ .../Atoms/Buttons/ImageButtonModel.swift | 4 ++- .../Atomic/Atoms/Buttons/Link/LinkModel.swift | 4 +++ .../Atoms/FormFields/Tags/TagModel.swift | 3 ++ .../Atoms/FormFields/Tags/TagsModel.swift | 5 ++++ .../TextFields/EntryFieldModel.swift | 4 +++ .../Atoms/Selectors/CheckboxModel.swift | 2 ++ .../Atomic/Atoms/Selectors/HeartModel.swift | 5 ++++ .../Atoms/Selectors/RadioBoxModel.swift | 6 ++++ .../Atoms/Selectors/RadioBoxesModel.swift | 3 ++ .../Atoms/Selectors/RadioButtonModel.swift | 5 ++++ .../Atoms/Selectors/RadioSwatchModel.swift | 5 ++++ .../Atoms/Selectors/RadioSwatchesModel.swift | 5 ++++ .../Atomic/Atoms/Selectors/ToggleModel.swift | 6 ++++ MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift | 7 +++-- .../Atomic/Atoms/Views/CaretViewModel.swift | 2 ++ .../CarouselIndicatorModel.swift | 2 ++ .../Atoms/Views/CheckboxLabelModel.swift | 2 ++ .../Atomic/Atoms/Views/DashLineModel.swift | 6 ++++ .../Atomic/Atoms/Views/ImageViewModel.swift | 2 ++ .../Atomic/Atoms/Views/Label/LabelModel.swift | 7 +++-- .../Atoms/Views/LeftRightLabelModel.swift | 2 ++ MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 6 ++++ .../Atoms/Views/LoadingSpinnerModel.swift | 8 +++-- .../Atoms/Views/MultiProgressModel.swift | 6 ++++ .../Atomic/Atoms/Views/ProgressBarModel.swift | 5 ++++ MVMCoreUI/Atomic/Atoms/Views/StarModel.swift | 5 ++++ MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift | 4 +++ .../Atomic/Atoms/Views/TileletModel.swift | 1 + .../Atomic/Atoms/Views/Video/VideoModel.swift | 2 ++ .../Atomic/Atoms/Views/WebViewModel.swift | 5 ++++ MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift | 6 ++++ .../LockUps/LockUpsPlanNamesModel.swift | 5 ++++ .../LockUps/LockupsPlanSMLXLModel.swift | 5 ++++ .../LockUps/TitleLockupModel.swift | 4 +++ .../Doughnut/DoughnutChartItemModel.swift | 4 ++- .../Doughnut/DoughnutChartModel.swift | 4 ++- .../ImageHeadlineBodyModel.swift | 2 ++ .../RadioButtonLabelModel.swift | 2 ++ .../TabBarModel.swift | 5 ++++ .../TabsModel.swift | 5 ++++ .../TwoButtonViewModel.swift | 1 + .../TwoLinkViewModel.swift | 5 ++++ .../ActionDetailWithImageModel.swift | 2 ++ .../LeftRightViews/CornerLabelsModel.swift | 1 + .../HeadlineBodyLinkToggleModel.swift | 1 + .../HeadlineBodyToggleModel.swift | 1 + .../ToggleMolecules/LabelToggleModel.swift | 5 ++++ .../Buttons/NavigationImageButtonModel.swift | 6 +++- .../Buttons/NavigationLabelButtonModel.swift | 7 ++++- .../NavigationBar/NavigationItemModel.swift | 4 +++ .../OtherContainers/ModuleMoleculeModel.swift | 8 ++++- .../NotificationXButtonModel.swift | 6 ++++ .../EyebrowHeadlineBodyLinkModel.swift | 4 +++ .../HeadlineBodyButtonModel.swift | 5 ++++ .../HeadlineBodyCaretLinkImageModel.swift | 1 + .../HeadlineBodyLinkModel.swift | 2 ++ .../HeadlineBodyModel.swift | 14 +++++++++ .../StringAndMoleculeModel.swift | 5 ++++ .../ThreeHeadlineBodyLinkModel.swift | 5 ++++ .../Organisms/Carousel/CarouselModel.swift | 5 ++++ .../MoleculeModelProtocol.swift | 10 +++---- .../ParentMoleculeModelProtocol.swift | 30 ++++++++++++++----- .../TemplateModelProtocol.swift | 2 +- .../MoleculeTreeTraversalProtocol.swift | 11 +++++-- .../Containers/Views/ContainerModel.swift | 7 +++++ 67 files changed, 300 insertions(+), 28 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index 8818107b..b3c23e87 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -18,6 +18,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat //-------------------------------------------------- //Making static property as class property so that subclasses can override getter function of the property open class var identifier: String { "button" } + public var id: String = { return UUID().uuidString }() + public var accessibilityIdentifier: String? public var accessibilityText: String? public var title: String @@ -174,6 +176,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -201,6 +204,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) title = try typeContainer.decode(String.self, forKey: .title) @@ -263,6 +267,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(title, forKey: .title) try container.encode(enabled, forKey: .enabled) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift index 71431d0f..399219cb 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift @@ -16,6 +16,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea //-------------------------------------------------- public static var identifier: String = "caretLink" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var accessibilityIdentifier: String? public var title: String @@ -41,6 +42,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case backgroundColor case accessibilityIdentifier case title @@ -61,6 +63,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) title = try typeContainer.decode(String.self, forKey: .title) @@ -94,6 +97,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift index 560027f3..df24270d 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift @@ -14,8 +14,9 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro //-------------------------------------------------- public static var identifier: String = "imageButton" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? - public var image: ImageViewModel? public var accessibilityText: String? @@ -34,6 +35,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro } private enum CodingKeys: String, CodingKey { + case id case moleculeName case image case backgroundColor diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift index 38bcb491..5b290d6e 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift @@ -15,6 +15,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode //-------------------------------------------------- public class var identifier: String { "link" } + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var accessibilityIdentifier: String? @@ -48,6 +49,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -91,6 +93,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) title = try typeContainer.decode(String.self, forKey: .title) @@ -137,6 +140,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(title, forKey: .title) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift index 823d2478..d7148baa 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift @@ -11,11 +11,14 @@ import MVMCore @objcMembers public class TagModel: MoleculeModelProtocol { public static var identifier: String = "tag" + public var id: String = { return UUID().uuidString }() + public var label: LabelModel public var action: ActionModelProtocol? public var backgroundColor: Color? private enum CodingKeys: String, CodingKey { + case id case moleculeName case label case action diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift index 6330bb94..24adcc43 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift @@ -11,10 +11,13 @@ import MVMCore @objcMembers public class TagsModel: MoleculeModelProtocol { public static var identifier: String = "tags" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var tags: [TagModel] private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case tags @@ -30,12 +33,14 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString tags = try typeContainer.decode([TagModel].self, forKey: .tags) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tags, forKey: .tags) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 7b3eee03..92ad5c53 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -16,6 +16,7 @@ import Foundation //-------------------------------------------------- public class var identifier: String { "" } + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var accessibilityIdentifier: String? @@ -63,6 +64,7 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -138,6 +140,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) @@ -166,6 +169,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift index 7b6b36d8..6f30282e 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift @@ -20,6 +20,7 @@ //-------------------------------------------------- public static var identifier: String = "checkbox" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var accessibilityIdentifier: String? public var selected: Bool = false @@ -51,6 +52,7 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case accessibilityIdentifier case checked diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift index 4be1343a..7580e6e0 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift @@ -14,6 +14,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- public static var identifier: String = "heart" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var accessibilityIdentifier: String? public var isActive: Bool = false @@ -27,6 +29,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -49,6 +52,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let isActive = try typeContainer.decodeIfPresent(Bool.self, forKey: .isActive) { self.isActive = isActive } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index 27defd48..cf592ecb 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -13,6 +13,8 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioBox" + public var id: String = { return UUID().uuidString }() + public var text: String public var subText: String? public var backgroundColor: Color? @@ -30,6 +32,7 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case text case subText @@ -58,6 +61,8 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString text = try typeContainer.decode(String.self, forKey: .text) subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText) selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) @@ -81,6 +86,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(text, forKey: .text) try container.encodeIfPresent(subText, forKey: .subText) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 6348eac5..f4f538d6 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -13,6 +13,8 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioBoxes" + public var id: String = { return UUID().uuidString }() + public var boxes: [RadioBoxModel] public var backgroundColor: Color? public var accessibilityIdentifier: String? @@ -49,6 +51,7 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case enabled case readOnly diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 86eb36e9..497a0b1c 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -15,6 +15,8 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- public static var identifier: String = "radioButton" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var accessibilityIdentifier: String? public var state: Bool = false @@ -35,6 +37,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -80,6 +83,8 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.state = state } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift index f0a194e9..1f47abc4 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift @@ -13,6 +13,8 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioSwatch" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var accessibilityIdentifier: String? public var color: Color = Color(uiColor: .mvmBlue) @@ -29,6 +31,7 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -54,6 +57,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) @@ -79,6 +83,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index d5d3992a..9a154167 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -13,6 +13,8 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioSwatches" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var accessibilityIdentifier: String? public var swatches: [RadioSwatchModel] @@ -43,6 +45,7 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -67,6 +70,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches) @@ -81,6 +85,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index e8d50851..3973f0bc 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -13,6 +13,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- public static var identifier: String = "toggle" + public var id: String = { return UUID().uuidString }() + public var accessibilityIdentifier: String? public var backgroundColor: Color? public var selected: Bool = false @@ -36,6 +38,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case state case animated @@ -86,6 +89,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.selected = state } @@ -128,6 +133,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeModelIfPresent(action, forKey: .action) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift index 388f1669..05b54373 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift @@ -17,8 +17,9 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol { public static var identifier: String { return "arrow" } - public var moleculeName: String? + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var disabledColor: Color = Color(uiColor: .mvmCoolGray3) public var color: Color = Color(uiColor: .mvmBlack) @@ -57,6 +58,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case disabledColor @@ -75,7 +77,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) if let disabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) { @@ -113,6 +115,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(disabledColor, forKey: .disabledColor) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift index 1e2595ec..a5ebc86d 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift @@ -15,6 +15,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "caretView" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var strokeColor: Color = Color(uiColor: .mvmBlack) public var strokeColor_inverted: Color = Color(uiColor: .mvmWhite) @@ -28,6 +29,7 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case strokeColor diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift index 164bb306..d1d762c1 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift @@ -18,6 +18,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro return "" } + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var moleculeName: String? public var numberOfPages: Int = 0 @@ -44,6 +45,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case currentIndex diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index 58f398b6..11252461 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -18,6 +18,8 @@ public enum CheckboxPosition: String, Codable { @objcMembers open class CheckboxLabelModel: MoleculeModelProtocol { open class var identifier: String { "checkboxLabel" } public var moleculeName: String = CheckboxLabelModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var checkboxAlignment: CheckboxPosition? public var checkbox: CheckboxModel diff --git a/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift index 95cc40fd..30864afc 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift @@ -15,6 +15,8 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "dashLine" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var accessibilityIdentifier: String? public var dashColor: Color = Color(uiColor: .mvmCoolGray3) @@ -35,6 +37,7 @@ import MVMCore //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case accessibilityIdentifier @@ -56,6 +59,8 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let dashColor = try typeContainer.decodeIfPresent(Color.self, forKey: .dashColor) { self.dashColor = dashColor } @@ -74,6 +79,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(dashColor, forKey: .dashColor) try container.encode(isHidden, forKey: .isHidden) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift index c61739a7..4c37a2d8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift @@ -13,6 +13,7 @@ //-------------------------------------------------- open class var identifier: String { "image" } + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var moleculeName: String = ImageViewModel.identifier @@ -45,6 +46,7 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case image diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift index 76b534a5..19284756 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift @@ -7,13 +7,14 @@ // -@objcMembers open class LabelModel: MoleculeModelProtocol, Identifiable { +@objcMembers open class LabelModel: MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- open class var identifier: String { "label" } public var id: String + public var backgroundColor: Color? public var text: String public var accessibilityText: String? @@ -35,8 +36,8 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case moleculeName case id + case moleculeName case text case accessibilityText case textColor @@ -110,7 +111,7 @@ open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(id, forKey: .id) + try container.encode(id, forKey: .id) try container.encode(text, forKey: .text) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(textColor, forKey: .textColor) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift index 07c534f8..1574567a 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift @@ -15,6 +15,8 @@ import UIKit public static var identifier: String = "leftRightLabelView" public var moleculeName: String = LeftRightLabelModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var leftText: LabelModel public var rightText: LabelModel? diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index cc9e7333..4850ac21 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -53,6 +53,8 @@ import VDSColorTokens //-------------------------------------------------- public static var identifier: String = "line" + public var id: String = { return UUID().uuidString }() + public var type: Style = .secondary public var frequency: Frequency? = .allExceptTop @@ -120,6 +122,7 @@ import VDSColorTokens //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case type case backgroundColor @@ -138,6 +141,8 @@ import VDSColorTokens required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let type = try typeContainer.decodeIfPresent(Style.self, forKey: .type) { self.type = type } @@ -158,6 +163,7 @@ import VDSColorTokens public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(id, forKey: .id) try container.encode(type, forKey: .type) try container.encode(inverted, forKey: .inverted) try container.encodeIfPresent(frequency, forKey: .frequency) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift index ddfba326..064d6c38 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift @@ -13,9 +13,10 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - public var backgroundColor: Color? public static var identifier: String = "loadingSpinner" + public var id: String = { return UUID().uuidString }() + + public var backgroundColor: Color? public var strokeColor = Color(uiColor: .mvmBlack) public var lineWidth: CGFloat = 4 public var diameter: CGFloat = 40 @@ -25,6 +26,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case strokeColor @@ -45,6 +47,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) { @@ -62,6 +65,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(diameter, forKey: .diameter) diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift index fb70ffd0..cadee43d 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift @@ -19,13 +19,17 @@ import Foundation } @objcMembers public class MultiProgressBarModel: MoleculeModelProtocol { + public static var identifier: String = "multiProgressBar" + public var id: String = { return UUID().uuidString }() + public var progressList: [SingleProgressBarModel] public var backgroundColor: Color? public var thickness: CGFloat? public var roundedCorners: Bool? private enum CodingKeys: String, CodingKey { + case id case moleculeName case progressList case thickness @@ -39,6 +43,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) @@ -47,6 +52,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(progressList, forKey: .progressList) try container.encodeIfPresent(thickness, forKey: .thickness) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift index 7cef8936..fd24858e 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift @@ -10,6 +10,8 @@ import Foundation @objcMembers public class ProgressBarModel: MoleculeModelProtocol { public static var identifier: String = "progressBar" + public var id: String = { return UUID().uuidString }() + @Percent public var percent: CGFloat public var color: Color = Color(uiColor: .mfCerulean()) public var backgroundColor: Color? = Color(uiColor: .mfLightSilver()) @@ -17,6 +19,7 @@ import Foundation public var thickness: CGFloat? private enum CodingKeys: String, CodingKey { + case id case moleculeName case roundedCorners case thickness @@ -31,6 +34,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString percent = try typeContainer.decode(CGFloat.self, forKey: .percent) if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) { self.color = color @@ -44,6 +48,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(percent, forKey: .percent) try container.encode(color, forKey: .color) diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift index 56f4f7ad..520425f7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift @@ -13,6 +13,8 @@ open class StarModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "star" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? @Percent public var percent: CGFloat = 0 public var borderColor: Color? @@ -23,6 +25,7 @@ open class StarModel: MoleculeModelProtocol { // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case percent @@ -43,6 +46,7 @@ open class StarModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString if let percent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .percent) { self.percent = percent } @@ -56,6 +60,7 @@ open class StarModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(percent, forKey: .percent) diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift index f79f638e..a2d04d66 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift @@ -13,6 +13,8 @@ import MVMCore // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "stars" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var starBackgroundColor: Color? public var stars: [StarModel] @@ -25,6 +27,7 @@ import MVMCore // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case starBackgroundColor @@ -48,6 +51,7 @@ import MVMCore //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + stars = try typeContainer.decode([StarModel].self, forKey: .stars) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) starBackgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .starBackgroundColor) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift index 620e0940..a7e09cb2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift @@ -15,6 +15,7 @@ open class TileletModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "tilelet" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var color: TileContainer.BackgroundColor public var padding: TileContainer.Padding diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift index 7c348760..b34cc7aa 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift @@ -10,6 +10,7 @@ import Foundation open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { public static var identifier = "video" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var video: String public var showControls = false @@ -43,6 +44,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { private var resignActiveListener: Any? private enum CodingKeys: String, CodingKey { + case id case moleculeName case video case showControls diff --git a/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift index 4cb2bd55..e953e2ab 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift @@ -12,6 +12,8 @@ import MVMCore @objcMembers public class WebViewModel: MoleculeModelProtocol { public static var identifier: String = "webview" public var moleculeName: String = WebViewModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var url: URL? public var htmlString: String? @@ -23,6 +25,7 @@ import MVMCore } private enum CodingKeys: String, CodingKey{ + case id case moleculeName case backgroundColor case url @@ -39,6 +42,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) url = try typeContainer.decodeIfPresent(URL.self, forKey: .url) htmlString = try typeContainer.decodeIfPresent(String.self, forKey: .htmlString) @@ -51,6 +55,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(url, forKey: .url) diff --git a/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift index 85e4fffb..32284277 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift @@ -19,6 +19,8 @@ public enum GraphStyle: String, Codable { public class WheelModel: MoleculeModelProtocol { public static var identifier: String = "wheel" + public var id: String = { return UUID().uuidString }() + public var style: GraphStyle = .unlimited { didSet { updateStyle() @@ -43,6 +45,7 @@ public class WheelModel: MoleculeModelProtocol { } private enum CodingKeys: String, CodingKey { + case id case style case size case diameter @@ -56,6 +59,8 @@ public class WheelModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let style = try typeContainer.decodeIfPresent(GraphStyle.self, forKey: .style) { self.style = style } @@ -84,6 +89,7 @@ public class WheelModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(style, forKey: .style) try container.encode(size, forKey: .size) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift index 0d68da42..5a172208 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift @@ -13,6 +13,8 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "planNamesLockup" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var headline: LabelModel public var subHeadline: LabelModel @@ -31,6 +33,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol { // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case headline @@ -43,6 +46,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol { //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) headline = try typeContainer.decode(LabelModel.self, forKey: .headline) subHeadline = try typeContainer.decode(LabelModel.self, forKey: .subHeadline) @@ -51,6 +55,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(headline, forKey: .headline) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift index 433bc322..ee684645 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift @@ -14,6 +14,8 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "planLockup" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var planLabel : LabelModel public var headline : LabelModel @@ -43,6 +45,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case planLabel @@ -57,6 +60,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) planLabel = try typeContainer.decode(LabelModel.self, forKey: .planLabel) headline = try typeContainer.decode(LabelModel.self, forKey: .headline) @@ -67,6 +71,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(planLabel, forKey: .planLabel) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift index 4548207d..9e55db1b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift @@ -16,6 +16,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco public static var identifier: String = "titleLockup" public var moleculeName: String = TitleLockupModel.identifier + public var id: String = { return UUID().uuidString }() public var eyebrow: LabelModel? public var title: LabelModel @@ -130,6 +131,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case eyebrow @@ -145,6 +147,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString title = try typeContainer.decodeMolecule(codingKey: .title) eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) subTitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subTitle) @@ -164,6 +167,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(eyebrow, forKey: .eyebrow) try container.encodeModel(title, forKey: .title) diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift index ee4e664a..187fc8a5 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift @@ -14,9 +14,11 @@ import Foundation // MARK: - Properties //-------------------------------------------------- - public var backgroundColor: Color? public static var identifier: String = "doughnutChartItem" public var moleculeName: String = DoughnutChartItemModel.identifier + public var id: String = { return UUID().uuidString }() + + public var backgroundColor: Color? public var label: LabelModel @Percent public var percent: CGFloat public var color: Color diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift index fbb034c6..07d7756f 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift @@ -14,9 +14,11 @@ import Foundation // MARK: - Properties //-------------------------------------------------- - public var backgroundColor: Color? public static var identifier: String = "doughnutChart" public var moleculeName: String = DoughnutChartModel.identifier + public var id: String = { return UUID().uuidString }() + + public var backgroundColor: Color? public var title: LabelModel? public var subtitle: LabelModel? public var sections: [DoughnutChartItemModel] diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index 2c188d6b..08fe6db3 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -15,6 +15,8 @@ public class ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" public var moleculeName: String = ImageHeadlineBodyModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var image: ImageViewModel public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 69bca3fc..ea574220 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -15,6 +15,8 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioButtonLabel" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var moleculeName: String = RadioButtonLabelModel.identifier public var radioButton: RadioButtonModel diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index 3b62210c..a40d303f 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -11,6 +11,8 @@ import VDSColorTokens open class TabBarModel: MoleculeModelProtocol { public static var identifier: String = "tabBar" + public var id: String = { return UUID().uuidString }() + open var tabs: [TabBarItemModel] private var _backgroundColor: Color? @@ -58,6 +60,7 @@ open class TabBarModel: MoleculeModelProtocol { open var selectedTab: Int = 0 private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case tabs @@ -73,6 +76,7 @@ open class TabBarModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString tabs = try typeContainer.decode([TabBarItemModel].self, forKey: .tabs) if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) { backgroundColor = color @@ -93,6 +97,7 @@ open class TabBarModel: MoleculeModelProtocol { open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 6e154895..e938c119 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -11,6 +11,8 @@ import VDSColorTokens open class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" + public var id: String = { return UUID().uuidString }() + open var tabs: [TabItemModel] open var style: NavigationItemStyle? @@ -71,6 +73,7 @@ open class TabsModel: MoleculeModelProtocol { open var selectedIndex: Int = 0 private enum CodingKeys: String, CodingKey { + case id case moleculeName case tabs case backgroundColor @@ -87,6 +90,7 @@ open class TabsModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) _selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) @@ -100,6 +104,7 @@ open class TabsModel: MoleculeModelProtocol { open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 718cfc30..3f7eeba8 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -15,6 +15,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "twoButtonView" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift index 57962c09..089e1160 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift @@ -10,11 +10,14 @@ import Foundation public class TwoLinkViewModel: MoleculeModelProtocol { public static var identifier: String = "twoLinkView" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var rightLink: LinkModel? public var leftLink: LinkModel? private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case rightLink @@ -28,6 +31,7 @@ public class TwoLinkViewModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) rightLink = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .rightLink) leftLink = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .leftLink) @@ -35,6 +39,7 @@ public class TwoLinkViewModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(rightLink, forKey: .rightLink) diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index 7c8bd202..cb237b05 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -11,6 +11,8 @@ import Foundation public class ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" public var moleculeName: String = ActionDetailWithImageModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel public var image: ImageViewModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift index aabd29e7..88a42067 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift @@ -11,6 +11,7 @@ import MVMCore public class CornerLabelsModel: ParentMoleculeModelProtocol { public static var identifier: String = "cornerLabels" + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var topLeftLabel: LabelModel? public var topRightLabel: LabelModel? diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index 19c1f4d6..15d9c78c 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -10,6 +10,7 @@ import Foundation public class HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" public var moleculeName: String = HeadlineBodyLinkToggleModel.identifier + public var id: String = { return UUID().uuidString }() public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index 800c976b..fffd53f7 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -12,6 +12,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" public var moleculeName: String = HeadlineBodyToggleModel.identifier + public var id: String = { return UUID().uuidString }() open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift index ee0c5f78..845296dd 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift @@ -12,6 +12,8 @@ import MVMCore public class LabelToggleModel: MoleculeModelProtocol { public static var identifier: String = "labelToggle" public var moleculeName: String = LabelToggleModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var label: LabelModel public var toggle: ToggleModel @@ -22,6 +24,7 @@ public class LabelToggleModel: MoleculeModelProtocol { } private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case label @@ -30,6 +33,7 @@ public class LabelToggleModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey:.backgroundColor) label = try typeContainer.decode(LabelModel.self, forKey:.label) toggle = try typeContainer.decode(ToggleModel.self, forKey:.toggle) @@ -38,6 +42,7 @@ public class LabelToggleModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(label, forKey: .label) try container.encode(toggle, forKey: .toggle) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift index f0b0bbc0..0c702899 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift @@ -13,9 +13,11 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule // MARK: - Properties //-------------------------------------------------- + public static var identifier: String = "navigationImageButton" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var accessibilityIdentifier: String? - public static var identifier: String = "navigationImageButton" public var image: String public var action: ActionModelProtocol public var accessibilityText: String? @@ -35,6 +37,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case image case action case accessibilityIdentifier @@ -60,6 +63,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(image, forKey: .image) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encode(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift index d72c6ae0..f8152d20 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift @@ -12,8 +12,10 @@ open class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeMo // MARK: - Properties //-------------------------------------------------- - open var backgroundColor: Color? open class var identifier: String { "navigationLabelButton" } + public var id: String = { return UUID().uuidString }() + + open var backgroundColor: Color? open var accessibilityIdentifier: String? open var title: String open var action: ActionModelProtocol @@ -32,6 +34,7 @@ open class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeMo //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case accessibilityIdentifier case title @@ -44,6 +47,7 @@ open class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeMo required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action) @@ -51,6 +55,7 @@ open class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeMo open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encode(title, forKey: .title) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index 64b61480..025e9dd4 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -19,6 +19,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc //-------------------------------------------------- open class var identifier: String { "navigationBar" } + public var id: String = { return UUID().uuidString }() private let defaultHidesSystemBackButton = true @@ -74,6 +75,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case title case hidden @@ -96,6 +98,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString title = try typeContainer.decodeIfPresent(String.self, forKey: .title) if let hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) { self.hidden = hidden @@ -122,6 +125,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(title, forKey: .title) try container.encode(hidden, forKey: .hidden) diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift index 931e7c04..0c499c1b 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift @@ -9,11 +9,15 @@ import Foundation open class ModuleMoleculeModel: MoleculeModelProtocol { - public var backgroundColor: Color? + public static var identifier: String = "moduleMolecule" + public var id: String = { return UUID().uuidString }() + + public var backgroundColor: Color? public var moduleName: String private enum CodingKeys: String, CodingKey { + case id case moduleName } @@ -23,11 +27,13 @@ open class ModuleMoleculeModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString moduleName = try typeContainer.decode(String.self, forKey:.moduleName) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moduleName, forKey: .moduleName) } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index 71324dff..02f55d83 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -10,12 +10,16 @@ import Foundation import MVMCore public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtocol { + public static var identifier: String = "notificationXButton" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var color: Color? public var action: ActionModelProtocol = ActionNoopModel() private enum CodingKeys: String, CodingKey { + case id case moleculeName case color case action @@ -28,6 +32,7 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco public required init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) { self.action = action @@ -36,6 +41,7 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(color, forKey: .color) try container.encodeModel(action, forKey: .action) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 83f5b4bd..56378b13 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -13,6 +13,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule //-------------------------------------------------- public static var identifier: String = "eyebrowHeadlineBodyLink" + public var id: String = { return UUID().uuidString }() public var moleculeName: String = EyebrowHeadlineBodyLinkModel.identifier public var backgroundColor: Color? public var eyebrow: LabelModel? @@ -56,6 +57,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case eyebrow @@ -70,6 +72,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) headline = try typeContainer.decodeMoleculeIfPresent(codingKey: .headline) @@ -84,6 +87,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(eyebrow, forKey: .eyebrow) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 70a08d3b..346d7ce3 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -14,6 +14,8 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyButton" public var moleculeName: String = HeadlineBodyButtonModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var headlineBody: HeadlineBodyModel @@ -45,6 +47,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case headlineBody @@ -58,6 +61,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) button = try typeContainer.decode(ButtonModel.self, forKey: .button) @@ -67,6 +71,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(headlineBody, forKey: .headlineBody) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift index 5d7752fe..452947ba 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift @@ -61,6 +61,7 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case headlineBody diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index 9f16e3ce..edca0398 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -16,6 +16,8 @@ public class HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" public var moleculeName: String = HeadlineBodyLinkModel.identifier + public var id: String = { return UUID().uuidString }() + public var headlineBody: HeadlineBodyModel public var link: LinkModel public var backgroundColor: Color? diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 20df223a..3cb6d28e 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -14,8 +14,10 @@ public static var identifier: String = "headlineBody" public var moleculeName: String = HeadlineBodyModel.identifier + public var id: String = { return UUID().uuidString }() public var headline: LabelModel? public var body: LabelModel? + public var another: LabelToggle? public var style: Style? public var backgroundColor: Color? @@ -23,6 +25,15 @@ [headline, body].compactMap { $0 } } + public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) -> Bool { + return [ + \HeadlineBodyModel.headline, + \HeadlineBodyModel.body, + ].contains { + replaceChildMolecule(on: self, keyPath: $0, replacementMolecule: replacementMolecule) + } + } + //-------------------------------------------------- // MARK: - Enum //-------------------------------------------------- @@ -57,6 +68,7 @@ //----------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case headline case body @@ -66,6 +78,7 @@ required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString headline = try typeContainer.decodeMoleculeIfPresent(codingKey: .headline) body = try typeContainer.decodeMoleculeIfPresent(codingKey: .body) style = try typeContainer.decodeIfPresent(Style.self, forKey: .style) @@ -74,6 +87,7 @@ public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(headline, forKey: .headline) try container.encodeIfPresent(body, forKey: .body) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift index b1b12a54..808a1469 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift @@ -13,6 +13,8 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "stringAndMoleculeModel" + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var string: String public var molecule: MoleculeModelProtocol @@ -33,6 +35,7 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case string @@ -46,6 +49,7 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { public required init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) string = try typeContainer.decode(String.self, forKey: .string) molecule = try typeContainer.decodeModel(codingKey: .molecule) @@ -54,6 +58,7 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(string, forKey: .string) try container.encodeModel(molecule, forKey: .molecule) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift index efdc058c..564834ac 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift @@ -16,6 +16,8 @@ public class ThreeHeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "threeHeadlineBodyLink" public var moleculeName: String = ThreeHeadlineBodyLinkModel.identifier + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var headline1: LabelModel @@ -41,6 +43,7 @@ public class ThreeHeadlineBodyLinkModel: MoleculeModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case headline1 @@ -56,6 +59,7 @@ public class ThreeHeadlineBodyLinkModel: MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) headline1 = try typeContainer.decode(LabelModel.self, forKey: .headline1) headline2 = try typeContainer.decode(LabelModel.self, forKey: .headline2) @@ -67,6 +71,7 @@ public class ThreeHeadlineBodyLinkModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(headline1, forKey: .headline1) try container.encode(headline2, forKey: .headline2) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift index bc3877e5..0521aebd 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift @@ -19,6 +19,8 @@ import UIKit return "carousel" } + public var id: String = { return UUID().uuidString }() + public var backgroundColor: Color? public var molecules: [MoleculeModelProtocol & CarouselItemModelProtocol] public var index: Int = 0 @@ -78,6 +80,7 @@ import UIKit //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case molecules @@ -108,6 +111,7 @@ import UIKit required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString molecules = try typeContainer.decodeModels(codingKey: .molecules) index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0 selectable = try typeContainer.decodeIfPresent(Bool.self, forKey: .selectable) ?? false @@ -144,6 +148,7 @@ import UIKit public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModels(molecules, forKey: .molecules) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index 6845d44b..31adc6ef 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -5,10 +5,10 @@ public enum MolecularError: Swift.Error { case countImbalance(String) } - public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol, MoleculeMaskingProtocol { var moleculeName: String { get } var backgroundColor: Color? { get set } + var id: String { get } } public extension MoleculeModelProtocol { @@ -20,7 +20,6 @@ public extension MoleculeModelProtocol { static var categoryCodingKey: String { "moleculeName" } } - // Helpers made due to swift not able to reconcile which category. extension KeyedDecodingContainer where Key: CodingKey { /// Decodes to a registered molecule based on the identifier @@ -53,8 +52,9 @@ public extension MoleculeModelProtocol { } // Base case. No additional children to traverse. - func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) { - onVisit(depth, self) + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol, inout Bool)->Void) { + var stop = false + onVisit(depth, self, &stop) } } @@ -67,7 +67,7 @@ public extension Array where Element == MoleculeModelProtocol { } } - func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol, inout Bool) -> Void) { forEach { (molecule) in molecule.depthFirstTraverse(options: options, depth: depth, onVisit: onVisit) } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift index 2ec05db4..5f2905aa 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -8,10 +8,11 @@ import Foundation -public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol { +public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol, AnyObject { var children: [MoleculeModelProtocol] { get } + func replaceChildMolecule(with molecule: MoleculeModelProtocol) -> Bool } public extension ParentMoleculeModelProtocol { @@ -35,21 +36,36 @@ public extension ParentMoleculeModelProtocol { return result } - func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol, inout Bool)->Void) { + var stop = false if (options == .parentFirst) { - onVisit(depth, self) + onVisit(depth, self, &stop) + guard !stop else { return } } - children.forEach { (molecule) in - if let additionalParent = molecule as? ParentMoleculeModelProtocol { + for child in children { + if let additionalParent = child as? ParentMoleculeModelProtocol { // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. additionalParent.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit) } else { - molecule.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit) + child.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit) } + guard !stop else { return } } if (options == .childFirst) { - onVisit(depth, self) + onVisit(depth, self, &stop) } // if options == .leafOnly don't call on self. } + + /// Top level test to replace child molecules. Each parent molecule should attempt to replace. + func replaceChildMolecule(with molecule: MoleculeModelProtocol) -> Bool { return false } + + /// Helper function for replacing molecules on a path. + func replaceChildMolecule(on target: P, keyPath: ReferenceWritableKeyPath, replacementMolecule: MoleculeModelProtocol) -> Bool { + if let currentMolecule = target[keyPath: keyPath], currentMolecule.id == replacementMolecule.id, let newHeadline = replacementMolecule as? T { + target[keyPath: keyPath] = newHeadline + return true + } + return false + } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift index 531a48d1..2cd233b0 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift @@ -30,7 +30,7 @@ public extension TemplateModelProtocol { return rootMolecules.reduceDepthFirstTraverse(options: options, depth: depth, initialResult: initialResult, nextPartialResult: nextPartialResult) } - func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol) -> Void) { + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol, inout Bool) -> Void) { return rootMolecules.depthFirstTraverse(options: options, depth: depth, onVisit: onVisit) } } diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift index d10a2d19..a2da7cf4 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift @@ -19,7 +19,7 @@ public protocol MoleculeTreeTraversalProtocol { func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result - func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol, inout Bool)->Void) //func breadthFirstTraverse() } @@ -37,7 +37,7 @@ public extension MoleculeTreeTraversalProtocol { } func printMolecules(options: TreeTraversalOptions = .parentFirst) { - depthFirstTraverse(options: options, depth: 1) { (depth, molecule) in + depthFirstTraverse(options: options, depth: 1) { depth, molecule, stop in print("\(String(repeating: ">>", count: depth)) \"\(molecule.moleculeName)\" [\(molecule)]") } } @@ -50,4 +50,11 @@ public extension MoleculeTreeTraversalProtocol { return accumulator } } + + func replaceMolecule(with replacementMolecule: MoleculeModelProtocol) { + depthFirstTraverse(options: .parentFirst, depth: 0) { depth, molecule, stop in + guard let parentMolecule = molecule as? ParentMoleculeModelProtocol else { return } + stop = parentMolecule.replaceChildMolecule(with: replacementMolecule) + } + } } diff --git a/MVMCoreUI/Containers/Views/ContainerModel.swift b/MVMCoreUI/Containers/Views/ContainerModel.swift index 731e9c95..c99cb5fd 100644 --- a/MVMCoreUI/Containers/Views/ContainerModel.swift +++ b/MVMCoreUI/Containers/Views/ContainerModel.swift @@ -13,6 +13,8 @@ open class ContainerModel: ContainerModelProtocol, Codable { // MARK: - Properties //-------------------------------------------------- + public var id: String = { return UUID().uuidString }() + public var horizontalAlignment: UIStackView.Alignment? public var useHorizontalMargins: Bool? public var leftPadding: CGFloat? @@ -30,6 +32,7 @@ open class ContainerModel: ContainerModelProtocol, Codable { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case horizontalAlignment case useHorizontalMargins case leftPadding @@ -74,6 +77,9 @@ open class ContainerModel: ContainerModelProtocol, Codable { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let verticalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .verticalAlignment) { verticalAlignment = ContainerHelper.getAlignment(for: verticalAlignmentString) } @@ -92,6 +98,7 @@ open class ContainerModel: ContainerModelProtocol, Codable { open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: verticalAlignment), forKey: .verticalAlignment) try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment) try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins) From 94defaa6bce5c265a989512eab1c5cb7333e964b Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 7 Sep 2023 08:34:28 -0400 Subject: [PATCH 14/61] Remove test code. --- .../Molecules/VerticalCombinationViews/HeadlineBodyModel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 3cb6d28e..ecdeed40 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -17,7 +17,6 @@ public var id: String = { return UUID().uuidString }() public var headline: LabelModel? public var body: LabelModel? - public var another: LabelToggle? public var style: Style? public var backgroundColor: Color? From b6c3159b526568d57c3478ee97ca8a898328d424 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 7 Sep 2023 09:20:44 -0400 Subject: [PATCH 15/61] Change ID default initializer, DecodableDefault for implicit decoding models. Add missing id encodes and decodes. --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift | 4 +++- MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift | 2 +- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift | 5 ++++- MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift | 3 ++- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift | 3 ++- MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift | 2 +- .../Atomic/Atoms/Selectors/RadioSwatchesModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift | 5 ++++- .../Views/CarouselIndicator/CarouselIndicatorModel.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/StarModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift | 5 ++++- MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift | 2 +- .../LockUps/LockUpsPlanNamesModel.swift | 2 +- .../LockUps/LockupsPlanSMLXLModel.swift | 2 +- .../DesignedComponents/LockUps/TitleLockupModel.swift | 2 +- .../Molecules/Doughnut/DoughnutChartItemModel.swift | 2 +- .../Atomic/Molecules/Doughnut/DoughnutChartModel.swift | 2 +- .../ImageHeadlineBodyModel.swift | 2 +- .../RadioButtonLabelModel.swift | 2 +- .../HorizontalCombinationViews/TabBarModel.swift | 2 +- .../Molecules/HorizontalCombinationViews/TabsModel.swift | 2 +- .../HorizontalCombinationViews/TwoButtonViewModel.swift | 5 ++++- .../HorizontalCombinationViews/TwoLinkViewModel.swift | 2 +- .../LeftRightViews/ActionDetailWithImageModel.swift | 2 +- .../Molecules/LeftRightViews/CornerLabelsModel.swift | 5 ++++- .../ToggleMolecules/HeadlineBodyLinkToggleModel.swift | 2 +- .../ToggleMolecules/HeadlineBodyToggleModel.swift | 2 +- .../ToggleMolecules/LabelToggleModel.swift | 2 +- .../Buttons/NavigationImageButtonModel.swift | 3 ++- .../Buttons/NavigationLabelButtonModel.swift | 2 +- .../Molecules/NavigationBar/NavigationItemModel.swift | 2 +- .../Molecules/OtherContainers/ModuleMoleculeModel.swift | 2 +- .../TopNotification/NotificationXButtonModel.swift | 2 +- .../EyebrowHeadlineBodyLinkModel.swift | 2 +- .../HeadlineBodyButtonModel.swift | 2 +- .../VerticalCombinationViews/HeadlineBodyLinkModel.swift | 2 +- .../VerticalCombinationViews/HeadlineBodyModel.swift | 2 +- .../StringAndMoleculeStack/StringAndMoleculeModel.swift | 2 +- .../ThreeHeadlineBodyLinkModel.swift | 2 +- MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift | 2 +- MVMCoreUI/Atomic/Organisms/StackModel.swift | 9 +++++++++ .../ModelProtocols/ParentMoleculeModelProtocol.swift | 8 ++++++++ MVMCoreUI/Containers/Views/ContainerModel.swift | 2 +- 63 files changed, 108 insertions(+), 61 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index b3c23e87..08afefde 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -18,7 +18,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat //-------------------------------------------------- //Making static property as class property so that subclasses can override getter function of the property open class var identifier: String { "button" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var accessibilityIdentifier: String? public var accessibilityText: String? diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift index 399219cb..3a5429e1 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift @@ -16,7 +16,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea //-------------------------------------------------- public static var identifier: String = "caretLink" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? public var title: String diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift index df24270d..a61ec150 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift @@ -14,7 +14,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro //-------------------------------------------------- public static var identifier: String = "imageButton" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var image: ImageViewModel? @@ -54,6 +54,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) @@ -79,6 +80,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(image, forKey: .image) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift index 5b290d6e..62ba0422 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift @@ -15,7 +15,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode //-------------------------------------------------- public class var identifier: String { "link" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift index d7148baa..40cb98b7 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagModel.swift @@ -11,7 +11,7 @@ import MVMCore @objcMembers public class TagModel: MoleculeModelProtocol { public static var identifier: String = "tag" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var label: LabelModel public var action: ActionModelProtocol? @@ -41,6 +41,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString label = try typeContainer.decode(LabelModel.self, forKey: .label) action = try typeContainer.decodeModelIfPresent(codingKey: .action) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) @@ -48,6 +49,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(label, forKey: .label) try container.encodeModelIfPresent(action, forKey: .action) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift index 24adcc43..22ce1d9a 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/Tags/TagsModel.swift @@ -11,7 +11,7 @@ import MVMCore @objcMembers public class TagsModel: MoleculeModelProtocol { public static var identifier: String = "tags" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var tags: [TagModel] diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 92ad5c53..6f58cf64 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -16,7 +16,7 @@ import Foundation //-------------------------------------------------- public class var identifier: String { "" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift index 6f30282e..604a8a8d 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift @@ -20,7 +20,7 @@ //-------------------------------------------------- public static var identifier: String = "checkbox" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? public var selected: Bool = false @@ -109,6 +109,8 @@ required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) if let borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) { @@ -182,6 +184,7 @@ public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift index 7580e6e0..cb301e22 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift @@ -14,7 +14,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- public static var identifier: String = "heart" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? @@ -80,6 +80,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(isActive, forKey: .isActive) try container.encode(activeColor, forKey: .activeColor) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index cf592ecb..acec6e83 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -13,7 +13,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioBox" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var text: String public var subText: String? diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index f4f538d6..f1c652f7 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -13,7 +13,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioBoxes" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var boxes: [RadioBoxModel] public var backgroundColor: Color? @@ -78,6 +78,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) @@ -94,6 +95,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(boxes, forKey: .boxes) try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 497a0b1c..99b5cdb7 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -15,7 +15,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- public static var identifier: String = "radioButton" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? @@ -110,6 +110,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(state, forKey: .state) try container.encode(enabled, forKey: .enabled) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift index 1f47abc4..91f13b48 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift @@ -13,7 +13,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioSwatch" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index 9a154167..f424593b 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -13,7 +13,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioSwatches" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index 3973f0bc..429a5769 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -13,7 +13,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- public static var identifier: String = "toggle" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var accessibilityIdentifier: String? public var backgroundColor: Color? diff --git a/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift index 05b54373..7697143e 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ArrowModel.swift @@ -18,7 +18,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol { return "arrow" } public var moleculeName: String? - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var disabledColor: Color = Color(uiColor: .mvmCoolGray3) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift index a5ebc86d..380328d5 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CaretViewModel.swift @@ -15,7 +15,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "caretView" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var strokeColor: Color = Color(uiColor: .mvmBlack) public var strokeColor_inverted: Color = Color(uiColor: .mvmWhite) @@ -53,6 +53,8 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + if let strokeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .strokeColor) { self.strokeColor = strokeColor } @@ -80,6 +82,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(strokeColor, forKey: .strokeColor) try container.encode(strokeColor_inverted, forKey: .strokeColor_inverted) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift index d1d762c1..f5c0adeb 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift @@ -18,7 +18,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro return "" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var moleculeName: String? public var numberOfPages: Int = 0 @@ -68,6 +68,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) @@ -114,6 +115,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(numberOfPages, forKey: .numberOfPages) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index 11252461..f5a65103 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -18,7 +18,7 @@ public enum CheckboxPosition: String, Codable { @objcMembers open class CheckboxLabelModel: MoleculeModelProtocol { open class var identifier: String { "checkboxLabel" } public var moleculeName: String = CheckboxLabelModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var checkboxAlignment: CheckboxPosition? diff --git a/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift index 30864afc..8e533fde 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/DashLineModel.swift @@ -15,7 +15,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "dashLine" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? diff --git a/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift index 4c37a2d8..7f8fa7b6 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift @@ -13,7 +13,7 @@ //-------------------------------------------------- open class var identifier: String { "image" } - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var moleculeName: String = ImageViewModel.identifier diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift index 1574567a..91aef2a9 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift @@ -15,7 +15,7 @@ import UIKit public static var identifier: String = "leftRightLabelView" public var moleculeName: String = LeftRightLabelModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var leftText: LabelModel diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index 4850ac21..3b4c57e9 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -53,7 +53,7 @@ import VDSColorTokens //-------------------------------------------------- public static var identifier: String = "line" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var type: Style = .secondary public var frequency: Frequency? = .allExceptTop diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift index 064d6c38..b74807fb 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift @@ -14,7 +14,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "loadingSpinner" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var strokeColor = Color(uiColor: .mvmBlack) diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift index cadee43d..d664afa6 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift @@ -21,7 +21,7 @@ import Foundation @objcMembers public class MultiProgressBarModel: MoleculeModelProtocol { public static var identifier: String = "multiProgressBar" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var progressList: [SingleProgressBarModel] public var backgroundColor: Color? diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift index fd24858e..439fad3d 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers public class ProgressBarModel: MoleculeModelProtocol { public static var identifier: String = "progressBar" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString @Percent public var percent: CGFloat public var color: Color = Color(uiColor: .mfCerulean()) diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift index 520425f7..7b427cde 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift @@ -13,7 +13,7 @@ open class StarModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "star" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? @Percent public var percent: CGFloat = 0 diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift index a2d04d66..10e6400a 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarsModel.swift @@ -13,7 +13,7 @@ import MVMCore // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "stars" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var starBackgroundColor: Color? @@ -52,6 +52,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString stars = try typeContainer.decode([StarModel].self, forKey: .stars) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) starBackgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .starBackgroundColor) @@ -67,6 +68,7 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(stars, forKey: .stars) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift index a7e09cb2..b41d9eef 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift @@ -15,7 +15,7 @@ open class TileletModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "tilelet" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var color: TileContainer.BackgroundColor public var padding: TileContainer.Padding @@ -31,6 +31,7 @@ open class TileletModel: MoleculeModelProtocol { public var action: ActionModelProtocol? private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case color @@ -48,6 +49,7 @@ open class TileletModel: MoleculeModelProtocol { } required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) + self.id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString self.backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor) self.color = try container.decodeIfPresent(TileContainer.BackgroundColor.self, forKey: .color) ?? TileContainer.BackgroundColor.black self.padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? TileContainer.Padding.padding4X @@ -87,6 +89,7 @@ open class TileletModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(color, forKey: .color) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift index b34cc7aa..27567926 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift @@ -10,7 +10,7 @@ import Foundation open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { public static var identifier = "video" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var video: String public var showControls = false @@ -59,6 +59,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString video = try typeContainer.decode(String.self, forKey:.video) if let showControls = try typeContainer.decodeIfPresent(Bool.self, forKey: .showControls) { self.showControls = showControls @@ -74,6 +75,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(video, forKey: .video) try container.encode(showControls, forKey: .showControls) diff --git a/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift index e953e2ab..28d619a8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WebViewModel.swift @@ -12,7 +12,7 @@ import MVMCore @objcMembers public class WebViewModel: MoleculeModelProtocol { public static var identifier: String = "webview" public var moleculeName: String = WebViewModel.identifier - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var url: URL? diff --git a/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift index 32284277..4fed14cb 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift @@ -19,7 +19,7 @@ public enum GraphStyle: String, Codable { public class WheelModel: MoleculeModelProtocol { public static var identifier: String = "wheel" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var style: GraphStyle = .unlimited { didSet { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift index 5a172208..acbf276d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNamesModel.swift @@ -13,7 +13,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "planNamesLockup" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var headline: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift index ee684645..3e1c1bcc 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXLModel.swift @@ -14,7 +14,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "planLockup" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var planLabel : LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift index 9e55db1b..89d32ca9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift @@ -16,7 +16,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco public static var identifier: String = "titleLockup" public var moleculeName: String = TitleLockupModel.identifier - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var eyebrow: LabelModel? public var title: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift index 187fc8a5..ce2e4fac 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift @@ -16,7 +16,7 @@ import Foundation public static var identifier: String = "doughnutChartItem" public var moleculeName: String = DoughnutChartItemModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var label: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift index 07d7756f..4dbcb4bb 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift @@ -16,7 +16,7 @@ import Foundation public static var identifier: String = "doughnutChart" public var moleculeName: String = DoughnutChartModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var title: LabelModel? diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index 08fe6db3..04aeb0fa 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -15,7 +15,7 @@ public class ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" public var moleculeName: String = ImageHeadlineBodyModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var image: ImageViewModel diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index ea574220..7839bcdc 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -15,7 +15,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioButtonLabel" - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var moleculeName: String = RadioButtonLabelModel.identifier diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index a40d303f..b984a9da 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -11,7 +11,7 @@ import VDSColorTokens open class TabBarModel: MoleculeModelProtocol { public static var identifier: String = "tabBar" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString open var tabs: [TabBarItemModel] diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index e938c119..3671e5e1 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -11,7 +11,7 @@ import VDSColorTokens open class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString open var tabs: [TabItemModel] diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 3f7eeba8..b5d07c4a 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -15,7 +15,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "twoButtonView" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? @@ -29,6 +29,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case id case moleculeName case backgroundColor case primaryButton @@ -50,6 +51,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) //set context value for 'primary' style to be set for the primaryButton in case the @@ -67,6 +69,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(primaryButton, forKey: .primaryButton) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift index 089e1160..c9ae177b 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift @@ -10,7 +10,7 @@ import Foundation public class TwoLinkViewModel: MoleculeModelProtocol { public static var identifier: String = "twoLinkView" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var rightLink: LinkModel? diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index cb237b05..99ef07fd 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -11,7 +11,7 @@ import Foundation public class ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" public var moleculeName: String = ActionDetailWithImageModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift index 88a42067..dc8f2396 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabelsModel.swift @@ -11,7 +11,7 @@ import MVMCore public class CornerLabelsModel: ParentMoleculeModelProtocol { public static var identifier: String = "cornerLabels" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var topLeftLabel: LabelModel? public var topRightLabel: LabelModel? @@ -27,6 +27,7 @@ public class CornerLabelsModel: ParentMoleculeModelProtocol { } private enum CodingKeys: String, CodingKey { + case id case backgroundColor case topLeftLabel case topRightLabel @@ -38,6 +39,7 @@ public class CornerLabelsModel: ParentMoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) molecule = try typeContainer.decodeModelIfPresent(codingKey: .molecule) topLeftLabel = try typeContainer.decodeMoleculeIfPresent(codingKey: .topLeftLabel) @@ -48,6 +50,7 @@ public class CornerLabelsModel: ParentMoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModelIfPresent(molecule, forKey: .molecule) try container.encodeModelIfPresent(topLeftLabel, forKey: .topLeftLabel) diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index 15d9c78c..0783d542 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -10,7 +10,7 @@ import Foundation public class HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" public var moleculeName: String = HeadlineBodyLinkToggleModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index fffd53f7..419097aa 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -12,7 +12,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" public var moleculeName: String = HeadlineBodyToggleModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift index 845296dd..fe8cc16a 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift @@ -12,7 +12,7 @@ import MVMCore public class LabelToggleModel: MoleculeModelProtocol { public static var identifier: String = "labelToggle" public var moleculeName: String = LabelToggleModel.identifier - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var label: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift index 0c702899..ab1c993e 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationImageButtonModel.swift @@ -14,7 +14,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule //-------------------------------------------------- public static var identifier: String = "navigationImageButton" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var accessibilityIdentifier: String? @@ -52,6 +52,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) image = try typeContainer.decode(String.self, forKey: .image) action = try typeContainer.decodeModel(codingKey: .action) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift index f8152d20..33529e77 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/Buttons/NavigationLabelButtonModel.swift @@ -13,7 +13,7 @@ open class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeMo //-------------------------------------------------- open class var identifier: String { "navigationLabelButton" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString open var backgroundColor: Color? open var accessibilityIdentifier: String? diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index 025e9dd4..d39cdeaf 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -19,7 +19,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc //-------------------------------------------------- open class var identifier: String { "navigationBar" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString private let defaultHidesSystemBackButton = true diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift index 0c499c1b..b34922db 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift @@ -11,7 +11,7 @@ import Foundation open class ModuleMoleculeModel: MoleculeModelProtocol { public static var identifier: String = "moduleMolecule" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var moduleName: String diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index 02f55d83..ac1c8905 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -12,7 +12,7 @@ import MVMCore public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public static var identifier: String = "notificationXButton" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var color: Color? diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 56378b13..0d46916e 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -13,7 +13,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule //-------------------------------------------------- public static var identifier: String = "eyebrowHeadlineBodyLink" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var moleculeName: String = EyebrowHeadlineBodyLinkModel.identifier public var backgroundColor: Color? public var eyebrow: LabelModel? diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 346d7ce3..1b713720 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -14,7 +14,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyButton" public var moleculeName: String = HeadlineBodyButtonModel.identifier - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index edca0398..a715f7f7 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -16,7 +16,7 @@ public class HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" public var moleculeName: String = HeadlineBodyLinkModel.identifier - public var id: String = { return UUID().uuidString }() + @DecodableDefault.UUID public var id: String public var headlineBody: HeadlineBodyModel public var link: LinkModel diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index ecdeed40..a3eaf918 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -14,7 +14,7 @@ public static var identifier: String = "headlineBody" public var moleculeName: String = HeadlineBodyModel.identifier - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var headline: LabelModel? public var body: LabelModel? public var style: Style? diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift index 808a1469..8ffc24e4 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift @@ -13,7 +13,7 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "stringAndMoleculeModel" - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var string: String diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift index 564834ac..8f413429 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLinkModel.swift @@ -16,7 +16,7 @@ public class ThreeHeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "threeHeadlineBodyLink" public var moleculeName: String = ThreeHeadlineBodyLinkModel.identifier - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift index 0521aebd..5bfd8d0f 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift @@ -19,7 +19,7 @@ import UIKit return "carousel" } - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var backgroundColor: Color? public var molecules: [MoleculeModelProtocol & CarouselItemModelProtocol] diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index 6310fcea..da6c067e 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -25,6 +25,15 @@ return molecules } + public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) -> Bool { + guard let replacementMolecule = replacementMolecule as? StackItemModelProtocol & MoleculeModelProtocol else { return false } + guard let matchingIndex = molecules.firstIndex(where: { molecule in + molecule.id == replacementMolecule.id + }) else { return false } + molecules[matchingIndex] = replacementMolecule + return true + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift index 5f2905aa..78377a25 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -68,4 +68,12 @@ public extension ParentMoleculeModelProtocol { } return false } + + func replaceChildMolecule(on target: P, keyPath: ReferenceWritableKeyPath, replacementMolecule: MoleculeModelProtocol) -> Bool { + if target[keyPath: keyPath].id == replacementMolecule.id, let newHeadline = replacementMolecule as? T { + target[keyPath: keyPath] = newHeadline + return true + } + return false + } } diff --git a/MVMCoreUI/Containers/Views/ContainerModel.swift b/MVMCoreUI/Containers/Views/ContainerModel.swift index c99cb5fd..b54590dd 100644 --- a/MVMCoreUI/Containers/Views/ContainerModel.swift +++ b/MVMCoreUI/Containers/Views/ContainerModel.swift @@ -13,7 +13,7 @@ open class ContainerModel: ContainerModelProtocol, Codable { // MARK: - Properties //-------------------------------------------------- - public var id: String = { return UUID().uuidString }() + public var id: String = UUID().uuidString public var horizontalAlignment: UIStackView.Alignment? public var useHorizontalMargins: Bool? From 0e300ca5a75d007f19706b5126081482d82b281a Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 7 Sep 2023 12:46:05 -0400 Subject: [PATCH 16/61] DecodableDefault.UUID -> UUIDString --- MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift | 2 +- .../Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift | 2 +- MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift | 2 +- .../HorizontalCombinationViews/ImageHeadlineBodyModel.swift | 2 +- .../HorizontalCombinationViews/RadioButtonLabelModel.swift | 2 +- .../Molecules/LeftRightViews/ActionDetailWithImageModel.swift | 2 +- .../ToggleMolecules/HeadlineBodyLinkToggleModel.swift | 2 +- .../ToggleMolecules/HeadlineBodyToggleModel.swift | 2 +- .../VerticalCombinationViews/HeadlineBodyLinkModel.swift | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index f5a65103..ca0acd79 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -18,7 +18,7 @@ public enum CheckboxPosition: String, Codable { @objcMembers open class CheckboxLabelModel: MoleculeModelProtocol { open class var identifier: String { "checkboxLabel" } public var moleculeName: String = CheckboxLabelModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var checkboxAlignment: CheckboxPosition? diff --git a/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift index 7f8fa7b6..5079fc93 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ImageViewModel.swift @@ -13,7 +13,7 @@ //-------------------------------------------------- open class var identifier: String { "image" } - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var moleculeName: String = ImageViewModel.identifier diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift index 91aef2a9..2f442dc8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelModel.swift @@ -15,7 +15,7 @@ import UIKit public static var identifier: String = "leftRightLabelView" public var moleculeName: String = LeftRightLabelModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var leftText: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift index ce2e4fac..7ac68d0a 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift @@ -16,7 +16,7 @@ import Foundation public static var identifier: String = "doughnutChartItem" public var moleculeName: String = DoughnutChartItemModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var label: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift index 4dbcb4bb..3333ae77 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift @@ -16,7 +16,7 @@ import Foundation public static var identifier: String = "doughnutChart" public var moleculeName: String = DoughnutChartModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var title: LabelModel? diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index 04aeb0fa..84518c8c 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -15,7 +15,7 @@ public class ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" public var moleculeName: String = ImageHeadlineBodyModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var image: ImageViewModel diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 7839bcdc..571848dc 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -15,7 +15,7 @@ import MVMCore //-------------------------------------------------- public static var identifier: String = "radioButtonLabel" - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var moleculeName: String = RadioButtonLabelModel.identifier diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index 99ef07fd..2e7b7500 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -11,7 +11,7 @@ import Foundation public class ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" public var moleculeName: String = ActionDetailWithImageModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index 0783d542..84a03adf 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -10,7 +10,7 @@ import Foundation public class HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" public var moleculeName: String = HeadlineBodyLinkToggleModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index 419097aa..4c86ed76 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -12,7 +12,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" public var moleculeName: String = HeadlineBodyToggleModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index a715f7f7..6c2113bf 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -16,7 +16,7 @@ public class HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" public var moleculeName: String = HeadlineBodyLinkModel.identifier - @DecodableDefault.UUID public var id: String + @DecodableDefault.UUIDString public var id: String public var headlineBody: HeadlineBodyModel public var link: LinkModel From b19d009cffe571773db231e64faecac65f3a60b9 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 7 Sep 2023 13:07:49 -0400 Subject: [PATCH 17/61] unnecessary coding key --- .../HeadlineBodyCaretLinkImageModel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift index 452947ba..5d7752fe 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift @@ -61,7 +61,6 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case id case moleculeName case backgroundColor case headlineBody From 4c2214d7d4fa1774d687fb46d02d7808484354e5 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 10:37:42 -0400 Subject: [PATCH 18/61] VDS Button to atomic beginning/ --- .../Atomic/Atoms/Buttons/ButtonModel.swift | 18 +- .../Atomic/Atoms/Buttons/PillButton.swift | 195 ++++++------------ .../Atomic/Extensions/VDS-Enums+Codable.swift | 2 + MVMCoreUI/Styles/Styler.swift | 36 ---- 4 files changed, 79 insertions(+), 172 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index 08afefde..22ee9b8b 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -8,10 +8,10 @@ import UIKit import VDSColorTokens +import VDS public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?) - open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol { //-------------------------------------------------- // MARK: - Properties @@ -26,13 +26,13 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat public var action: ActionModelProtocol public var enabled: Bool = true public var width: CGFloat? - public var style: Styler.Button.Style? { + public var style: Use? { didSet { guard let style = style else { return } setFacade(by: style) } } - public var size: Styler.Button.Size? = .standard + public var size: ButtonSize = .large public var groupName: String = "" public var inverted: Bool = false @@ -160,14 +160,14 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark) } - public func setFacade(by style: Styler.Button.Style) { - + public func setFacade(by style: VDS.Use) { switch style { case .primary: setPrimaryFacade() - case .secondary: setSecondaryFacade() + @unknown default: + setPrimaryFacade() } } @@ -211,17 +211,17 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat action = try typeContainer.decodeModel(codingKey: .action) ///Style captured from the JSON - if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style){ + if let style = try typeContainer.decodeIfPresent(Use.self, forKey: .style) { self.style = style setFacade(by: style) - } else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Styler.Button.Style { ///Reading the style param from context which is set is molecules, ex: TwoButtonView + } else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Use { ///Reading the style param from context which is set is molecules, ex: TwoButtonView self.style = style setFacade(by: style) } else { ///Default style setFacade(by: .primary) } - if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) { + if let size = try typeContainer.decodeIfPresent(VDS.ButtonSize.self, forKey: .size) { self.size = size } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index e578fa51..56df2044 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -8,35 +8,19 @@ import UIKit import VDSColorTokens +import VDS -open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { +open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - /// Used to size the button. - var size = MVMCoreUIUtility.getWidth() - + var model: MoleculeModelProtocol? var buttonModel: ButtonModel? { get { model as? ButtonModel } } - /// Need to re-style on set. - open override var isEnabled: Bool { - didSet { style(with: buttonModel) } - } - - open var buttonSize: Styler.Button.Size = .standard { - didSet { buttonModel?.size = buttonSize } - } - - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - public var widthConstraint: NSLayoutConstraint? - public var minimumWidthConstraint: NSLayoutConstraint? - //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -44,127 +28,29 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { @objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) { let model = ButtonModel(with: "", action: ActionNoopModel()) model.style = isPrimary ? .primary : .secondary - model.size = istiny ? .tiny : .standard + model.size = istiny ? .small : .large self.init(model: model, nil, nil) } - //-------------------------------------------------- - // MARK: - Computed Properties - //-------------------------------------------------- - - public var enabledTitleColor: UIColor? { - get { titleColor(for: .normal) } - set { setTitleColor(newValue, for: .normal) } - } - - public var disabledTitleColor: UIColor? { - get { titleColor(for: .disabled) } - set { setTitleColor(newValue, for: .disabled) } - } - - public var borderColor: UIColor? { - get { - guard let currentColor = layer.borderColor else { return nil } - return UIColor(cgColor: currentColor) - } - set { layer.borderColor = newValue?.cgColor } - } - - //-------------------------------------------------- - // MARK: - Methods - //-------------------------------------------------- - - /// The primary styling for a button. Should be used for main buttons - public func stylePrimary() { - let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) - style(with: buttonModel) - } - - /// The secondary styling for a button. Should be used for secondary buttons - public func styleSecondary() { - let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) - style(with: buttonModel) - } - - /// Styles the button based on the model style - private func style(with model: ButtonModel?) { - - layer.borderWidth = model?.style == .secondary ? 1 : 0 - - if let titleColor = model?.enabledColors.text { - enabledTitleColor = titleColor - } - - if let disabledTitleColor = model?.disabledColors.text { - self.disabledTitleColor = disabledTitleColor - } - - #if DEBUG - // Useful to detect with isHittable when performing UI testing. - isAccessibilityElement = isEnabled - #endif - - if isEnabled { - if let fillColor = model?.enabledColors.fill { - backgroundColor = fillColor - } - - if let borderColor = model?.enabledColors.border { - self.borderColor = borderColor - } - } else { - if let fillColor = model?.disabledColors.fill { - backgroundColor = fillColor - } - - if let borderColor = model?.disabledColors.border { - self.borderColor = borderColor - } - } - } - - private func getInnerPadding() -> CGFloat { - buttonSize.getHeight() / 2.0 - } - - private func getContentEdgeInsets() -> UIEdgeInsets { - var verticalPadding = 0.0 - var horizontalPadding = 0.0 - switch buttonSize { - case .standard: - verticalPadding = Padding.Three - horizontalPadding = Padding.Five - break - case .small: - verticalPadding = Padding.Two - horizontalPadding = Padding.Four - break - case .tiny: - verticalPadding = Padding.One - horizontalPadding = Padding.Two - break - } - return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding) - } - //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - // The button will get styled in the enable check in super. - super.set(with: model, delegateObject, additionalData) - + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? ButtonModel else { return } + self.model = model + + if let accessibilityIdentifier = model.accessibilityIdentifier { + self.accessibilityIdentifier = accessibilityIdentifier + } setTitle(model.title, for: .normal) if let accessibilityText = model.accessibilityText { accessibilityLabel = accessibilityText } - if let size = model.size { - buttonSize = size - } + isEnabled = model.enabled + size = model.size model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { @@ -173,7 +59,62 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { } FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) + + guard let model = model as? ButtonModelProtocol else { return } + //set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } +} + +open func reset() { + backgroundColor = .clear +} + +// MARK: Overridables +// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead. +open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + model.moleculeName +} + +open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil } + +open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { nil } + +//-------------------------------------------------- +// MARK: - Accessibility +//-------------------------------------------------- + +open override func accessibilityActivate() -> Bool { + guard isEnabled else { return false } + buttonAction?(self) + return buttonAction != nil +} + +} + +// MARK: - MVMCoreViewProtocol +extension Button: MVMCoreViewProtocol { + +open func updateView(_ size: CGFloat) { } + +/// Will be called only once. +open func setupView() { + isAccessibilityElement = true + accessibilityTraits = .button + translatesAutoresizingMaskIntoConstraints = false + insetsLayoutMarginsFromSafeArea = false + titleLabel?.numberOfLines = 0 + titleLabel?.lineBreakMode = .byWordWrapping +} +} + +// MARK: AppleGuidelinesProtocol +extension Button: AppleGuidelinesProtocol { + +override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + Self.acceptablyOutsideBounds(point: point, bounds: bounds) +} +} + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return (model as? ButtonModel)?.size?.getHeight() diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 6c143d9c..b2463ed1 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -16,3 +16,5 @@ extension Icon.Size: Codable {} extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} +extension ButtonSize: Codable {} +extension Use: Codable {} diff --git a/MVMCoreUI/Styles/Styler.swift b/MVMCoreUI/Styles/Styler.swift index 2cbc9a00..2daac86a 100644 --- a/MVMCoreUI/Styles/Styler.swift +++ b/MVMCoreUI/Styles/Styler.swift @@ -159,42 +159,6 @@ open class Styler { } } - public enum Button { - - public enum Style: String, Codable { - case primary - case secondary - } - ///MVA 3.0 - Button sizes are standard(default size), small, Tiny. Tiny button has been depricated as of Rebranding 3.0. - public enum Size: String, Codable { - case standard - case small - case tiny - - func getHeight() -> CGFloat { - switch self { - case .standard: - return 44 - case .small: - return 32 - case .tiny: - return 20 - } - } - - func minimumWidth() -> CGFloat { - switch self { - case .standard: - return 76 - case .small: - return 0 - case .tiny: - return 49 - } - } - } - } - //-------------------------------------------------- // MARK: - Functions //-------------------------------------------------- From 8e35e8036a5bd5a2b5a4bc12c4714d4ecd0a8c41 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 13:55:17 -0400 Subject: [PATCH 19/61] Tiny button to small --- .../Atomic/Atoms/Buttons/ButtonModel.swift | 4 +- .../Atomic/Atoms/Buttons/PillButton.swift | 180 +++++++----------- .../Atomic/Extensions/VDS-Enums+Codable.swift | 21 +- .../ListDeviceComplexButtonMediumModel.swift | 2 +- .../ListDeviceComplexButtonSmallModel.swift | 2 +- ...htVariableButtonAllTextAndLinksModel.swift | 2 +- .../TwoButtonViewModel.swift | 6 +- .../NotificationMoleculeModel.swift | 2 +- .../BGImageHeadlineBodyButtonModel.swift | 2 +- .../HeadlineBodyButtonModel.swift | 2 +- 10 files changed, 105 insertions(+), 118 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index 22ee9b8b..b15f8adb 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -32,7 +32,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat setFacade(by: style) } } - public var size: ButtonSize = .large + public var size: VDS.Button.Size = .large public var groupName: String = "" public var inverted: Bool = false @@ -221,7 +221,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat setFacade(by: .primary) } - if let size = try typeContainer.decodeIfPresent(VDS.ButtonSize.self, forKey: .size) { + if let size = try typeContainer.decodeIfPresent(VDS.Button.Size.self, forKey: .size) { self.size = size } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 56df2044..4a812a57 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -9,8 +9,10 @@ import UIKit import VDSColorTokens import VDS +import MVMCore +import Combine -open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol { +open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol, MVMCoreViewProtocol, MFButtonProtocol { //-------------------------------------------------- // MARK: - Properties @@ -21,10 +23,33 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi get { model as? ButtonModel } } + var onClickCancellable: Cancellable? + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- + required public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: .zero) + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + } + + open override func setup() { + super.setup() + setupView() + } + + //-------------------------------------------------- + // MARK: - Convenience + //-------------------------------------------------- + @objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) { let model = ButtonModel(with: "", action: ActionNoopModel()) model.style = isPrimary ? .primary : .secondary @@ -32,8 +57,20 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi self.init(model: model, nil, nil) } + /// The primary styling for a button. Should be used for main buttons + public func stylePrimary() { + let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) + use = .primary + } + + /// The secondary styling for a button. Should be used for secondary buttons + public func styleSecondary() { + let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) + use = .secondary + } + //-------------------------------------------------- - // MARK: - MVMCoreViewProtocol + // MARK: - MoleculeViewProtocol //-------------------------------------------------- open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { @@ -51,129 +88,60 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi isEnabled = model.enabled size = model.size +// if let backgroundColor = model.backgroundColor { +// self.backgroundColor = backgroundColor.uiColor +// } model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - self?.enableField(model.enabled) + self?.isEnabled = model.enabled }) } FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - guard let model = model as? ButtonModelProtocol else { return } - //set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) - } -} - -open func reset() { - backgroundColor = .clear -} - -// MARK: Overridables -// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead. -open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - model.moleculeName -} - -open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil } - -open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { nil } - -//-------------------------------------------------- -// MARK: - Accessibility -//-------------------------------------------------- - -open override func accessibilityActivate() -> Bool { - guard isEnabled else { return false } - buttonAction?(self) - return buttonAction != nil -} - -} - -// MARK: - MVMCoreViewProtocol -extension Button: MVMCoreViewProtocol { - -open func updateView(_ size: CGFloat) { } - -/// Will be called only once. -open func setupView() { - isAccessibilityElement = true - accessibilityTraits = .button - translatesAutoresizingMaskIntoConstraints = false - insetsLayoutMarginsFromSafeArea = false - titleLabel?.numberOfLines = 0 - titleLabel?.lineBreakMode = .byWordWrapping -} -} - -// MARK: AppleGuidelinesProtocol -extension Button: AppleGuidelinesProtocol { - -override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - Self.acceptablyOutsideBounds(point: point, bounds: bounds) -} -} - - - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return (model as? ButtonModel)?.size?.getHeight() + set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } - open override func updateView(_ size: CGFloat) { - super.updateView(size) - self.size = size - - switch buttonSize { - case .tiny: - titleLabel?.font = Styler.Font.BoldMicro.getFont(false) - case .small: - titleLabel?.font = Styler.Font.BoldBodySmall.getFont(false) - case .standard: - titleLabel?.font = Styler.Font.BoldBodyLarge.getFont(false) - } - - layer.cornerRadius = getInnerPadding() - contentEdgeInsets = getContentEdgeInsets() - - if let contraint = buttonModel?.width { - - if widthConstraint == nil { - widthConstraint = widthAnchor.constraint(equalToConstant: contraint) - } else if widthConstraint?.constant != contraint { - widthConstraint?.constant = contraint - } - widthConstraint?.isActive = true - minimumWidthConstraint?.isActive = false - } else { - - if minimumWidthConstraint == nil { - minimumWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: buttonSize.minimumWidth()) - } else { - minimumWidthConstraint?.constant = buttonSize.minimumWidth() - } - minimumWidthConstraint?.isActive = true - widthConstraint?.isActive = false - } + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + + open override func reset() { + super.reset() + //backgroundColor = .clear } - open override func setupView() { - super.setupView() - - titleLabel?.numberOfLines = 1 - titleLabel?.lineBreakMode = .byTruncatingTail - titleLabel?.textAlignment = .center - contentHorizontalAlignment = .center - stylePrimary() + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return (model as? ButtonModel)?.size.height } + open func updateView(_ size: CGFloat) {} + + open func setupView() {} + //-------------------------------------------------- // MARK: - MVMCoreUIViewConstrainingProtocol //-------------------------------------------------- open func horizontalAlignment() -> UIStackView.Alignment { .center } - public func enableField(_ enable: Bool) { - isEnabled = enable + //-------------------------------------------------- + // MARK: - Action + //-------------------------------------------------- + + open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + onClickCancellable = onClickSubscriber.publisher.sink { [weak self] _ in + guard let self = self, + let actionModel = self.buttonModel?.action else { return } + Task(priority: .userInitiated) { + try await Self.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: self.model) + } + } + } + + open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws { + guard delegateObject?.buttonDelegate?.button?(button, shouldPerformActionWithMap: model.toJSON(), additionalData: additionalData) ?? true else { return } + try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: model, additionalData: MVMCoreUIActionHandler.add(sourceModel: sourceModel, to: additionalData), delegateObject: delegateObject) } } diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index b2463ed1..ea462930 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -16,5 +16,24 @@ extension Icon.Size: Codable {} extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} -extension ButtonSize: Codable {} extension Use: Codable {} +extension VDS.Button.Size: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let string = try container.decode(String.self) + switch string { + case VDS.Button.Size.large.rawValue: + self = .large + case VDS.Button.Size.small.rawValue, "tiny": + self = .small + default: + self = .large + } + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(self) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift index 88f7fe97..54b313e6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift @@ -42,7 +42,7 @@ public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelPro override public func setDefaults() { super.setDefaults() - button.size = .tiny + button.size = .small button.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift index 13be8c03..d06a3845 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift @@ -42,7 +42,7 @@ public class ListDeviceComplexButtonSmallModel: ListItemModel, MoleculeModelProt override public func setDefaults() { super.setDefaults() - button.size = .tiny + button.size = .small button.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift index 21a4b08c..30856e55 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift @@ -32,7 +32,7 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul override public func setDefaults() { super.setDefaults() - self.button.size = .tiny + self.button.size = .small self.button.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index b5d07c4a..a7b4055c 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -7,7 +7,7 @@ // import UIKit - +import VDS public class TwoButtonViewModel: ParentMoleculeModelProtocol { //-------------------------------------------------- @@ -56,13 +56,13 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { //set context value for 'primary' style to be set for the primaryButton in case the //property is not returned in the JSON and once decoded, this value is removed from the context - try decoder.setContext(value: Styler.Button.Style.primary, for: "style") { + try decoder.setContext(value: Use.primary, for: "style") { self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton) } //set context value for 'secondary' style to be set for the primaryButton in case the //property is not returned in the JSON and once decoded, this value is removed from the context - try decoder.setContext(value: Styler.Button.Style.secondary, for: "style") { + try decoder.setContext(value: Use.secondary, for: "style") { self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton) } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index d26bb06c..27ca95a8 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -89,7 +89,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { } } - button?.size = .tiny + button?.size = .small button?.style = .secondary switch style { case .error, .warning: diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift index 99ee1567..4e2d031a 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift @@ -54,7 +54,7 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc image.height = BGImageHeadlineBodyButton.heightConstant } - button?.size = .tiny + button?.size = .small button?.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 1b713720..347277fd 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -38,7 +38,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { /// Defaults to set public func setDefaults() { - button.size = .tiny + button.size = .small button.style = .secondary } From 741bf0501b2f739d8e3bdae9eb5ce6da498480fe Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 14:14:30 -0400 Subject: [PATCH 20/61] Updates to Button --- .../Atomic/Atoms/Buttons/PillButton.swift | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 4a812a57..e8105d3e 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -18,12 +18,12 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi // MARK: - Properties //-------------------------------------------------- - var model: MoleculeModelProtocol? - var buttonModel: ButtonModel? { + open var model: MoleculeModelProtocol? + public var buttonModel: ButtonModel? { get { model as? ButtonModel } } - var onClickCancellable: Cancellable? + internal var onClickCancellable: Cancellable? //-------------------------------------------------- // MARK: - Initializers @@ -58,14 +58,14 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi } /// The primary styling for a button. Should be used for main buttons - public func stylePrimary() { - let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) + open func stylePrimary() { + model = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) use = .primary } /// The secondary styling for a button. Should be used for secondary buttons - public func styleSecondary() { - let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) + open func styleSecondary() { + model = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) use = .secondary } @@ -81,26 +81,25 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi self.accessibilityIdentifier = accessibilityIdentifier } - setTitle(model.title, for: .normal) - if let accessibilityText = model.accessibilityText { - accessibilityLabel = accessibilityText - } - + text = model.title isEnabled = model.enabled size = model.size // if let backgroundColor = model.backgroundColor { // self.backgroundColor = backgroundColor.uiColor // } + if let accessibilityText = model.accessibilityText { + accessibilityLabel = accessibilityText + } + + FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) + + set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { self?.isEnabled = model.enabled }) } - - FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - - set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } //-------------------------------------------------- From c82a0cd4d60d2ab47aaf2049267d16b22662f841 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 14:49:07 -0400 Subject: [PATCH 21/61] Make PillButton VDSMoleculeViewProtocol --- .../Atomic/Atoms/Buttons/PillButton.swift | 89 +++++++------------ .../Atomic/Extensions/VDS-Enums+Codable.swift | 2 +- 2 files changed, 32 insertions(+), 59 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index e8105d3e..2c1c44e7 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -12,40 +12,18 @@ import VDS import MVMCore import Combine -open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol, MVMCoreViewProtocol, MFButtonProtocol { - +open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol, MVMCoreViewProtocol, MFButtonProtocol, VDSMoleculeViewProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - open var model: MoleculeModelProtocol? - public var buttonModel: ButtonModel? { - get { model as? ButtonModel } - } - + public var viewModel: ButtonModel! + public var delegateObject: MVMCoreUIDelegateObject? + public var additionalData: [AnyHashable: Any]? + internal var onClickCancellable: Cancellable? - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - required public init() { - super.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: .zero) - } - - public required init?(coder: NSCoder) { - super.init(coder: coder) - } - - open override func setup() { - super.setup() - setupView() - } - //-------------------------------------------------- // MARK: - Convenience //-------------------------------------------------- @@ -59,45 +37,45 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi /// The primary styling for a button. Should be used for main buttons open func stylePrimary() { - model = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) + viewModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) use = .primary } /// The secondary styling for a button. Should be used for secondary buttons open func styleSecondary() { - model = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) + viewModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) use = .secondary } + open override func setup() { + super.setup() + setupView() + } + //-------------------------------------------------- - // MARK: - MoleculeViewProtocol + // MARK: - VDSMoleculeViewProtocol //-------------------------------------------------- - open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? ButtonModel else { return } - self.model = model - - if let accessibilityIdentifier = model.accessibilityIdentifier { + public func viewModelDidUpdate() { + if let accessibilityIdentifier = viewModel.accessibilityIdentifier { self.accessibilityIdentifier = accessibilityIdentifier } - text = model.title - isEnabled = model.enabled - size = model.size -// if let backgroundColor = model.backgroundColor { -// self.backgroundColor = backgroundColor.uiColor -// } - if let accessibilityText = model.accessibilityText { + text = viewModel.title + isEnabled = viewModel.enabled + size = viewModel.size + use = viewModel.style ?? .primary + if let accessibilityText = viewModel.accessibilityText { accessibilityLabel = accessibilityText } - FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) - set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) + set(with: viewModel.action, delegateObject: delegateObject, additionalData: additionalData) - model.updateUI = { [weak self] in + viewModel.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - self?.isEnabled = model.enabled + self?.viewModelDidUpdate() }) } } @@ -106,11 +84,6 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - open override func reset() { - super.reset() - //backgroundColor = .clear - } - open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return (model as? ButtonModel)?.size.height } @@ -130,13 +103,13 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi //-------------------------------------------------- open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - onClickCancellable = onClickSubscriber.publisher.sink { [weak self] _ in - guard let self = self, - let actionModel = self.buttonModel?.action else { return } - Task(priority: .userInitiated) { - try await Self.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: self.model) + onClickSubscriber = publisher(for: .touchUpInside) + .sink {[weak self] control in + guard let self = self else { return } + Task(priority: .userInitiated) { + try await Self.performButtonAction(with: self.viewModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: self.viewModel) + } } - } } open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws { diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index ea462930..369dbb18 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -22,7 +22,7 @@ extension VDS.Button.Size: Codable { let container = try decoder.singleValueContainer() let string = try container.decode(String.self) switch string { - case VDS.Button.Size.large.rawValue: + case VDS.Button.Size.large.rawValue, "standard": self = .large case VDS.Button.Size.small.rawValue, "tiny": self = .small From a925560ecbb463bad2eabb00a88a540ca7455368 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 16:18:10 -0400 Subject: [PATCH 22/61] RawRepresentableCodable --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ .../Atomic/Atoms/Buttons/PillButton.swift | 9 +++-- .../Atomic/Extensions/VDS-Enums+Codable.swift | 22 ++-------- .../Utility/RawRepresentableCodable.swift | 40 +++++++++++++++++++ 4 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 MVMCoreUI/Utility/RawRepresentableCodable.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index acb13d9a..964bc30c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -289,6 +289,7 @@ AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */; }; AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509629E477C0009DC2AD /* AlertHandler.swift */; }; AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509729E477C0009DC2AD /* AlertController.swift */; }; + AF8118302AB39B0900FAD1BA /* RawRepresentableCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */; }; AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931F29E5CA73001A9663 /* AlertOperation.swift */; }; AFA4932229E5EF2E001A9663 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */; }; AFA4933F29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */; }; @@ -875,6 +876,7 @@ AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAccessibilityTraits+Codable.swift"; sourceTree = ""; }; AF7E509629E477C0009DC2AD /* AlertHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertHandler.swift; sourceTree = ""; }; AF7E509729E477C0009DC2AD /* AlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertController.swift; sourceTree = ""; }; + AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawRepresentableCodable.swift; sourceTree = ""; }; AFA4931F29E5CA73001A9663 /* AlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertOperation.swift; sourceTree = ""; }; AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = ""; }; AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingDelegateProtocol.swift; sourceTree = ""; }; @@ -2152,6 +2154,7 @@ D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */, 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */, 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */, + AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */, ); path = Utility; sourceTree = ""; @@ -2746,6 +2749,7 @@ 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, + AF8118302AB39B0900FAD1BA /* RawRepresentableCodable.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */, 52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 2c1c44e7..d99b78f4 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -68,16 +68,17 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi if let accessibilityText = viewModel.accessibilityText { accessibilityLabel = accessibilityText } - - FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) - + set(with: viewModel.action, delegateObject: delegateObject, additionalData: additionalData) viewModel.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - self?.viewModelDidUpdate() + guard let self = self else { return } + self.isEnabled = self.viewModel.enabled }) } + + FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 369dbb18..ee504e2f 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -17,23 +17,7 @@ extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} extension Use: Codable {} -extension VDS.Button.Size: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let string = try container.decode(String.self) - switch string { - case VDS.Button.Size.large.rawValue, "standard": - self = .large - case VDS.Button.Size.small.rawValue, "tiny": - self = .small - default: - self = .large - } - - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(self) - } +extension VDS.Button.Size: RawRepresentableCodable { + public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } + public static var defaultValue: VDS.Button.Size? { nil } } diff --git a/MVMCoreUI/Utility/RawRepresentableCodable.swift b/MVMCoreUI/Utility/RawRepresentableCodable.swift new file mode 100644 index 00000000..09441add --- /dev/null +++ b/MVMCoreUI/Utility/RawRepresentableCodable.swift @@ -0,0 +1,40 @@ +// +// RawRepresentableCodable.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 9/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol RawRepresentableCodable: RawRepresentable, Codable where RawValue: Hashable & Decodable { + static var mapping: [RawValue: Self] { get } + static var defaultValue: Self? { get } +} + +public enum RawRepresentableCodableError: Swift.Error { + case invalid(value: String) +} + +extension RawRepresentableCodable { + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let rawValue = try container.decode(RawValue.self) + if let found = Self(rawValue: rawValue) { + self = found + } else if let found = Self.mapping[rawValue] { + self = found + } else if let defaultValue = Self.defaultValue { + self = defaultValue + } else { + throw RawRepresentableCodableError.invalid(value: "\(rawValue)") + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(self) + } +} From c2cc637c382f1bed8997c8e465aeebe21dab00c2 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 16:35:44 -0400 Subject: [PATCH 23/61] remove old junk --- .../Atomic/Atoms/Buttons/PillButton.swift | 33 +++---------------- .../TwoButtonView.swift | 7 ++-- .../NotificationMoleculeView.swift | 2 +- .../HeadlineBodyButton.swift | 2 +- 4 files changed, 10 insertions(+), 34 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index d99b78f4..ddffb179 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -24,34 +24,6 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi internal var onClickCancellable: Cancellable? - //-------------------------------------------------- - // MARK: - Convenience - //-------------------------------------------------- - - @objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) { - let model = ButtonModel(with: "", action: ActionNoopModel()) - model.style = isPrimary ? .primary : .secondary - model.size = istiny ? .small : .large - self.init(model: model, nil, nil) - } - - /// The primary styling for a button. Should be used for main buttons - open func stylePrimary() { - viewModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) - use = .primary - } - - /// The secondary styling for a button. Should be used for secondary buttons - open func styleSecondary() { - viewModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) - use = .secondary - } - - open override func setup() { - super.setup() - setupView() - } - //-------------------------------------------------- // MARK: - VDSMoleculeViewProtocol //-------------------------------------------------- @@ -91,6 +63,11 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi open func updateView(_ size: CGFloat) {} + open override func setup() { + super.setup() + setupView() + } + open func setupView() {} //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 5f846730..9a70c12e 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -7,7 +7,7 @@ // import UIKit - +import VDS @objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol { //-------------------------------------------------- @@ -29,9 +29,8 @@ import UIKit //-------------------------------------------------- public func setDefaultAppearance() { - - primaryButton.stylePrimary() - secondaryButton.styleSecondary() + primaryButton.use = .primary + secondaryButton.use = .secondary } open override func updateView(_ size: CGFloat) { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift index c731f6d6..200dea16 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift @@ -15,7 +15,7 @@ import Foundation public let headline = Label(fontStyle: .BoldBodySmall) public let body = Label(fontStyle: .RegularBodySmall) - public let button = PillButton(asPrimaryButton: false, makeTiny: true) + public let button = PillButton() public let closeButton = NotificationXButton() public var labelStack: Stack! public var horizontalStack: Stack! diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift index a40066e2..d7fced36 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift @@ -64,7 +64,7 @@ headlineBody.headlineLabel.font = Styler.Font.BoldTitleMedium.getFont() headlineBody.messageLabel.font = Styler.Font.RegularMicro.getFont() - button.styleSecondary() + button.use = .secondary button.isHidden = false buttonHeadlinePadding = PaddingTwo } From 34d3386d36b240a7ff3a0399c32e1f4a73477d97 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Sep 2023 16:02:15 -0500 Subject: [PATCH 24/61] updated onClick Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift b/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift index 41d68493..32c8015a 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift @@ -50,14 +50,13 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{ //setup action if let action = viewModel.action { //add the subscriber - onClickSubscriber = publisher(for: .touchUpInside) - .sink {[weak self] control in - guard let self else { return } - MVMCoreUIActionHandler.performActionUnstructured(with: action, - sourceModel: self.viewModel, - additionalData: self.additionalData, - delegateObject: self.delegateObject) - } + onClick = { [weak self] control in + guard let self, let viewModel = self.viewModel else { return } + MVMCoreUIActionHandler.performActionUnstructured(with: action, + sourceModel: viewModel, + additionalData: self.additionalData, + delegateObject: self.delegateObject) + } } } From fe580d12e4cca358ef6a0c9e4db19b8e0c961839 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Sep 2023 16:02:26 -0500 Subject: [PATCH 25/61] updated onClick Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index ddffb179..c93a22db 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -12,7 +12,7 @@ import VDS import MVMCore import Combine -open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol, MVMCoreViewProtocol, MFButtonProtocol, VDSMoleculeViewProtocol { +open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties @@ -81,13 +81,12 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi //-------------------------------------------------- open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - onClickSubscriber = publisher(for: .touchUpInside) - .sink {[weak self] control in - guard let self = self else { return } - Task(priority: .userInitiated) { - try await Self.performButtonAction(with: self.viewModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: self.viewModel) - } + onClick = { [weak self] control in + guard let self = self, let viewModel = self.viewModel else { return } + Task(priority: .userInitiated) { + try await Self.performButtonAction(with: viewModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel) } + } } open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws { From 9a191d9516b2d13364b163a636f509e8d67bde86 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Fri, 15 Sep 2023 11:22:48 +0530 Subject: [PATCH 26/61] defect: Passing subNavManager's delegate to NavigationHandler, so that the delegate can update the viewcontroller for the tab updates --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 7bdee349..458c0169 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -273,7 +273,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, // Load controller from the cache needToTrackTabSelect = true Task(priority: .userInitiated) { - await NavigationHandler.shared().replace(viewController: controller, navigationController: subNavigationController, tryToReplace: false, animated: true) + await NavigationHandler.shared().replace(viewController: controller, navigationController:subNavigationController, delegateObject:delegateObject(), tryToReplace: false, animated: true) } } else if let tabsModel = tabs.tabsModel, let action = tabsModel.tabs[indexPath.row].action { From 917a0f84806045af86189ba07be917146cb68a35 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Fri, 15 Sep 2023 12:13:02 -0400 Subject: [PATCH 27/61] PillButton inverted-> surface --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift | 1 + MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index b15f8adb..94a7778b 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -9,6 +9,7 @@ import UIKit import VDSColorTokens import VDS +import MVMCore public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index c93a22db..645c6602 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -37,6 +37,7 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonPr isEnabled = viewModel.enabled size = viewModel.size use = viewModel.style ?? .primary + surface = viewModel.inverted ? .dark : .light if let accessibilityText = viewModel.accessibilityText { accessibilityLabel = accessibilityText } From 68ad6595595294b562bc993be60b26570fc44cde Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Fri, 15 Sep 2023 12:13:44 -0400 Subject: [PATCH 28/61] pill button open --- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index c93a22db..0bfad746 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -18,7 +18,7 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonPr // MARK: - Properties //-------------------------------------------------- - public var viewModel: ButtonModel! + open var viewModel: ButtonModel! public var delegateObject: MVMCoreUIDelegateObject? public var additionalData: [AnyHashable: Any]? @@ -28,7 +28,7 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonPr // MARK: - VDSMoleculeViewProtocol //-------------------------------------------------- - public func viewModelDidUpdate() { + open func viewModelDidUpdate() { if let accessibilityIdentifier = viewModel.accessibilityIdentifier { self.accessibilityIdentifier = accessibilityIdentifier } From 05069e044cb64ed9c850aeb17874a2d05f68092b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 09:55:56 -0500 Subject: [PATCH 29/61] added helper protocol Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 6 +++++- .../Atomic/Extensions/VDS-Enums+Codable.swift | 2 ++ .../Atomic/Protocols/VDS-Interpreters.swift | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 MVMCoreUI/Atomic/Protocols/VDS-Interpreters.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index acb13d9a..a46d3b1a 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 */ @@ -587,6 +587,7 @@ EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; }; EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; }; EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; }; + EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */; }; FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; }; /* End PBXBuildFile section */ @@ -1174,6 +1175,7 @@ EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = ""; }; EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = ""; }; EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = ""; }; + EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VDS-Interpreters.swift"; sourceTree = ""; }; FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -2415,6 +2417,7 @@ 011B58EE23A2AA850085F53C /* ModelProtocols */, 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */, EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */, + EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */, ); path = Protocols; sourceTree = ""; @@ -2972,6 +2975,7 @@ D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */, + EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */, D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 6c143d9c..3f132670 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -16,3 +16,5 @@ extension Icon.Size: Codable {} extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} +extension VDS.Line.Style: Codable {} +extension VDS.Line.Orientation: Codable {} diff --git a/MVMCoreUI/Atomic/Protocols/VDS-Interpreters.swift b/MVMCoreUI/Atomic/Protocols/VDS-Interpreters.swift new file mode 100644 index 00000000..24237527 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/VDS-Interpreters.swift @@ -0,0 +1,18 @@ +// +// VDS-Interpreters.swift +// MVMCoreUI +// +// Created by Matt Bruce on 9/20/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +public protocol Invertable { + var inverted: Bool { get set } +} + +extension Invertable { + public var surface: Surface { return inverted ? .dark : .light } +} From 470bb160d6f928337d4497bb2f96f1034a3b700f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 13:25:33 -0500 Subject: [PATCH 30/61] update for VDS Protocol Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift index 41349f2c..fcbd07d1 100644 --- a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift @@ -28,5 +28,9 @@ extension VDSMoleculeViewProtocol { viewModel = castedModel viewModelDidUpdate() } + + public func update(viewModel: ViewModel){ + set(with: viewModel, delegateObject, additionalData) + } } From 099fce290e81b8c2419529244d3e7ff9e10b911b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 13:26:31 -0500 Subject: [PATCH 31/61] updated LineModel and Line Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 125 +++++++++---------- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 87 +++---------- 2 files changed, 73 insertions(+), 139 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index e36c8d23..c527a362 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -7,116 +7,107 @@ // import UIKit +import VDS - -@objcMembers open class Line: View { +@objcMembers open class Line: VDS.View, VDSMoleculeViewProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - var lineModel: LineModel? { - get { return model as? LineModel } - } - - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - public var heightConstraint: NSLayoutConstraint? - public var widthConstraint: NSLayoutConstraint? - - open func updateLineConstraints(constant: CGFloat) { - if let useVerticalLine = lineModel?.useVerticalLine, useVerticalLine { - heightConstraint?.isActive = false - widthConstraint?.isActive = true - widthConstraint?.constant = constant - } else { - widthConstraint?.isActive = false - heightConstraint?.isActive = true - heightConstraint?.constant = constant + open var line = VDS.Line() + open var viewModel: LineModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + open var orientation: VDS.Line.Orientation = .horizontal { + didSet { + viewModel.orientation = orientation + update(viewModel: viewModel) } } //-------------------------------------------------- // MARK: - Initializer - //-------------------------------------------------- - + //-------------------------------------------------- public convenience init(pinTo view: UIView, edge: UIRectEdge, useMargin: Bool) { self.init(frame: .zero) addLine(to: view, edge: edge, useMargin: useMargin) } - public init() { - super.init(frame: .zero) - model = LineModel(type: .secondary) - setStyle(.secondary) + public required init() { + super.init() + viewModel = LineModel(type: .primary) } public override init(frame: CGRect) { super.init(frame: frame) - model = LineModel(type: .secondary) - setStyle(.secondary) + viewModel = LineModel(type: .primary) } public required init?(coder: NSCoder) { super.init(coder: coder) - model = LineModel(type: .secondary) - setStyle(.secondary) + viewModel = LineModel(type: .primary) } - public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.init(model: model, delegateObject, additionalData) + //-------------------------------------------------- + // MARK: - Overrides + //-------------------------------------------------- + open override func setup() { + super.setup() + addSubview(line) + line.pinToSuperView() } - + //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- - - open func setStyle(_ style: LineModel.Style) { - lineModel?.type = style - backgroundColor = lineModel?.backgroundColor?.uiColor - updateLineConstraints(constant: lineModel?.thickness ?? 1) - } - open func shouldBeVisible() -> Bool { - guard let type = lineModel?.type else { return false } + guard let type = viewModel?.type else { return false } return type != .none } - //-------------------------------------------------- - // MARK: - MoleculeViewProtocol - //-------------------------------------------------- + open func setStyle(_ style: LineModel.Style) { + viewModel.type = style + update(viewModel: viewModel) + } open func addLine(to view: UIView, edge: UIRectEdge, useMargin: Bool) { view.addSubview(self) - NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: self, useMargins: useMargin, pinTop: edge != .bottom, pinBottom: edge != .top, pinLeft: edge != .right, pinRight: edge != .left).values)) + NSLayoutConstraint.activate( + Array( + NSLayoutConstraint.pinView(toSuperview: self, + useMargins: useMargin, + pinTop: edge != .bottom, + pinBottom: edge != .top, + pinLeft: edge != .right, + pinRight: edge != .left).values + ) + ) } - open override func setupView() { - super.setupView() - heightConstraint = heightAnchor.constraint(equalToConstant: 1) - heightConstraint?.isActive = true - widthConstraint = widthAnchor.constraint(equalToConstant: 1) - widthConstraint?.isActive = false + //-------------------------------------------------- + // MARK: - VDSMoleculeViewProtocol + //-------------------------------------------------- + open func viewModelDidUpdate() { + surface = viewModel.surface + line.style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary + line.orientation = viewModel.orientation } - - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - if let lineModel = model as? LineModel { - setStyle(lineModel.type) - } + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + public func updateView(_ size: CGFloat) { + setNeedsDisplay() } - - open override func reset() { - setStyle(.secondary) - } - - public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return (model as? LineModel)?.thickness ?? 1 + + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 1 } } +//-------------------------------------------------- +// MARK: - MVMCoreUIViewConstrainingProtocol +//-------------------------------------------------- extension Line: MVMCoreUIViewConstrainingProtocol { open func needsToBeConstrained() -> Bool { diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index 3b4c57e9..ecb39df0 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -8,8 +8,9 @@ import UIKit import VDSColorTokens +import VDS -@objcMembers public class LineModel: MoleculeModelProtocol { +@objcMembers public class LineModel: MoleculeModelProtocol, Invertable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- @@ -28,23 +29,9 @@ import VDSColorTokens case between } - /** - The style of the line: - - secondary (1 height, silver) - - primary (1 height, black) - - standard (1 height, silver) - deprecated - - thin (1 height, black) - deprecated - - medium (2 height, black) - - heavy (4 height, black) - - none (hidden) - */ public enum Style: String, Codable { case secondary case primary - case standard - case thin - case medium - case heavy case none } @@ -54,53 +41,14 @@ import VDSColorTokens public static var identifier: String = "line" public var id: String = UUID().uuidString - - public var type: Style = .secondary + public var backgroundColor: Color? + + public var type: Style = .primary public var frequency: Frequency? = .allExceptTop - - //TODO: use color insted of backgroundColor. Needs server changes - // public var color: Color? - private var _backgroundColor: Color? - public var backgroundColor: Color? { - get { - if let backgroundColor = _backgroundColor { return backgroundColor } - if inverted { - if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray20) } - return Color(uiColor: VDSColor.elementsPrimaryOndark) - } - if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray85) } - return Color(uiColor: VDSColor.elementsPrimaryOnlight) - } - set { - _backgroundColor = newValue - } - } - - private var _thickness: CGFloat? - public var thickness: CGFloat { - get { - if let thickness = _thickness { return thickness } - switch type { - case .heavy: - return 4 - case .medium: - return 2 - case .none: - return 0 - default: - return 1 - } - } - set { - _thickness = newValue - } - } - + public var inverted: Bool = false - // Use this to show vertical line - // Default is false - public var useVerticalLine: Bool? + public var orientation: VDS.Line.Orientation = .horizontal //-------------------------------------------------- // MARK: - Initializer @@ -108,13 +56,10 @@ import VDSColorTokens public init(type: Style) { self.type = type - self.useVerticalLine = false } public init(verticalLineOf type: Style, backgroundColor: Color? = nil) { self.type = type - self.backgroundColor = backgroundColor - self.useVerticalLine = true } //-------------------------------------------------- @@ -125,13 +70,10 @@ import VDSColorTokens case id case moleculeName case type - case backgroundColor - case backgroundColor_inverted - case color case frequency case inverted case useVerticalLine - case thickness + case orientation } //-------------------------------------------------- @@ -155,9 +97,12 @@ import VDSColorTokens self.inverted = inverted } - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) - _thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) + /// adding code to look for the old useVerticalLine or the new orientation + if let useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) { + orientation = useVerticalLine ? .vertical : .horizontal + }else if let orientation = try typeContainer.decodeIfPresent(VDS.Line.Orientation.self, forKey: .orientation) { + self.orientation = orientation + } } public func encode(to encoder: Encoder) throws { @@ -167,8 +112,6 @@ import VDSColorTokens try container.encode(type, forKey: .type) try container.encode(inverted, forKey: .inverted) try container.encodeIfPresent(frequency, forKey: .frequency) - try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(useVerticalLine, forKey: .useVerticalLine) - try container.encodeIfPresent(_thickness, forKey: .thickness) + try container.encodeIfPresent(orientation == .vertical, forKey: .useVerticalLine) } } From 2e03cec5be3ed5ed51c991c56823ed7f7cb0969d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 13:27:51 -0500 Subject: [PATCH 32/61] updated ListProgressBarThin Signed-off-by: Matt Bruce --- .../Molecules/DesignedComponents/List/ListProgressBarThin.swift | 2 +- .../DesignedComponents/List/ListProgressBarThinModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift index 9b85dc4f..d9875068 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -102,7 +102,7 @@ leftHeadline.styleB1(true) leftBody.styleB2(true) rightLabel.styleB2(true) - rightBar.setStyle(.medium) + rightBar.setStyle(.primary) } //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift index 52c175df..d6787f52 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift @@ -39,7 +39,7 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol { override public func setDefaults() { super.setDefaults() - rightBar.type = .medium + rightBar.type = .primary if rightBar.backgroundColor == nil { rightBar.backgroundColor = Color(uiColor: .gray) From 81a5d5099fe7528dbe7974af702300d9c9bf02ba Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 13:28:16 -0500 Subject: [PATCH 33/61] updated ListRightVariableTotalData Signed-off-by: Matt Bruce --- .../List/RightVariable/ListRightVariableTotalData.swift | 4 ++-- .../List/RightVariable/ListRightVariableTotalDataModel.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift index a749041a..9845ea16 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift @@ -44,7 +44,7 @@ override open func setupView() { super.setupView() - bar.setStyle(.heavy) + bar.setStyle(.primary) bar.widthAnchor.constraint(equalToConstant: 20).isActive = true rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) addMolecule(stack) @@ -74,7 +74,7 @@ super.reset() leftLabel.setFontStyle(.BoldBodySmall) rightLabel.setFontStyle(.RegularBodySmall) - bar.setStyle(.heavy) + bar.setStyle(.primary) } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift index cebaeb34..53ede6e5 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift @@ -24,7 +24,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc override public func setDefaults() { super.setDefaults() rightLabel.hero = 0 - bar.type = .heavy + bar.type = .primary if bar.backgroundColor == nil { bar.backgroundColor = Color(uiColor: .mvmBlue) From aed46d592c86a8860f6d24cf716e2d0d9eaf1378 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 13:28:38 -0500 Subject: [PATCH 34/61] updated tabs and tabs model Signed-off-by: Matt Bruce --- .../Atomic/Molecules/HorizontalCombinationViews/TabBar.swift | 2 +- .../Atomic/Molecules/HorizontalCombinationViews/Tabs.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift index e49006fa..bbe17e05 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift @@ -50,7 +50,7 @@ import VDSColorTokens setItems(tabs, animated: false) selectedItem = tabs[model.selectedTab] - guard let lineModel = line.lineModel else { return } + guard let lineModel = line.viewModel else { return } lineModel.inverted = model.style == .dark line.set(with: lineModel, delegateObject, additionalData) } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index e5682e71..e6689f3d 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -174,7 +174,7 @@ import VDSColorTokens self.additionalData = additionalData selectedIndex = tabsModel?.selectedIndex ?? 0 selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor - let lineModel = bottomLine.lineModel ?? LineModel(type: .secondary) + let lineModel = bottomLine.viewModel ?? LineModel(type: .secondary) lineModel.inverted = tabsModel?.style == .dark bottomLine.set(with: lineModel, delegateObject, additionalData) reloadData() From 5d9944b5eab6482d78026235a675a31e81738255 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 14:07:36 -0500 Subject: [PATCH 35/61] subclass line directly Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index c527a362..e3195aa2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -9,22 +9,15 @@ import UIKit import VDS -@objcMembers open class Line: VDS.View, VDSMoleculeViewProtocol { +@objcMembers open class Line: VDS.Line, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - open var line = VDS.Line() open var viewModel: LineModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - open var orientation: VDS.Line.Orientation = .horizontal { - didSet { - viewModel.orientation = orientation - update(viewModel: viewModel) - } - } - + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -47,15 +40,6 @@ import VDS super.init(coder: coder) viewModel = LineModel(type: .primary) } - - //-------------------------------------------------- - // MARK: - Overrides - //-------------------------------------------------- - open override func setup() { - super.setup() - addSubview(line) - line.pinToSuperView() - } //-------------------------------------------------- // MARK: - Methods @@ -89,8 +73,8 @@ import VDS //-------------------------------------------------- open func viewModelDidUpdate() { surface = viewModel.surface - line.style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary - line.orientation = viewModel.orientation + style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary + orientation = viewModel.orientation } //-------------------------------------------------- From 62afe434f9a37c36fb127550b39a3862853f46df Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 14:07:49 -0500 Subject: [PATCH 36/61] updated to use line properties Signed-off-by: Matt Bruce --- .../UINavigationController+Extension.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index 625f0a25..d45ca632 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -81,9 +81,9 @@ public extension UINavigationController { /// Returns a ShadowImage based on the line property of NavigationItemModelProtocol func getNavigationBarShadowImage(for navigationItemModel: NavigationItemModelProtocol) -> UIImage? { - guard let thickness = navigationItemModel.line?.thickness, - let backgroundColor = navigationItemModel.line?.backgroundColor else { return nil } - return backgroundColor.uiColor.image(CGSize(width: thickness, height: thickness)) + guard let model = navigationItemModel.line else { return nil } + let line = Line(model: model, nil, nil) + return line.lineColor.image(CGSize(width: line.lineWidth, height: line.lineWidth)) } /// Convenience function for setting the navigation bar ui From 10370f3ac6840a89f97b158aecfe4b6691765519 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 14:35:46 -0500 Subject: [PATCH 37/61] Revert "subclass line directly" This reverts commit 5d9944b5eab6482d78026235a675a31e81738255. --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index e3195aa2..c527a362 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -9,15 +9,22 @@ import UIKit import VDS -@objcMembers open class Line: VDS.Line, VDSMoleculeViewProtocol { +@objcMembers open class Line: VDS.View, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- + open var line = VDS.Line() open var viewModel: LineModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - + open var orientation: VDS.Line.Orientation = .horizontal { + didSet { + viewModel.orientation = orientation + update(viewModel: viewModel) + } + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -40,6 +47,15 @@ import VDS super.init(coder: coder) viewModel = LineModel(type: .primary) } + + //-------------------------------------------------- + // MARK: - Overrides + //-------------------------------------------------- + open override func setup() { + super.setup() + addSubview(line) + line.pinToSuperView() + } //-------------------------------------------------- // MARK: - Methods @@ -73,8 +89,8 @@ import VDS //-------------------------------------------------- open func viewModelDidUpdate() { surface = viewModel.surface - style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary - orientation = viewModel.orientation + line.style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary + line.orientation = viewModel.orientation } //-------------------------------------------------- From b2b33db8a986517997760a7007fef6ce24a83179 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 14:40:56 -0500 Subject: [PATCH 38/61] Revert "Revert "subclass line directly"" This reverts commit 10370f3ac6840a89f97b158aecfe4b6691765519. --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index c527a362..e3195aa2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -9,22 +9,15 @@ import UIKit import VDS -@objcMembers open class Line: VDS.View, VDSMoleculeViewProtocol { +@objcMembers open class Line: VDS.Line, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - open var line = VDS.Line() open var viewModel: LineModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - open var orientation: VDS.Line.Orientation = .horizontal { - didSet { - viewModel.orientation = orientation - update(viewModel: viewModel) - } - } - + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -47,15 +40,6 @@ import VDS super.init(coder: coder) viewModel = LineModel(type: .primary) } - - //-------------------------------------------------- - // MARK: - Overrides - //-------------------------------------------------- - open override func setup() { - super.setup() - addSubview(line) - line.pinToSuperView() - } //-------------------------------------------------- // MARK: - Methods @@ -89,8 +73,8 @@ import VDS //-------------------------------------------------- open func viewModelDidUpdate() { surface = viewModel.surface - line.style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary - line.orientation = viewModel.orientation + style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary + orientation = viewModel.orientation } //-------------------------------------------------- From 6da75b26bd94176658092e2e6baca48486ec3cd2 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 14:51:12 -0500 Subject: [PATCH 39/61] don't call super to draw if model is set to none Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index e3195aa2..c3ce3d7f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -68,6 +68,11 @@ import VDS ) } + open override func draw(_ rect: CGRect) { + guard viewModel.type != .none else { return } + super.draw(rect) + } + //-------------------------------------------------- // MARK: - VDSMoleculeViewProtocol //-------------------------------------------------- From 2a34fa433dbeb29e0dbbfa1cd63a56bd7f981556 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 20 Sep 2023 14:51:21 -0500 Subject: [PATCH 40/61] updated for line Signed-off-by: Matt Bruce --- .../Headers/H2/HeadersH2PricingTwoRows.swift | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift index 1baf057c..f38793eb 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift @@ -42,6 +42,13 @@ import Foundation return Stack.createStack(with: [headline, horizontalStack], spacing: 8) }() + + //------------------------------------------------------- + // MARK: - Constraints + //------------------------------------------------------- + public var verticalLine1HeightConstraint: NSLayoutConstraint? + public var verticalLine2HeightConstraint: NSLayoutConstraint? + //------------------------------------------------------- // MARK: - Lifecycle //------------------------------------------------------- @@ -51,11 +58,10 @@ import Foundation body.lineBreakMode = .byTruncatingTail body2.lineBreakMode = .byTruncatingTail body3.lineBreakMode = .byTruncatingTail - - verticalLine1.widthConstraint?.isActive = true - verticalLine1.backgroundColor = .mvmBlack - verticalLine2.widthConstraint?.isActive = true - verticalLine2.backgroundColor = .mvmBlack + + // setup lines + verticalLine1.orientation = .vertical + verticalLine2.orientation = .vertical addMolecule(stack) stack.restack() @@ -80,13 +86,13 @@ import Foundation } open func setLineHeight() { - verticalLine1.heightConstraint?.isActive = false - verticalLine1.heightConstraint = verticalLine1.heightAnchor.constraint(equalTo: body2.heightAnchor, multiplier: 1) - verticalLine1.heightConstraint?.isActive = true + verticalLine1HeightConstraint?.isActive = false + verticalLine1HeightConstraint = verticalLine1.heightAnchor.constraint(equalTo: body2.heightAnchor, multiplier: 1) + verticalLine1HeightConstraint?.isActive = true - verticalLine2.heightConstraint?.isActive = false - verticalLine2.heightConstraint = verticalLine2.heightAnchor.constraint(equalTo: body3.heightAnchor, multiplier: 1) - verticalLine2.heightConstraint?.isActive = true + verticalLine2HeightConstraint?.isActive = false + verticalLine2HeightConstraint = verticalLine2.heightAnchor.constraint(equalTo: body3.heightAnchor, multiplier: 1) + verticalLine2HeightConstraint?.isActive = true } //---------------------------------------------------- From 89f65ebe3dbe6785968e2d46cd78e7ce269c106a Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 21 Sep 2023 14:41:35 -0500 Subject: [PATCH 41/61] added codable Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 6c143d9c..b3500df1 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -16,3 +16,4 @@ extension Icon.Size: Codable {} extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} +extension TextLink.Size: Codable {} From 0f85c96201024930bb272ee85c0e786b318ddefb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 21 Sep 2023 14:41:42 -0500 Subject: [PATCH 42/61] updated link Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Buttons/Link/Link.swift | 92 +++++++------------ .../Atomic/Atoms/Buttons/Link/LinkModel.swift | 69 ++------------ 2 files changed, 38 insertions(+), 123 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index 4f4a8b34..8c1e5f4a 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -8,83 +8,53 @@ import UIKit import VDSColorTokens +import VDS + +@objcMembers open class Link: VDS.TextLink, VDSMoleculeViewProtocol { -@objcMembers open class Link: Button { //-------------------------------------------------- - // MARK: - Draw + // MARK: - Public Properties //-------------------------------------------------- + open var viewModel: LinkModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? - open override func draw(_ rect: CGRect) { + //-------------------------------------------------- + // MARK: - Public Functions + //-------------------------------------------------- + open func viewModelDidUpdate() { + isEnabled = viewModel.enabled + size = viewModel.size + text = viewModel.title - guard let textRect = titleLabel?.frame, - let context = UIGraphicsGetCurrentContext() - else { return } - - // Set line to the same color as the text - if let color = titleLabel?.textColor?.cgColor { - context.setStrokeColor(color) + onClick = { [weak self] control in + guard let self else { return } + MVMCoreUIActionHandler.performActionUnstructured(with: self.viewModel.action, + sourceModel: self.viewModel, + additionalData: self.additionalData, + delegateObject: self.delegateObject) } - - // x should be according to the text, not the button - let x = textRect.origin.x - - // Line is 0 point below the text - let y = textRect.origin.y + textRect.size.height - - context.move(to: CGPoint(x: x, y: y)) - context.addLine(to: CGPoint(x: x + textRect.size.width, y: y)) - context.strokePath() } - - open override var intrinsicContentSize: CGSize { - guard let size = titleLabel?.intrinsicContentSize else { return super.intrinsicContentSize } - return CGSize(width: size.width, height: size.height + 1) - } - + //-------------------------------------------------- - // MARK: - MoleculeViewProtocol + // MARK: - Overrides //-------------------------------------------------- - - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) + open override func updateAccessibility() { + super.updateAccessibility() - guard let model = model as? LinkModel else { return } - - setTitle(model.title, for: .normal) - if let accessibilityText = model.accessibilityText { + if let viewModel, let accessibilityText = viewModel.accessibilityText { accessibilityLabel = accessibilityText } - setTitleColor((model.inverted ? model.enabledColor_inverted : model.enabledColor).uiColor, for: .normal) - setTitleColor((model.inverted ? model.disabledColor_inverted : model.disabledColor).uiColor, for: .disabled) - setTitleColor((model.inverted ? model.activeColor_inverted : model.activeColor).uiColor, for: .highlighted) - isEnabled = model.enabled - titleLabel?.font = model.getFont(model.size) - set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 } -} + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 } -// MARK: - MVMCoreViewProtocol -extension Link { + open func updateView(_ size: CGFloat) { } - open override func updateView(_ size: CGFloat) { - super.updateView(size) - } - - open override func setupView() { - super.setupView() - backgroundColor = .clear - contentMode = .redraw - setTitleColor(VDSColor.elementsPrimaryOnlight, for: .normal) - setTitleColor(VDSColor.interactiveDisabledOnlight, for: .disabled) - setTitleColor(VDSColor.interactiveActiveOnlight, for: .highlighted) - titleLabel?.numberOfLines = 1 - titleLabel?.lineBreakMode = .byTruncatingTail - titleLabel?.textAlignment = .left - contentHorizontalAlignment = .left - contentVerticalAlignment = .top - } + open func setupView() {} } // MARK: - MVMCoreUIViewConstrainingProtocol diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift index 62ba0422..7e9a4640 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDS open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- @@ -23,15 +23,9 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode public var accessibilityText: String? public var action: ActionModelProtocol public var enabled = true - public var enabledColor = Color(uiColor: VDSColor.elementsPrimaryOnlight) - public var enabledColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark) - public var disabledColor = Color(uiColor: VDSColor.interactiveDisabledOnlight) - public var disabledColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark) - public var activeColor = Color(uiColor: VDSColor.interactiveActiveOnlight) - public var activeColor_inverted = Color(uiColor: VDSColor.interactiveActiveOndark) public var inverted = false - public var size:linkFontSize = linkFontSize.small + public var size: TextLink.Size = .small public var shouldMaskRecordedView: Bool? = false @@ -57,34 +51,10 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode case title case action case enabled - case enabledColor - case enabledColor_inverted - case disabledColor - case disabledColor_inverted - case activeColor - case activeColor_inverted case inverted case size case shouldMaskRecordedView } - - public enum linkFontSize: String, Codable { - case small - case large - } - - //-------------------------------------------------- - // MARK: - Method - //-------------------------------------------------- - - func getFont(_ type: linkFontSize) -> UIFont { - switch type { - case .small: - return MFStyler.fontRegularBodySmall() - case .large: - return MFStyler.fontRegularBodyLarge() - } - } //-------------------------------------------------- // MARK: - Codec @@ -108,30 +78,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode self.inverted = inverted } - if let enabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) { - self.enabledColor = enabledColor - } - - if let enabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor_inverted) { - self.enabledColor_inverted = enabledColor_inverted - } - - if let disabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) { - self.disabledColor = disabledColor - } - - if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) { - self.disabledColor_inverted = disabledColor_inverted - } - - if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) { - self.activeColor = activeColor - } - - if let activeColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor_inverted) { - self.activeColor_inverted = activeColor_inverted - } - if let size = try typeContainer.decodeIfPresent(linkFontSize.self, forKey: .size) { + if let size = try typeContainer.decodeIfPresent(TextLink.Size.self, forKey: .size) { self.size = size } @@ -148,13 +95,11 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode try container.encodeModel(action, forKey: .action) try container.encode(inverted, forKey: .inverted) try container.encode(enabled, forKey: .enabled) - try container.encode(enabledColor, forKey: .enabledColor) - try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted) - try container.encode(disabledColor, forKey: .disabledColor) - try container.encode(disabledColor_inverted, forKey: .disabledColor_inverted) - try container.encode(activeColor, forKey: .activeColor) - try container.encode(activeColor_inverted, forKey: .activeColor_inverted) try container.encodeIfPresent(size, forKey: .size) try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView) } } + +extension LinkModel { + public var surface: Surface { inverted ? .dark : .light } +} From f4221c0215a9cdbfa05633069a0a13c031183af7 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 21 Sep 2023 14:41:50 -0500 Subject: [PATCH 43/61] updated external link Signed-off-by: Matt Bruce --- .../Atoms/Buttons/Link/ExternalLink.swift | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift index e051cf32..9e5cd108 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift @@ -11,29 +11,24 @@ import UIKit open class ExternalLink: Link { //-------------------------------------------------- - // MARK: - Properties + // MARK: - Public Properties //-------------------------------------------------- - - public var exportImageView: UIImageView? - + open var exportImageView: UIImageView? + open var exportImageHeight: NSLayoutConstraint? + open var exportImageWidth: NSLayoutConstraint? + //-------------------------------------------------- - // MARK: - MoleculeViewProtocol + // MARK: - Overrides //-------------------------------------------------- - - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - - guard let model = model as? ExternalLinkModel else { return } - - exportImageView?.tintColor = titleColor(for: model.enabled ? .normal : .disabled) + open override func viewModelDidUpdate() { + super.viewModelDidUpdate() + exportImageView?.tintColor = textColor + exportImageWidth?.constant = textStyle.lineHeight + exportImageHeight?.constant = textStyle.lineHeight } - - //-------------------------------------------------- - // MARK: - MVMCoreViewProtocol - //-------------------------------------------------- - - open override func setupView() { - super.setupView() + + open override func setup() { + super.setup() let image = MVMCoreUIUtility.imageNamed("externalLink") exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate)) @@ -46,10 +41,10 @@ open class ExternalLink: Link { addSubview(exportIcon) trailingAnchor.constraint(greaterThanOrEqualTo: exportIcon.trailingAnchor).isActive = true - if let titleLabel = titleLabel { - let dimension = titleLabel.font.pointSize - exportIcon.heightAnchor.constraint(equalToConstant: dimension).isActive = true - exportIcon.widthAnchor.constraint(equalToConstant: dimension).isActive = true + exportImageHeight = exportIcon.heightAnchor.constraint(equalToConstant: textStyle.pointSize).activate() + exportImageWidth = exportIcon.widthAnchor.constraint(equalToConstant: textStyle.pointSize).activate() + + if let titleLabel { exportIcon.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4).isActive = true exportIcon.bottomAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor, constant: 3).isActive = true } From dff7cc6d3120905e78d5e0886bf276fc64afb919 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 21 Sep 2023 14:46:28 -0500 Subject: [PATCH 44/61] updated accessibility Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index 8c1e5f4a..86776016 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -26,6 +26,7 @@ import VDS isEnabled = viewModel.enabled size = viewModel.size text = viewModel.title + surface = viewModel.surface onClick = { [weak self] control in guard let self else { return } @@ -42,8 +43,14 @@ import VDS open override func updateAccessibility() { super.updateAccessibility() - if let viewModel, let accessibilityText = viewModel.accessibilityText { - accessibilityLabel = accessibilityText + if let viewModel { + if let accessibilityText = viewModel.accessibilityText { + self.accessibilityLabel = accessibilityText + } + + if let accessibilityIdentifier = viewModel.accessibilityIdentifier { + self.accessibilityIdentifier = accessibilityIdentifier + } } } From 1e12517c555078320f257b2f16af4066083760f3 Mon Sep 17 00:00:00 2001 From: Sourabh Bhardwaj Date: Mon, 25 Sep 2023 19:38:01 +0530 Subject: [PATCH 45/61] Fixed headline body component's accessbility label issue --- .../List/OneColumn/ListOneColumnFullWidthTextBodyText.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift index 7a17dd1b..f9cfcc95 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift @@ -55,11 +55,11 @@ import Foundation isAccessibilityElement = true var message = "" - if let headlineLabel = headlineBody.headlineLabel.text { + if let headlineLabel = headlineBody.headlineLabel.accessibilityLabel ?? headlineBody.headlineLabel.text { message += headlineLabel + ", " } - if let messageLabel = headlineBody.messageLabel.text { + if let messageLabel = headlineBody.messageLabel.accessibilityLabel ?? headlineBody.messageLabel.text { message += messageLabel } From ab50921e88fbb95d0a0f1f57d71b0e7d4e444612 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 27 Sep 2023 15:34:49 -0500 Subject: [PATCH 46/61] added color extension for isDark Signed-off-by: Matt Bruce --- MVMCoreUI/Categories/UIColor+MFConvenience.h | 4 ++++ MVMCoreUI/Categories/UIColor+MFConvenience.m | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.h b/MVMCoreUI/Categories/UIColor+MFConvenience.h index 97280ba1..2bb81cd8 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.h +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.h @@ -187,4 +187,8 @@ + (nullable NSString *)hexStringForColor:(nonnull UIColor*)color; + (nonnull UIColor *)mfGetColorForHexWithTransparency:(nonnull NSString *)hexString; + +// Returns if the color is dark or not +- (BOOL)isDark; + @end diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.m b/MVMCoreUI/Categories/UIColor+MFConvenience.m index 8786df01..c185e7bb 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.m +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.m @@ -403,4 +403,10 @@ } } +- (BOOL)isDark { + CGFloat greyScale = 0; + [self getWhite:&greyScale alpha:nil]; + return greyScale < 0.5; +} + @end From f98c6059b8b2a307c699429b759d55d62a0502cd Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 27 Sep 2023 15:53:53 -0500 Subject: [PATCH 47/61] rearranged Signed-off-by: Matt Bruce --- MVMCoreUI/Categories/UIColor+MFConvenience.h | 6 +++--- MVMCoreUI/Categories/UIColor+MFConvenience.m | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.h b/MVMCoreUI/Categories/UIColor+MFConvenience.h index 2bb81cd8..10e9433d 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.h +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.h @@ -183,12 +183,12 @@ // Returns a gradient lighter color; + (nonnull UIColor *)mfGradientColor:(nullable UIColor *)color; +// Returns if the color is dark or not +- (BOOL)isDark; + #pragma mark - Hex String + (nullable NSString *)hexStringForColor:(nonnull UIColor*)color; + (nonnull UIColor *)mfGetColorForHexWithTransparency:(nonnull NSString *)hexString; -// Returns if the color is dark or not -- (BOOL)isDark; - @end diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.m b/MVMCoreUI/Categories/UIColor+MFConvenience.m index c185e7bb..ac25ec22 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.m +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.m @@ -389,6 +389,12 @@ return [UIColor whiteColor]; } +- (BOOL)isDark { + CGFloat greyScale = 0; + [self getWhite:&greyScale alpha:nil]; + return greyScale < 0.5; +} + #pragma mark - Hex String + (nullable NSString *)hexStringForColor:(nonnull UIColor*)color { @@ -403,10 +409,4 @@ } } -- (BOOL)isDark { - CGFloat greyScale = 0; - [self getWhite:&greyScale alpha:nil]; - return greyScale < 0.5; -} - @end From a19bd60f063d0a939ebb9c96dd80784bb0e8c6ea Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 27 Sep 2023 15:56:53 -0500 Subject: [PATCH 48/61] indented Signed-off-by: Matt Bruce --- MVMCoreUI/Categories/UIColor+MFConvenience.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.m b/MVMCoreUI/Categories/UIColor+MFConvenience.m index ac25ec22..cd809509 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.m +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.m @@ -390,9 +390,9 @@ } - (BOOL)isDark { - CGFloat greyScale = 0; - [self getWhite:&greyScale alpha:nil]; - return greyScale < 0.5; + CGFloat greyScale = 0; + [self getWhite:&greyScale alpha:nil]; + return greyScale < 0.5; } #pragma mark - Hex String From ab9d61fd156873c6fcc0225c88b9c9ffc57dca5b Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Sep 2023 09:25:50 -0400 Subject: [PATCH 49/61] Link Fix --- MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift | 2 +- .../UINavigationController+Extension.swift | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index 4f4a8b34..c6a14872 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -21,7 +21,7 @@ import VDSColorTokens else { return } // Set line to the same color as the text - if let color = titleLabel?.textColor?.cgColor { + if let color = titleColor(for: state)?.cgColor { context.setStrokeColor(color) } diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index 625f0a25..3372c1ab 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -12,6 +12,7 @@ import MVMCore public extension UINavigationController { /// Convenience function for setting the navigation item. + @MainActor func setNavigationItem(with model: NavigationItemModelProtocol, for viewController: UIViewController, coordinatingWith pageBehaviorController: PageBehaviorHandlerProtocol? = nil) { let behaviorHandler = pageBehaviorController ?? viewController as? PageBehaviorHandlerProtocol; @@ -33,6 +34,7 @@ public extension UINavigationController { } /// Convenience function for setting the navigation buttons. + @MainActor func setNavigationButtons(with model: NavigationItemModelProtocol, for viewController: UIViewController) { let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject var leftItems: [UIBarButtonItem] = [] @@ -60,6 +62,7 @@ public extension UINavigationController { } /// Convenience function for setting the navigation titleView. + @MainActor func setNavigationTitleView(with model: NavigationItemModelProtocol, for viewController: UIViewController, coordinatingWith pageBehaviorController: PageBehaviorHandlerProtocol? = nil) { guard let titleViewModel = model.titleView else { return } @@ -87,6 +90,7 @@ public extension UINavigationController { } /// Convenience function for setting the navigation bar ui + @MainActor func setNavigationBarUI(with model: NavigationItemModelProtocol) { let navigationBar = navigationBar let font = Styler.Font.BoldTitleSmall.getFont(false) From 2d83b8a6ef3d71afb408d0c67eed3116ca99eb06 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Sep 2023 10:22:38 -0400 Subject: [PATCH 50/61] Guard in link code. --- MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index 86776016..5ca77679 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -10,7 +10,7 @@ import UIKit import VDSColorTokens import VDS -@objcMembers open class Link: VDS.TextLink, VDSMoleculeViewProtocol { +open class Link: VDS.TextLink, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Public Properties @@ -43,14 +43,13 @@ import VDS open override func updateAccessibility() { super.updateAccessibility() - if let viewModel { - if let accessibilityText = viewModel.accessibilityText { - self.accessibilityLabel = accessibilityText - } - - if let accessibilityIdentifier = viewModel.accessibilityIdentifier { - self.accessibilityIdentifier = accessibilityIdentifier - } + guard let viewModel = viewModel else { return } + if let accessibilityText = viewModel.accessibilityText { + self.accessibilityLabel = accessibilityText + } + + if let accessibilityIdentifier = viewModel.accessibilityIdentifier { + self.accessibilityIdentifier = accessibilityIdentifier } } From 4d4f7c334d6ebc357ce6222a5578c6107d1387da Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Sep 2023 19:41:06 -0400 Subject: [PATCH 51/61] Code review: Fix data list items and navigation bar. --- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 24 +++++++++++---- .../List/ListProgressBarThin.swift | 9 ++++-- .../List/ListProgressBarThinModel.swift | 10 +++---- .../ListRightVariableTotalData.swift | 18 ++++++++---- .../ListRightVariableTotalDataModel.swift | 20 +++++++++---- .../UINavigationController+Extension.swift | 29 +++++++++---------- .../SubNav/SubNavManagerController.swift | 13 +++++---- 7 files changed, 77 insertions(+), 46 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index ecb39df0..a170c4b4 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -10,7 +10,7 @@ import UIKit import VDSColorTokens import VDS -@objcMembers public class LineModel: MoleculeModelProtocol, Invertable { +public class LineModel: MoleculeModelProtocol, Invertable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- @@ -29,9 +29,23 @@ import VDS case between } + /** + The style of the line: + - secondary (VDS Secondary) + - primary (VDS Primary) + - standard (VDS Secondary) - deprecated + - thin (VDS Primar) - deprecated + - medium (VDS Primar) + - heavy (VDS Primar) + - none (hidden) + */ public enum Style: String, Codable { case secondary case primary + case standard + case thin + case medium + case heavy case none } @@ -43,7 +57,7 @@ import VDS public var id: String = UUID().uuidString public var backgroundColor: Color? - public var type: Style = .primary + public var type: Style = .secondary public var frequency: Frequency? = .allExceptTop public var inverted: Bool = false @@ -58,7 +72,7 @@ import VDS self.type = type } - public init(verticalLineOf type: Style, backgroundColor: Color? = nil) { + public init(verticalLineOf type: Style) { self.type = type } @@ -100,7 +114,7 @@ import VDS /// adding code to look for the old useVerticalLine or the new orientation if let useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) { orientation = useVerticalLine ? .vertical : .horizontal - }else if let orientation = try typeContainer.decodeIfPresent(VDS.Line.Orientation.self, forKey: .orientation) { + } else if let orientation = try typeContainer.decodeIfPresent(VDS.Line.Orientation.self, forKey: .orientation) { self.orientation = orientation } } @@ -112,6 +126,6 @@ import VDS try container.encode(type, forKey: .type) try container.encode(inverted, forKey: .inverted) try container.encodeIfPresent(frequency, forKey: .frequency) - try container.encodeIfPresent(orientation == .vertical, forKey: .useVerticalLine) + try container.encode(orientation == .vertical, forKey: .useVerticalLine) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift index d9875068..e29ef00c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -7,7 +7,7 @@ // -@objcMembers open class ListProgressBarThin: TableViewCell { +open class ListProgressBarThin: TableViewCell { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- @@ -15,7 +15,11 @@ public let progressBar = ProgressBar() public let leftHeadline = Label(fontStyle: .BoldBodySmall) public let leftBody = Label(fontStyle: .BoldBodySmall) - public let rightBar = Line() + public let rightBar: DataLine = { + var line = DataLine() + line.heightConstraint.constant = 2 + return line + }() public let rightLabel = Label(fontStyle: .BoldBodySmall) private let barStackItem: StackItem private let rightLabelStackItem: StackItem @@ -102,7 +106,6 @@ leftHeadline.styleB1(true) leftBody.styleB2(true) rightLabel.styleB2(true) - rightBar.setStyle(.primary) } //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift index d6787f52..0cc5f172 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift @@ -16,14 +16,14 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol { public var progressBar: ProgressBarModel public var leftHeadline: LabelModel public var leftBody: LabelModel? - public var rightBar: LineModel + public var rightBar: DataLineModel public var rightLabel: LabelModel //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: LineModel, rightLabel: LabelModel) { + public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: DataLineModel, rightLabel: LabelModel) { self.progressBar = progressBar self.leftHeadline = leftHeadline self.leftBody = leftBody @@ -38,9 +38,7 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol { override public func setDefaults() { super.setDefaults() - - rightBar.type = .primary - + if rightBar.backgroundColor == nil { rightBar.backgroundColor = Color(uiColor: .gray) } @@ -74,7 +72,7 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol { progressBar = try typeContainer.decode(ProgressBarModel.self, forKey:.progressBar) leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline) leftBody = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .leftBody) - rightBar = try typeContainer.decode(LineModel.self, forKey: .rightBar) + rightBar = try typeContainer.decode(DataLineModel.self, forKey: .rightBar) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) try super.init(from: decoder) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift index 9845ea16..6dc1ffe2 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift @@ -6,15 +6,26 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // +open class DataLine: View { + + lazy var heightConstraint = heightAnchor.constraint(equalToConstant: 4) + lazy var widthConstraint = widthAnchor.constraint(equalToConstant: 20) + + open override func setupView() { + super.setupView() + heightConstraint.isActive = true + widthConstraint.isActive = true + } +} -@objcMembers open class ListRightVariableTotalData: TableViewCell { +open class ListRightVariableTotalData: TableViewCell { //----------------------------------------------------- // MARK: - Outlets //----------------------------------------------------- public let leftLabel = Label(fontStyle: .BoldBodySmall) public let rightLabel = Label(fontStyle: .RegularBodySmall) - public let bar = Line() + public let bar = DataLine() //----------------------------------------------------- // MARK: - Properties @@ -44,8 +55,6 @@ override open func setupView() { super.setupView() - bar.setStyle(.primary) - bar.widthAnchor.constraint(equalToConstant: 20).isActive = true rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) addMolecule(stack) stack.restack() @@ -74,7 +83,6 @@ super.reset() leftLabel.setFontStyle(.BoldBodySmall) rightLabel.setFontStyle(.RegularBodySmall) - bar.setStyle(.primary) } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift index 53ede6e5..28a3a25c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalDataModel.swift @@ -6,8 +6,18 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // +public struct DataLineModel: Codable, MoleculeModelProtocol { + public var id: String = UUID().uuidString + public static var identifier: String = "line" + public var backgroundColor: Color? + + private enum CodingKeys: String, CodingKey { + case backgroundColor + } +} public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -15,7 +25,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc public static var identifier: String = "listRVLine" public var leftLabel: LabelModel public var rightLabel: LabelModel - public var bar: LineModel + public var bar: DataLineModel //-------------------------------------------------- // MARK: - Method @@ -24,8 +34,6 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc override public func setDefaults() { super.setDefaults() rightLabel.hero = 0 - bar.type = .primary - if bar.backgroundColor == nil { bar.backgroundColor = Color(uiColor: .mvmBlue) } @@ -35,7 +43,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc // MARK: - Initializer //-------------------------------------------------- - public init(leftLabel: LabelModel, rightlabel:LabelModel, bar: LineModel){ + public init(leftLabel: LabelModel, rightlabel:LabelModel, bar: DataLineModel) { self.leftLabel = leftLabel self.rightLabel = rightlabel self.bar = bar @@ -46,7 +54,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc // MARK: - Keys //-------------------------------------------------- - private enum CodingKeys: String, CodingKey{ + private enum CodingKeys: String, CodingKey { case moleculeName case leftLabel case rightLabel @@ -61,7 +69,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) - bar = try typeContainer.decode(LineModel.self, forKey: .bar) + bar = try typeContainer.decode(DataLineModel.self, forKey: .bar) try super.init(from: decoder) } diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index ac9684ac..fb1bde79 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -82,13 +82,6 @@ public extension UINavigationController { } } - /// Returns a ShadowImage based on the line property of NavigationItemModelProtocol - func getNavigationBarShadowImage(for navigationItemModel: NavigationItemModelProtocol) -> UIImage? { - guard let model = navigationItemModel.line else { return nil } - let line = Line(model: model, nil, nil) - return line.lineColor.image(CGSize(width: line.lineWidth, height: line.lineWidth)) - } - /// Convenience function for setting the navigation bar ui @MainActor func setNavigationBarUI(with model: NavigationItemModelProtocol) { @@ -105,14 +98,7 @@ public extension UINavigationController { appearance.backgroundColor = backgroundColor appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) appearance.titlePositionAdjustment = model.titleOffset ?? .zero - if let type = model.line?.type, - type != .none, - let color = model.line?.backgroundColor { - appearance.shadowColor = color.uiColor - } else { - appearance.shadowColor = .clear - } - appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate) + appearance.setShadow(for: model.line) navigationBar.standardAppearance = appearance navigationBar.scrollEdgeAppearance = appearance @@ -126,3 +112,16 @@ public extension UINavigationController { return viewController } } + +public extension UINavigationBarAppearance { + func setShadow(for model: LineModel?) { + let model = model ?? LineModel(type: .secondary) + let line = Line(model: model, nil, nil) + if model.type != .none { + shadowColor = line.lineColor + } else { + shadowColor = .clear + } + shadowImage = line.lineColor.image(CGSize(width: line.lineWidth, height: line.lineWidth)).withRenderingMode(.alwaysTemplate) + } +} diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 458c0169..7461c93d 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -125,13 +125,14 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, /// Hides/Shows the navigation bar for the page. open func hideNavigationBarLine(_ isHidden: Bool) { guard self == navigationController?.topViewController else { return } - var color = UIColor.clear - if !isHidden, - let backgroundColor = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line?.backgroundColor?.uiColor { - color = backgroundColor + var model: LineModel? + if isHidden { + model = LineModel(type: .none) + } else if let lineModel = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line { + model = lineModel } - navigationController?.navigationBar.standardAppearance.shadowColor = color - navigationController?.navigationBar.scrollEdgeAppearance?.shadowColor = color + navigationController?.navigationBar.standardAppearance.setShadow(for: model) + navigationController?.navigationBar.scrollEdgeAppearance?.setShadow(for: model) } open override func updateViews() { From 1da8a6db77b106baf683f625ab6e4155e7ca065f Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Sep 2023 20:12:36 -0400 Subject: [PATCH 52/61] Default to secondary --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 6 +++--- .../UINavigationController+Extension.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index c3ce3d7f..2d20d209 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -28,17 +28,17 @@ import VDS public required init() { super.init() - viewModel = LineModel(type: .primary) + viewModel = LineModel(type: .secondary) } public override init(frame: CGRect) { super.init(frame: frame) - viewModel = LineModel(type: .primary) + viewModel = LineModel(type: .secondary) } public required init?(coder: NSCoder) { super.init(coder: coder) - viewModel = LineModel(type: .primary) + viewModel = LineModel(type: .secondary) } //-------------------------------------------------- diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index fb1bde79..57aeb02d 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -117,7 +117,7 @@ public extension UINavigationBarAppearance { func setShadow(for model: LineModel?) { let model = model ?? LineModel(type: .secondary) let line = Line(model: model, nil, nil) - if model.type != .none { + if line.shouldBeVisible() { shadowColor = line.lineColor } else { shadowColor = .clear From e5e17a286df55c0bf4a9ef43c9ca0e3ff2ae61e5 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Sep 2023 20:31:25 -0400 Subject: [PATCH 53/61] fix to vertical lines --- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index a170c4b4..8a473016 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -74,6 +74,7 @@ public class LineModel: MoleculeModelProtocol, Invertable { public init(verticalLineOf type: Style) { self.type = type + orientation = .vertical } //-------------------------------------------------- From c3503edecbaf54888b915a29002f21a17ff92baa Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Sep 2023 20:39:50 -0400 Subject: [PATCH 54/61] Changes to ensure line does not stretch --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index 2d20d209..ba0af74f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -17,6 +17,22 @@ import VDS open var viewModel: LineModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? + + open override var orientation: Line.Orientation { + didSet { + if orientation == .horizontal { + setContentHuggingPriority(.defaultLow, for: .horizontal) + setContentHuggingPriority(.required, for: .vertical) + setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + setContentCompressionResistancePriority(.required, for: .vertical) + } else { + setContentHuggingPriority(.required, for: .horizontal) + setContentHuggingPriority(.defaultLow, for: .vertical) + setContentCompressionResistancePriority(.required, for: .horizontal) + setContentCompressionResistancePriority(.defaultLow, for: .vertical) + } + } + } //-------------------------------------------------- // MARK: - Initializer From 308700c667f3c2534a51bffd2043620d2c2407e3 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 4 Oct 2023 10:17:49 -0400 Subject: [PATCH 55/61] MVMCoreObject to swift --- .../xcshareddata/xcschemes/MVMCoreUI.xcscheme | 66 +++++++++++++++++++ MVMCoreUI/Alerts/AlertOperation.swift | 2 +- MVMCoreUI/OtherHandlers/CoreUIObject.swift | 16 ++--- MVMCoreUI/OtherHandlers/MVMCoreUISession.m | 3 +- 4 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 MVMCoreUI.xcodeproj/xcshareddata/xcschemes/MVMCoreUI.xcscheme diff --git a/MVMCoreUI.xcodeproj/xcshareddata/xcschemes/MVMCoreUI.xcscheme b/MVMCoreUI.xcodeproj/xcshareddata/xcschemes/MVMCoreUI.xcscheme new file mode 100644 index 00000000..9e236f99 --- /dev/null +++ b/MVMCoreUI.xcodeproj/xcshareddata/xcschemes/MVMCoreUI.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MVMCoreUI/Alerts/AlertOperation.swift b/MVMCoreUI/Alerts/AlertOperation.swift index 088a6ff5..50b71e46 100644 --- a/MVMCoreUI/Alerts/AlertOperation.swift +++ b/MVMCoreUI/Alerts/AlertOperation.swift @@ -73,7 +73,7 @@ public class AlertOperation: MVMCoreOperation { if await !self.properties.getIsDisplayed() { self.markAsFinished() } else { - (CoreUIObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject) + (MVMCoreObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject) if self.isCancelled { await self.dismissAlertView() } diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index b96e9b93..5f16a8f3 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -9,19 +9,17 @@ import UIKit import MVMCore -@objcMembers open class CoreUIObject: MVMCoreObject { +@objcMembers +public class CoreUIObject: NSObject { + private static var singleton = CoreUIObject() + public static func sharedInstance() -> CoreUIObject? { singleton } + private override init() {} + public var alertHandler: AlertHandler? public var topNotificationHandler: NotificationHandler? - open override func defaultInitialSetup() { + public func defaultInitialSetup() { CoreUIModelMapping.registerObjects() - loadHandler = MVMCoreLoadHandler() - cache = MVMCoreCache() - session = MVMCoreUISession() - sessionHandler = MVMCoreSessionTimeHandler() - actionHandler = MVMCoreUIActionHandler() - viewControllerMapping = MVMCoreUIViewControllerMappingObject() - loggingDelegate = MVMCoreUILoggingHandler() alertHandler = AlertHandler() } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUISession.m b/MVMCoreUI/OtherHandlers/MVMCoreUISession.m index 42a3e769..3b1d5913 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUISession.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUISession.m @@ -9,7 +9,8 @@ #import "MVMCoreUISession.h" #import "MFLoadingViewController.h" #import "NSLayoutConstraint+MFConvenience.h" -@import MVMCore.MVMCoreObject; +@import MVMCore.MVMCoreLoadingOverlayDelegateProtocol; +@import MVMCore.Swift; @interface MVMCoreUISession () From e940c9bf087da7112718d4723728eed1378b23a8 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 4 Oct 2023 17:20:54 -0400 Subject: [PATCH 56/61] add to default config --- MVMCoreUI/OtherHandlers/CoreUIObject.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index 5f16a8f3..d1fd18f9 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -19,7 +19,12 @@ public class CoreUIObject: NSObject { public var topNotificationHandler: NotificationHandler? public func defaultInitialSetup() { + MVMCoreObject.sharedInstance()?.defaultInitialSetup() CoreUIModelMapping.registerObjects() + MVMCoreObject.sharedInstance()?.session = MVMCoreUISession() + MVMCoreObject.sharedInstance()?.actionHandler = MVMCoreUIActionHandler() + MVMCoreObject.sharedInstance()?.viewControllerMapping = MVMCoreUIViewControllerMappingObject() + MVMCoreObject.sharedInstance()?.loggingDelegate = MVMCoreUILoggingHandler() alertHandler = AlertHandler() } } From 0afa13392f4faaf80d0678f8340ff5392a6ec47b Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 5 Oct 2023 13:53:19 -0400 Subject: [PATCH 57/61] take into account contentInset when calculating itemWidth --- MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index ea7d89b8..6b360120 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -384,7 +384,7 @@ open class Carousel: View { extension Carousel: UICollectionViewDelegateFlowLayout { open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - let itemWidth = collectionView.bounds.width * itemWidthPercent + let itemWidth = (collectionView.bounds.width - collectionView.contentInset.left - collectionView.contentInset.right) * itemWidthPercent return CGSize(width: itemWidth, height: collectionView.bounds.height) } From 281f1e8f52572d98c59db3a45b07ceb0861e329e Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 12 Oct 2023 12:52:23 -0400 Subject: [PATCH 58/61] Fix extra space on the left of title issue for ExternalLink --- MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift index 9e5cd108..3e8fa804 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift @@ -29,7 +29,8 @@ open class ExternalLink: Link { open override func setup() { super.setup() - + contentHorizontalAlignment = .left + let image = MVMCoreUIUtility.imageNamed("externalLink") exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate)) From c8aac2e5d7056279496ad40bf2cdf5e8aa5f742b Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Fri, 13 Oct 2023 14:21:22 -0400 Subject: [PATCH 59/61] Updated to get the upcoming view controller navigationBar model --- .../UINavigationController+Extension.swift | 2 +- MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index 3372c1ab..2909ce4a 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -119,7 +119,7 @@ public extension UINavigationController { setNavigationBarHidden(model.hidden, animated: true) } - @MainActor + @objc @MainActor func getViewController() -> UIViewController? { guard let topViewController = getViewControllers().last, let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { return nil } diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift index e04de6bb..05cd9ae2 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift +++ b/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift @@ -57,9 +57,10 @@ public extension MVMCoreUIUtility { return findViews(by: type, views: queue) + matching } + @MainActor static func visibleNavigationBarStlye() -> NavigationItemStyle? { - if let vc = MVMCoreUIUtility.getCurrentVisibleController(), - let navController = NavigationController.navigationController(), + if let navController = NavigationController.navigationController(), + let vc = navController.getViewController(), let navigationBar = navController.getNavigationModel(from: vc) as? NavigationItemModel { return navigationBar.style } From b1da7aaeed03b28035f7c95d843a823647185ccd Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 23 Oct 2023 16:41:08 -0400 Subject: [PATCH 60/61] Footer button filled for iphones --- .../Atomic/Molecules/HeadersAndFooters/FooterModel.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift index bab51c2d..dd23035c 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift @@ -24,5 +24,9 @@ if bottomPadding == nil { bottomPadding = PaddingDefaultVerticalSpacing } + guard let _ = molecule as? ButtonModel, + !MVMCoreGetterUtility.isOnIPad(), + horizontalAlignment == nil else { return } + horizontalAlignment = .fill } } From e373aa3b086c8ec4128691319fa50eb77b7339fc Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 23 Oct 2023 17:42:32 -0400 Subject: [PATCH 61/61] Full width foot pill button --- .../Molecules/HeadersAndFooters/FooterModel.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift index dd23035c..93e296f2 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift @@ -24,9 +24,14 @@ if bottomPadding == nil { bottomPadding = PaddingDefaultVerticalSpacing } - guard let _ = molecule as? ButtonModel, - !MVMCoreGetterUtility.isOnIPad(), - horizontalAlignment == nil else { return } - horizontalAlignment = .fill + guard !MVMCoreGetterUtility.isOnIPad(), + horizontalAlignment == nil else { return } + + if let _ = molecule as? ButtonModel { + horizontalAlignment = .fill + } else if let model = molecule as? TwoButtonViewModel, + model.primaryButton == nil || model.secondaryButton == nil { + horizontalAlignment = .fill + } } }