From 790a19b34f2719f616d6178772a7c26c791eead0 Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Fri, 19 Mar 2021 17:04:21 -0400 Subject: [PATCH 01/20] initial progress --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ .../Molecules/Items/TabsListItemModel.swift | 2 +- .../MoleculeContainerModel.swift | 10 ++++ .../MoleculeContainerProtocol.swift | 10 +++- MVMCoreUI/Atomic/Organisms/StackModel.swift | 8 ++- .../Atomic/Organisms/StackModelProtocol.swift | 8 ++- .../MoleculeModelProtocol.swift | 53 ++++++++++++++++++- .../ParentMoleculeModelProtocol.swift | 39 ++++++++++++++ .../TemplateModelProtocol.swift | 1 + .../MoleculeTreeTraversalProtocol.swift | 48 +++++++++++++++++ .../Templates/CollectionTemplateModel.swift | 7 +++ .../Templates/ListPageTemplateModel.swift | 7 +++ .../Atomic/Templates/TemplateModel.swift | 1 + .../Templates/ThreeLayerModelBase.swift | 12 +++++ .../ThreeLayerPageTemplateModel.swift | 7 +++ .../BaseControllers/ViewController.swift | 7 +++ 16 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift create mode 100644 MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9ba02cb8..664974b2 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -123,6 +123,8 @@ 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; }; + 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */; }; + 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */; }; 27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehavior.swift */; }; 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; @@ -679,6 +681,8 @@ 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = ""; }; + 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTreeTraversalProtocol.swift; sourceTree = ""; }; + 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentMoleculeModelProtocol.swift; sourceTree = ""; }; 27F973522466074500CAB5C5 /* PageBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehavior.swift; sourceTree = ""; }; 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenBrightnessModifierBehavior.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; @@ -1147,6 +1151,7 @@ D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */, D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */, D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */, + 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */, ); path = ModelProtocols; sourceTree = ""; @@ -2275,6 +2280,7 @@ isa = PBXGroup; children = ( 012A88C7238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift */, + 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, D20F3B43252E00E4004B3F56 /* PageProtocol.swift */, 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */, @@ -2820,6 +2826,7 @@ 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */, AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */, + 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */, D2D3957A252FDBB300047B11 /* ModalSectionListTemplate.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */, @@ -2945,6 +2952,7 @@ 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, + 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */, 0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift index c83b8933..d0f13c1f 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift @@ -12,7 +12,7 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "tabsListItem" var tabs: TabsModel var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]] - + private enum CodingKeys: String, CodingKey { case moleculeName case tabs diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift index 77b40716..dadf3aa9 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift @@ -48,4 +48,14 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco try container.encodeModel(molecule, forKey: .molecule) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } + + public func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + let result = nextPartialResult(initialResult, molecule) + return nextPartialResult(result, self) + } + + public func depthFirstTraverse(_ cb: (MoleculeModelProtocol)->Void) { + cb(molecule) + cb(self) + } } diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift index 882cf181..636e7af0 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift @@ -8,6 +8,14 @@ import Foundation -public protocol MoleculeContainerModelProtocol: ContainerModelProtocol { +public protocol MoleculeContainerModelProtocol: ContainerModelProtocol, ParentMoleculeModelProtocol { var molecule: MoleculeModelProtocol { get set } } + +public extension MoleculeContainerModelProtocol { + + var children: [MoleculeModelProtocol] { + return [molecule] + } + +} diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index d96da035..8b1dcc0f 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -7,7 +7,8 @@ // -@objcMembers public class StackModel: ContainerModel, StackModelProtocol, MoleculeModelProtocol { +@objcMembers public class StackModel: ContainerModel, StackModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -24,6 +25,10 @@ public var spacing: CGFloat = StackModel.defaultSpacing public var useStackSpacingBeforeFirstItem = false + public var children: [MoleculeModelProtocol] { + return molecules + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -77,4 +82,5 @@ try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } + } diff --git a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift index 54f6c9d0..068418f0 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift @@ -8,9 +8,15 @@ import Foundation -public protocol StackModelProtocol { +public protocol StackModelProtocol: ParentMoleculeModelProtocol { var molecules: [StackItemModelProtocol & MoleculeModelProtocol] { get set } var axis: NSLayoutConstraint.Axis { get set } var spacing: CGFloat { get set } var useStackSpacingBeforeFirstItem: Bool { get set } } + +extension StackModelProtocol { + + public var children: [MoleculeModelProtocol] { return molecules } + +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index 4f0cd296..03c9c596 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -7,7 +7,7 @@ public enum MolecularError: Swift.Error { } -public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol { +public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol { var moleculeName: String { get } var backgroundColor: Color? { get set } } @@ -20,3 +20,54 @@ public extension MoleculeModelProtocol { static var categoryCodingKey: String { "moleculeName" } } + +public extension MoleculeModelProtocol { + + func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + + return nextPartialResult(initialResult, self) + } + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + callback(self) + } + +} + +public extension Array where Element == MoleculeModelProtocol { + + func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + return reduce(initialResult) { (result, molecule) -> Result in + return molecule.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + } + } + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + forEach { (molecule) in + molecule.depthFirstTraverse(callback: callback) + } + } +} + +// Would prefer these to be defined in MoleculeTreeTraversalProtocol that MoleculeModelProtocol inherits. +public extension Array where Element == MoleculeModelProtocol { + + func countMolecules() -> Int { + return reduce(0) { (accumulator, molecule) in + return accumulator + molecule.countMolecules() + } + } + + func printMolecules() { + forEach { (molecule) in + molecule.printMolecules() + } + } + + func allMoleculesOfType() -> [T] { + return reduce([]) { (accumulator, molecule) in + return accumulator + molecule.allMoleculesOfType() + } + } + +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift new file mode 100644 index 00000000..5afa57f7 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -0,0 +1,39 @@ +// +// ParentModelProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 3/19/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol { + + var children: [MoleculeModelProtocol] { get } + +} + +public extension ParentMoleculeModelProtocol { + + func reduceDepthFirstTraverse(initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol) -> Result) -> Result { + + let result = children.reduce(initialResult) { (result, molecule) -> Result in + if let additionalParent = molecule as? ParentMoleculeModelProtocol { + return additionalParent.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + } + return molecule.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + } + return nextPartialResult(result, self) + } + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + children.forEach { (molecule) in + if let additionalParent = molecule as? ParentMoleculeModelProtocol { + additionalParent.depthFirstTraverse(callback: callback) + } + molecule.depthFirstTraverse(callback: callback) + } + callback(self) + } +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift index 3ed37d6b..31e5a131 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift @@ -11,6 +11,7 @@ import Foundation public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol { var template: String { get } + var rootMolecules: [MoleculeModelProtocol] { get } } public extension TemplateModelProtocol { diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift new file mode 100644 index 00000000..dc5ff7f2 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift @@ -0,0 +1,48 @@ + +// +// TreeTraversalProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 3/19/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol MoleculeTreeTraversalProtocol { + + // Future options -- Parent first depth first, leaves only. + + func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result + + func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) + + //func breadthFirstTraverse() +} + +// +// Helper Extensions +// + +extension MoleculeTreeTraversalProtocol { + + func countMolecules() -> Int { + return reduceDepthFirstTraverse(initialResult: 0) { (accumulator, molecule) in + return accumulator + 1 + } + } + + func printMolecules() { + depthFirstTraverse { (molecule) in + print(molecule) + } + } + + func allMoleculesOfType() -> [T] { + return reduceDepthFirstTraverse(initialResult: []) { (accumulator, molecule) in + if let typedMolecule = molecule as? T { + return accumulator + [typedMolecule] + } + return accumulator + } + } + +} diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift index f9d8c0a7..b0f3ae92 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift @@ -18,6 +18,13 @@ import Foundation } public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]? public var columns: Int? + + public override var rootMolecules: [MoleculeModelProtocol] { + if let molecules = molecules { + return super.rootMolecules + molecules + } + return super.rootMolecules + } //-------------------------------------------------- // MARK: - Initializer diff --git a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift index a7c92a08..44868e10 100644 --- a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift @@ -20,6 +20,13 @@ import Foundation public var line: LineModel? public var scrollToRowIndex: Int? + public override var rootMolecules: [MoleculeModelProtocol] { + if let molecules = molecules { + return super.rootMolecules + molecules + } + return super.rootMolecules + } + /// This template requires content. func validateModelHasContent() throws { if header == nil, diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index bb8bb104..c3d9bbbb 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -30,6 +30,7 @@ import Foundation public var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? public var behaviors: [PageBehaviorProtocol]? + public var rootMolecules: [MoleculeModelProtocol] { [] } public var tabBarHidden: Bool = false public var tabBarIndex: Int? diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift index 1120b0e7..405a94ce 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift @@ -9,11 +9,23 @@ import Foundation @objcMembers open class ThreeLayerModelBase: TemplateModel, ThreeLayerTemplateModelProtocol { + public var anchorHeader: Bool = false public var header: MoleculeModelProtocol? public var anchorFooter: Bool = false public var footer: MoleculeModelProtocol? + public override var rootMolecules: [MoleculeModelProtocol] { + var rootMolecules:[MoleculeModelProtocol] = [] + if let header = header { + rootMolecules.append(header) + } + if let footer = footer { + rootMolecules.append(footer) + } + return rootMolecules + } + public override init(pageType: String) { super.init(pageType: pageType) } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift index c4e93f7a..ced0b9ab 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift @@ -14,6 +14,13 @@ import Foundation } public var middle: MoleculeModelProtocol? + public override var rootMolecules: [MoleculeModelProtocol] { + if let middle = middle { + return super.rootMolecules + [middle] + } + return super.rootMolecules + } + public init(pageType: String, header: MoleculeModelProtocol?, middle: MoleculeModelProtocol?, footer: MoleculeModelProtocol?) { super.init(pageType: pageType) self.header = header diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index a2d82952..701d0fb2 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -336,6 +336,13 @@ import UIKit initialLoad() } + print("total molecules in tree: \(model?.rootMolecules.countMolecules() ?? 0)") + + model?.rootMolecules.printMolecules() + + let allVideoMolecules:[BGVideoImageMoleculeModel] = model?.rootMolecules.allMoleculesOfType() ?? [] + print("video molecules: \(allVideoMolecules.count)") + handleNewDataAndUpdateUI() } From 0c0fff22bbf92266ffabe95c2df4a1213b3e193c Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Mon, 22 Mar 2021 12:26:33 -0400 Subject: [PATCH 02/20] further ehancement and reach --- .../TwoButtonViewModel.swift | 6 ++- .../HeadlineBodyModel.swift | 6 ++- .../Organisms/Carousel/CarouselModel.swift | 10 ++++- .../MoleculeModelProtocol.swift | 17 ++++---- .../ParentMoleculeModelProtocol.swift | 39 +++++++++++++------ .../MoleculeTreeTraversalProtocol.swift | 26 ++++++++----- .../Templates/ThreeLayerModelBase.swift | 9 +---- 7 files changed, 72 insertions(+), 41 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index d4da0ba4..c767dc36 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -9,7 +9,7 @@ import UIKit -public class TwoButtonViewModel: MoleculeModelProtocol { +public class TwoButtonViewModel: ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -19,6 +19,10 @@ public class TwoButtonViewModel: MoleculeModelProtocol { public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? + public var children: [MoleculeModelProtocol] { + return [primaryButton, secondaryButton].compactMap { $0 } + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index ebc5614e..a7ff7280 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -9,7 +9,7 @@ import Foundation -@objcMembers open class HeadlineBodyModel: MoleculeModelProtocol { +@objcMembers open class HeadlineBodyModel: ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -21,6 +21,10 @@ import Foundation public var style: Style? public var backgroundColor: Color? + public var children: [MoleculeModelProtocol] { + return [headline, body].compactMap { $0 } + } + //-------------------------------------------------- // MARK: - Enum //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift index 5bf0728c..8721db72 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift @@ -9,7 +9,7 @@ import UIKit -@objcMembers public class CarouselModel: MoleculeModelProtocol, FormFieldProtocol { +@objcMembers public class CarouselModel: ParentMoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- // MARK: - Properties @@ -144,3 +144,11 @@ import UIKit try container.encode(selectedIndex, forKey: .selectedIndex) } } + +extension CarouselModel { + + public var children: [MoleculeModelProtocol] { + return molecules + } + +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index 03c9c596..f7927a1b 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -23,28 +23,29 @@ public extension MoleculeModelProtocol { public extension MoleculeModelProtocol { - func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { - + // Base case. No additional children to traverse. + func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { return nextPartialResult(initialResult, self) } - func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { - callback(self) + // Base case. No additional children to traverse. + func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) { + onVisit(self) } } public extension Array where Element == MoleculeModelProtocol { - func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { return reduce(initialResult) { (result, molecule) -> Result in - return molecule.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + return molecule.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) } } - func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, callback: (MoleculeModelProtocol)->Void) { forEach { (molecule) in - molecule.depthFirstTraverse(callback: callback) + molecule.depthFirstTraverse(options: options, onVisit: callback) } } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift index 5afa57f7..a1d9d225 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -16,24 +16,39 @@ public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol { public extension ParentMoleculeModelProtocol { - func reduceDepthFirstTraverse(initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol) -> Result) -> Result { - - let result = children.reduce(initialResult) { (result, molecule) -> Result in - if let additionalParent = molecule as? ParentMoleculeModelProtocol { - return additionalParent.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) - } - return molecule.reduceDepthFirstTraverse(initialResult: result, nextPartialResult: nextPartialResult) + func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol) -> Result) -> Result { + var result = initialResult + if (options == .parentFirst) { + result = nextPartialResult(result, self) } - return nextPartialResult(result, self) + result = children.reduce(result) { (result, molecule) -> Result in + if let additionalParent = molecule as? ParentMoleculeModelProtocol { + // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. + return additionalParent.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) + } + return molecule.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) + } + if (options == .childFirst) { + result = nextPartialResult(result, self) + } + // if options == .leafOnly don't call on self. + return result } - func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) { + if (options == .parentFirst) { + onVisit(self) + } children.forEach { (molecule) in if let additionalParent = molecule as? ParentMoleculeModelProtocol { - additionalParent.depthFirstTraverse(callback: callback) + // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. + additionalParent.depthFirstTraverse(options: options, onVisit: onVisit) } - molecule.depthFirstTraverse(callback: callback) + molecule.depthFirstTraverse(options: options, onVisit: onVisit) } - callback(self) + if (options == .childFirst) { + onVisit(self) + } + // if options == .leafOnly don't call on self. } } diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift index dc5ff7f2..137d8a77 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift @@ -7,13 +7,19 @@ // Copyright © 2021 Verizon Wireless. All rights reserved. // +public enum TreeTraversalOptions { + case parentFirst + case childFirst + case leafNodesOnly +} + public protocol MoleculeTreeTraversalProtocol { - + // Future options -- Parent first depth first, leaves only. - func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result + func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result - func depthFirstTraverse(callback: (MoleculeModelProtocol)->Void) + func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) //func breadthFirstTraverse() } @@ -24,20 +30,20 @@ public protocol MoleculeTreeTraversalProtocol { extension MoleculeTreeTraversalProtocol { - func countMolecules() -> Int { - return reduceDepthFirstTraverse(initialResult: 0) { (accumulator, molecule) in + func countMolecules(options: TreeTraversalOptions = .parentFirst) -> Int { + return reduceDepthFirstTraverse(options: options, initialResult: 0) { (accumulator, molecule) in return accumulator + 1 } } - func printMolecules() { - depthFirstTraverse { (molecule) in - print(molecule) + func printMolecules(options: TreeTraversalOptions = .parentFirst) { + depthFirstTraverse(options: options) { (molecule) in + print("\"\(molecule.moleculeName)\" [\(molecule)]") } } - func allMoleculesOfType() -> [T] { - return reduceDepthFirstTraverse(initialResult: []) { (accumulator, molecule) in + func allMoleculesOfType(options: TreeTraversalOptions = .parentFirst) -> [T] { + return reduceDepthFirstTraverse(options: options, initialResult: []) { (accumulator, molecule) in if let typedMolecule = molecule as? T { return accumulator + [typedMolecule] } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift index 405a94ce..25e7d1e9 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift @@ -16,14 +16,7 @@ import Foundation public var footer: MoleculeModelProtocol? public override var rootMolecules: [MoleculeModelProtocol] { - var rootMolecules:[MoleculeModelProtocol] = [] - if let header = header { - rootMolecules.append(header) - } - if let footer = footer { - rootMolecules.append(footer) - } - return rootMolecules + return [header, footer].compactMap { $0 } } public override init(pageType: String) { From a45b5119cb11622b804746ed24d06781347fb78f Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Mon, 22 Mar 2021 13:31:05 -0400 Subject: [PATCH 03/20] depth tracking --- .../MoleculeModelProtocol.swift | 16 +++++++------- .../ParentMoleculeModelProtocol.swift | 21 ++++++++++--------- .../MoleculeTreeTraversalProtocol.swift | 12 +++++------ 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index f7927a1b..4b432c2e 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -24,28 +24,28 @@ public extension MoleculeModelProtocol { public extension MoleculeModelProtocol { // Base case. No additional children to traverse. - func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { - return nextPartialResult(initialResult, self) + func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result { + return nextPartialResult(initialResult, self, depth) } // Base case. No additional children to traverse. - func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) { - onVisit(self) + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) { + onVisit(depth, self) } } public extension Array where Element == MoleculeModelProtocol { - func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { + func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result { return reduce(initialResult) { (result, molecule) -> Result in - return molecule.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) + return molecule.reduceDepthFirstTraverse(options: options, depth: depth, initialResult: result, nextPartialResult: nextPartialResult) } } - func depthFirstTraverse(options: TreeTraversalOptions, callback: (MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, callback: (Int, MoleculeModelProtocol)->Void) { forEach { (molecule) in - molecule.depthFirstTraverse(options: options, onVisit: callback) + molecule.depthFirstTraverse(options: options, depth: depth, onVisit: callback) } } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift index a1d9d225..2ec05db4 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -16,38 +16,39 @@ public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol { public extension ParentMoleculeModelProtocol { - func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol) -> Result) -> Result { + func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result { var result = initialResult if (options == .parentFirst) { - result = nextPartialResult(result, self) + result = nextPartialResult(result, self, depth) } result = children.reduce(result) { (result, molecule) -> Result in if let additionalParent = molecule as? ParentMoleculeModelProtocol { // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. - return additionalParent.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) + return additionalParent.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult) } - return molecule.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) + return molecule.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult) } if (options == .childFirst) { - result = nextPartialResult(result, self) + result = nextPartialResult(result, self, depth) } // if options == .leafOnly don't call on self. return result } - func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) { if (options == .parentFirst) { - onVisit(self) + onVisit(depth, self) } children.forEach { (molecule) in if let additionalParent = molecule as? ParentMoleculeModelProtocol { // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. - additionalParent.depthFirstTraverse(options: options, onVisit: onVisit) + additionalParent.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit) + } else { + molecule.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit) } - molecule.depthFirstTraverse(options: options, onVisit: onVisit) } if (options == .childFirst) { - onVisit(self) + onVisit(depth, self) } // if options == .leafOnly don't call on self. } diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift index 137d8a77..4e7efabb 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeTreeTraversalProtocol.swift @@ -17,9 +17,9 @@ public protocol MoleculeTreeTraversalProtocol { // Future options -- Parent first depth first, leaves only. - func reduceDepthFirstTraverse(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result + func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result - func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) //func breadthFirstTraverse() } @@ -31,19 +31,19 @@ public protocol MoleculeTreeTraversalProtocol { extension MoleculeTreeTraversalProtocol { func countMolecules(options: TreeTraversalOptions = .parentFirst) -> Int { - return reduceDepthFirstTraverse(options: options, initialResult: 0) { (accumulator, molecule) in + return reduceDepthFirstTraverse(options: options, depth: 0, initialResult: 0) { (accumulator, molecule, depth) in return accumulator + 1 } } func printMolecules(options: TreeTraversalOptions = .parentFirst) { - depthFirstTraverse(options: options) { (molecule) in - print("\"\(molecule.moleculeName)\" [\(molecule)]") + depthFirstTraverse(options: options, depth: 1) { (depth, molecule) in + print("\(String(repeating: ">>", count: depth)) \"\(molecule.moleculeName)\" [\(molecule)]") } } func allMoleculesOfType(options: TreeTraversalOptions = .parentFirst) -> [T] { - return reduceDepthFirstTraverse(options: options, initialResult: []) { (accumulator, molecule) in + return reduceDepthFirstTraverse(options: options, depth: 0, initialResult: []) { (accumulator, molecule, depth) in if let typedMolecule = molecule as? T { return accumulator + [typedMolecule] } From 59435f98f30a3f6098c8a25babec64fe63493fcc Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Mon, 22 Mar 2021 13:40:41 -0400 Subject: [PATCH 04/20] stack template root molecule --- MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift index f21a0421..6491bd8d 100644 --- a/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift @@ -15,6 +15,10 @@ import Foundation } public var moleculeStack: StackModel + public override var rootMolecules: [MoleculeModelProtocol] { + return [header, moleculeStack, footer].compactMap { $0 } + } + public init(pageType: String, moleculeStack: StackModel) { self.moleculeStack = moleculeStack super.init(pageType: pageType) From 3081aeb318c0e1a5df3e2c8933ff59967f61107e Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Mon, 22 Mar 2021 14:46:36 -0400 Subject: [PATCH 05/20] BGVideoImageMoleculeModel video element access --- .../Molecules/OtherContainers/BGVideoImageMoleculeModel.swift | 4 ++++ .../Molecules/OtherContainers/MoleculeContainerModel.swift | 4 ++++ .../Molecules/OtherContainers/MoleculeContainerProtocol.swift | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/BGVideoImageMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGVideoImageMoleculeModel.swift index f2ee20af..6b9a89c3 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/BGVideoImageMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGVideoImageMoleculeModel.swift @@ -15,6 +15,10 @@ open class BGVideoImageMoleculeModel: BGImageMoleculeModel { public var video: VideoModel + public override var children: [MoleculeModelProtocol] { + return [video, molecule] + } + private enum CodingKeys: String, CodingKey { case video } diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift index dadf3aa9..9c1bfc39 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift @@ -15,6 +15,10 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco public var backgroundColor: Color? public var molecule: MoleculeModelProtocol + public var children: [MoleculeModelProtocol] { + return [molecule] + } + private enum CodingKeys: String, CodingKey { case moleculeName case molecule diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift index 636e7af0..1e34932f 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift @@ -13,9 +13,9 @@ public protocol MoleculeContainerModelProtocol: ContainerModelProtocol, ParentMo } public extension MoleculeContainerModelProtocol { - + var children: [MoleculeModelProtocol] { return [molecule] } - + } From 4a491cbfaaa8b72bdf3906624f03db8838790716 Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Tue, 23 Mar 2021 10:00:27 -0400 Subject: [PATCH 06/20] remove unused code --- .../OtherContainers/MoleculeContainerModel.swift | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift index 9c1bfc39..5ddec277 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift @@ -44,7 +44,7 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) } - + open override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) @@ -52,14 +52,4 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco try container.encodeModel(molecule, forKey: .molecule) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } - - public func reduceDepthFirstTraverse(initialResult:Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { - let result = nextPartialResult(initialResult, molecule) - return nextPartialResult(result, self) - } - - public func depthFirstTraverse(_ cb: (MoleculeModelProtocol)->Void) { - cb(molecule) - cb(self) - } } From 081a2a50b82c0e526781df6c39061ebdf5b541dd Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 15:13:32 -0400 Subject: [PATCH 07/20] Make label model subclassaable --- MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift index 6b120d0c..d38a90fd 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift @@ -12,7 +12,7 @@ // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "label" + public class var identifier: String { "label" } public var backgroundColor: Color? public var text: String public var accessibilityText: String? From 14d2516263b0255a643130736f147248ee4d84a3 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 15:18:37 -0400 Subject: [PATCH 08/20] Move to separate files for behavior logic decode molecule for headline in eyebrowheadlinebody behaviors have models and handlers now, not just one --- .../Views/Video/ScrollBehaviorForVideo.swift | 25 ++++++ .../Video/ScrollBehaviorForVideoModel.swift | 20 +++++ .../Atoms/Views/{ => Video}/Video.swift | 0 .../Views/{ => Video}/VideoDataManager.swift | 0 .../Atoms/Views/{ => Video}/VideoModel.swift | 57 ++---------- .../Views/Video/VisibleBehaviorForVideo.swift | 28 ++++++ .../Video/VisibleBehaviorForVideoModel.swift | 20 +++++ MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 5 +- .../EyebrowHeadlineBodyLinkModel.swift | 4 +- .../MoleculeModelProtocol.swift | 14 +++ .../Atomic/Protocols/TemplateProtocol.swift | 9 +- .../Atomic/Templates/TemplateModel.swift | 2 +- .../MVMControllerModelProtocol.swift | 2 +- .../BaseControllers/ViewController.swift | 6 +- .../PageBehaviorHandlerModelProtocol.swift | 36 ++++++++ .../PageBehaviorHandlerProtocol.swift | 30 +++++++ .../Behaviors/PageBehaviorModelProtocol.swift | 35 ++++++++ .../Behaviors/PageBehaviorProtocol.swift | 34 +++++++ .../PageBehaviorProtocolRequirer.swift | 11 +++ .../PageScrolledClosureBehavior.swift | 33 ------- .../PageVisibilityClosureBehavior.swift | 40 --------- .../ScreenBrightnessModifierBehavior.swift | 90 ++++++++++--------- 22 files changed, 325 insertions(+), 176 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift rename MVMCoreUI/Atomic/Atoms/Views/{ => Video}/Video.swift (100%) rename MVMCoreUI/Atomic/Atoms/Views/{ => Video}/VideoDataManager.swift (100%) rename MVMCoreUI/Atomic/Atoms/Views/{ => Video}/VideoModel.swift (64%) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift create mode 100644 MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift create mode 100644 MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift create mode 100644 MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift create mode 100644 MVMCoreUI/Behaviors/PageBehaviorProtocol.swift create mode 100644 MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift delete mode 100644 MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift delete mode 100644 MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift new file mode 100644 index 00000000..77487305 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift @@ -0,0 +1,25 @@ +// +// ScrollBehaviorForVideo.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ScrollBehaviorForVideo: PageScrolledBehavior { + var model: PageBehaviorModelProtocol + + required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.model = model + } + + public func pageScrolled(scrollView: UIScrollView) { + // If visible to not visible, pause video. + // If not visible to visible, unpause if needed, add visible behavior + guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, + let view = model.view else { return } + model.halted = !view.isVisible(in: scrollView) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift new file mode 100644 index 00000000..6e460c22 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift @@ -0,0 +1,20 @@ +// +// ScrollBehaviorForVideoModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ScrollBehaviorForVideoModel: PageBehaviorModelProtocol { + + public static var identifier: String = "visibleBehaviorForVideoModel" + public var shouldAllowMultipleInstances: Bool = true + public weak var videoModel: VideoModel? + + init(with videoModel: VideoModel) { + self.videoModel = videoModel + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Views/Video.swift rename to MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift diff --git a/MVMCoreUI/Atomic/Atoms/Views/VideoDataManager.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoDataManager.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Views/VideoDataManager.swift rename to MVMCoreUI/Atomic/Atoms/Views/Video/VideoDataManager.swift diff --git a/MVMCoreUI/Atomic/Atoms/Views/VideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift similarity index 64% rename from MVMCoreUI/Atomic/Atoms/Views/VideoModel.swift rename to MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift index 1d079599..472ab3de 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/VideoModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift @@ -8,7 +8,7 @@ import Foundation -open class VideoModel: MoleculeModelProtocol { +open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { public static var identifier = "video" public var backgroundColor: Color? public var video: String @@ -39,8 +39,6 @@ open class VideoModel: MoleculeModelProtocol { /// Keeps a reference to the video data. public var videoDataManager: VideoDataManager - private weak var visibleBehavior: PageVisibilityClosureBehavior? - private weak var scrollBehavior: PageScrolledClosureBehavior? private var activeListener: Any? private var resignActiveListener: Any? @@ -81,61 +79,16 @@ open class VideoModel: MoleculeModelProtocol { try container.encode(alwaysReset, forKey: .alwaysReset) } + public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { + return [VisibleBehaviorForVideoModel(with: self), ScrollBehaviorForVideoModel(with: self)] + } + open func addVisibilityHalting(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { self.view = view halted = false - addVisibleBehavior(for: view, delegateObject: delegateObject) - addScrollBehavior(for: view, delegateObject: delegateObject) addActiveListener(for: view, delegateObject: delegateObject) } - /// Adds a behavior to pause the video on page hidden behavior and unpause if necessary on page shown. - open func addVisibleBehavior(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { - - let onShow = { [weak self] in - guard let self = self, - let view = self.view, - view.isVisibleInDelegate() else { return } - self.halted = false - } - let onHide: () -> Void = { [weak self] in - self?.halted = true - } - - guard visibleBehavior == nil else { - visibleBehavior?.pageShownHandler = onShow - visibleBehavior?.pageHiddenHandler = onHide - return - } - - guard var delegate = delegateObject?.behaviorTemplateDelegate else { return } - let pauseBehavior = PageVisibilityClosureBehavior(with: onShow, onPageHiddenHandler: onHide) - delegate.add(behavior: pauseBehavior) - self.visibleBehavior = pauseBehavior - } - - /// Adds a behavior to pause the video if scrolled off of the page and unpause if necessary if scrolled on. - open func addScrollBehavior(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { - - let onScroll = { [weak self] (scrollView: UIScrollView) in - // If visible to not visible, pause video. - // If not visible to visible, unpause if needed, add visible behavior - guard let self = self, - let view = self.view else { return } - self.halted = !view.isVisible(in: scrollView) - } - - guard scrollBehavior == nil else { - scrollBehavior?.pageScrolledHandler = onScroll - return - } - - guard var delegate = delegateObject?.behaviorTemplateDelegate else { return } - let scrollBehavior = PageScrolledClosureBehavior(with: onScroll) - delegate.add(behavior: scrollBehavior) - self.scrollBehavior = scrollBehavior - } - open func addActiveListener(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { removeActiveListener() diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift new file mode 100644 index 00000000..022585fd --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift @@ -0,0 +1,28 @@ +// +// VisibleBehaviorForVideo.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class VisibleBehaviorForVideo: PageVisibilityBehavior { + var model: PageBehaviorModelProtocol + + required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.model = model + } + + public func onPageShown() { + guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, + let view = model.view, + view.isVisibleInDelegate() else { return } + model.halted = false + } + + public func onPageHidden() { + (model as? VisibleBehaviorForVideoModel)?.videoModel?.halted = true + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift new file mode 100644 index 00000000..45734dac --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift @@ -0,0 +1,20 @@ +// +// VisibleBehaviorForVideoModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class VisibleBehaviorForVideoModel: PageBehaviorModelProtocol { + + public static var identifier: String = "visibleBehaviorForVideoModel" + public var shouldAllowMultipleInstances: Bool = true + public weak var videoModel: VideoModel? + + init(with videoModel: VideoModel) { + self.videoModel = videoModel + } +} diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index f868169d..13683ba3 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -243,6 +243,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: NotificationView.self, viewModelClass: NotificationModel.self) MoleculeObjectMapping.shared()?.register(viewClass: CollapsableNotification.self, viewModelClass: CollapsableNotificationModel.self) + // TODO: move all of these out of here. // MARK:- Helper models try? ModelRegistry.register(RuleRequiredModel.self) try? ModelRegistry.register(RuleAnyRequiredModel.self) @@ -261,7 +262,9 @@ import Foundation try? ModelRegistry.register(ActionTopNotificationModel.self) // MARK:- Behaviors - try? ModelRegistry.register(ScreenBrightnessModifierBehavior.self) + try? ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self) + try? ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: Label.self, viewModelClass: SwapMDNWithContactNameLabelModel.self) } /// Convenience function to get required modules for a give model diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index c9410775..2174514d 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -68,7 +68,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) - headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) + headline = try typeContainer.decodeMoleculeIfPresent(codingKey: .headline) body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) setDefaults() @@ -83,7 +83,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(eyebrow, forKey: .eyebrow) - try container.encodeIfPresent(headline, forKey: .headline) + try container.encodeModelIfPresent(headline, forKey: .headline) try container.encodeIfPresent(body, forKey: .body) try container.encodeIfPresent(link, forKey: .link) } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index a998b79d..1563c6bc 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -20,3 +20,17 @@ public extension MoleculeModelProtocol { static var categoryCodingKey: String { "moleculeName" } } + +extension KeyedDecodingContainer where Key: CodingKey { + /// Decodes to a registered molecule based on the identifier + public func decodeMoleculeIfPresent(codingKey: KeyedDecodingContainer.Key) throws -> T? { + + guard let model: MoleculeModelProtocol = try decodeModelIfPresent(codingKey: codingKey) else { return nil } + guard let modelT = model as? T else { + let message = "ModelRegistry Error wrong type: \(codingKey.stringValue)" + MVMCoreLoggingHandler.logDebugMessage(withDelegate: message) + throw ModelRegistry.Error.decoderOther(message: message) + } + return modelT + } +} diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 04bc080b..6577b258 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -22,12 +22,15 @@ public extension TemplateProtocol where Self: ViewController { let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() try decoder.add(delegateObject: delegateObjectIVar) - self.templateModel = try decodeTemplate(using: decoder, from: data) - self.model = templateModel as? MVMControllerModelProtocol + templateModel = try decodeTemplate(using: decoder, from: data) + model = templateModel as? MVMControllerModelProtocol + guard var model = model else { return } + model.traverseAndAdd(with: self) + var behaviorHandler = self + behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar) } func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel { return try decoder.decode(TemplateModel.self, from: data) } - } diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index bb8bb104..7c271021 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -29,7 +29,7 @@ import Foundation public var screenHeading: String? public var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? - public var behaviors: [PageBehaviorProtocol]? + public var behaviors: [PageBehaviorModelProtocol]? public var tabBarHidden: Bool = false public var tabBarIndex: Int? diff --git a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift index 64242fc3..78f6f604 100644 --- a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift +++ b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift @@ -9,6 +9,6 @@ import Foundation -public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol, PageBehaviorsTemplateProtocol { +public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol, PageBehaviorHandlerModelProtocol { } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index a2d82952..b841a062 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -8,7 +8,7 @@ import UIKit -@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol, PageProtocol { +@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol, PageProtocol, PageBehaviorHandlerProtocol { //-------------------------------------------------- // MARK: - Properties @@ -34,6 +34,8 @@ import UIKit public var formValidator: FormValidator? + public var behaviors: [PageBehaviorProtocol]? + public var needsUpdateUI = false private var observingForResponses = false private var initialLoadFinished = false @@ -620,6 +622,6 @@ import UIKit //-------------------------------------------------- func executeBehaviors(_ behaviorBlock:(_ behavior:T)->Void) { - model?.behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } + behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } } } diff --git a/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift new file mode 100644 index 00000000..d156d366 --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift @@ -0,0 +1,36 @@ +// +// PageBehaviorHandlerModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol PageBehaviorHandlerModelProtocol { + var behaviors: [PageBehaviorModelProtocol]? { get set } +} + +public extension PageBehaviorHandlerModelProtocol { + + /// Adds the behavior model to the behaviors if possible. + mutating func add(behavior: PageBehaviorModelProtocol) { + var newBehaviors = behaviors ?? [] + guard !behavior.shouldAllowMultipleInstances, + !newBehaviors.contains(where: { $0.behaviorName == behavior.behaviorName + }) else { return } + newBehaviors.append(behavior) + self.behaviors = newBehaviors + } + + /// Traverses all models and adds any required behavior models. + mutating func traverseAndAdd(with page: PageProtocol?) { + PageGetContactBehavior.traverse(with: page, closure: { (model) in + guard let behaviorRequirer = model as? PageBehaviorProtocolRequirer, + var pageModel = page?.pageModel as? PageBehaviorHandlerModelProtocol else { return } + for behavior in behaviorRequirer.getRequiredBehaviors() { + pageModel.add(behavior: behavior) + } + }) + } +} + diff --git a/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift new file mode 100644 index 00000000..b90ac1aa --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift @@ -0,0 +1,30 @@ +// +// PageBehaviorHandlerProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol PageBehaviorHandlerProtocol { + var behaviors: [PageBehaviorProtocol]? { get set } +} + +public extension PageBehaviorHandlerProtocol { + /// Creates the behaviors and sets the variable. + mutating func createBehaviors(for model: PageBehaviorHandlerModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + guard let behaviorModels = model.behaviors else { + behaviors = nil + return + } + var behaviors: [PageBehaviorProtocol] = [] + for behaviorModel in behaviorModels { + guard let handlerType = ModelRegistry.getHandler(behaviorModel) as? PageBehaviorProtocol.Type else { continue } + let behavior = handlerType.init(model: behaviorModel, delegateObject: delegateObject) + behaviors.append(behavior) + } + self.behaviors = behaviors.count > 0 ? behaviors : nil + } +} diff --git a/MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift new file mode 100644 index 00000000..d8502a7e --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift @@ -0,0 +1,35 @@ +// +// PageBehaviorModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol PageBehaviorModelProtocol: ModelProtocol { + + /// The type of rule + var behaviorName: String { get } + + /// If the behavior should allow multiple instances + var shouldAllowMultipleInstances: Bool { get } +} + +public extension PageBehaviorModelProtocol { + + var behaviorName: String { + get { type(of:self).identifier } + } + + static var shouldAllowMultipleInstances: Bool { + get { true } + } + + static var categoryCodingKey: String { + "behaviorName" + } + + static var categoryName: String { + "\(PageBehaviorModelProtocol.self)" + } +} diff --git a/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift new file mode 100644 index 00000000..2a3e9d28 --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift @@ -0,0 +1,34 @@ +// +// PageBehaviorProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 5/8/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol PageBehaviorProtocol: ModelHandlerProtocol { + + /// Initializes the behavior with the model + init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) +} + +public protocol PageVisibilityBehavior: PageBehaviorProtocol { + + func onPageShown() + func onPageHidden() +} + +public protocol PageScrolledBehavior: PageBehaviorProtocol { + + func pageScrolled(scrollView: UIScrollView) +} + +public extension MVMCoreUIDelegateObject { + weak var behaviorTemplateDelegate: (PageBehaviorHandlerProtocol & NSObjectProtocol)? { + get { + return (moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorHandlerProtocol & NSObjectProtocol) + } + } +} diff --git a/MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift b/MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift new file mode 100644 index 00000000..9ca72e1d --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift @@ -0,0 +1,11 @@ +// +// PageBehaviorProtocolRequirer.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol PageBehaviorProtocolRequirer { + func getRequiredBehaviors() -> [PageBehaviorModelProtocol] +} diff --git a/MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift b/MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift deleted file mode 100644 index c43d4ecc..00000000 --- a/MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// PageScrolledClosureBehavior.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 2/11/21. -// Copyright © 2021 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class PageScrolledClosureBehavior: PageScrolledBehavior { - - public static var identifier = "pageScrolledClosureBehavior" - - public var pageScrolledHandler: (_ scrollView: UIScrollView) -> Void - - public init(with onPageScrolledHandler: @escaping (_ scrollView: UIScrollView) -> Void) { - self.pageScrolledHandler = onPageScrolledHandler - } - - // This class is not meant to be decoded and encoded really. - public required init(from decoder: Decoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageScrolledClosureBehavior does not decode.") - } - - public func encode(to encoder: Encoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageScrolledClosureBehavior does not encode.") - } - - public func pageScrolled(scrollView: UIScrollView) { - pageScrolledHandler(scrollView) - } -} diff --git a/MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift b/MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift deleted file mode 100644 index f5ecd82c..00000000 --- a/MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// PageVisibilityClosureBehavior.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 2/11/21. -// Copyright © 2021 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class PageVisibilityClosureBehavior: PageVisibilityBehavior { - - public static var identifier = "pageVisibilityClosureBehavior" - - public var pageShownHandler: () -> Void - public var pageHiddenHandler: () -> Void - - public init(with onPageShownHandler: @escaping () -> Void, onPageHiddenHandler: @escaping () -> Void) { - self.pageShownHandler = onPageShownHandler - self.pageHiddenHandler = onPageHiddenHandler - } - - // This class is not meant to be decoded and encoded really. - public required init(from decoder: Decoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageVisibilityClosureBehavior does not decode.") - } - - public func encode(to encoder: Encoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageVisibilityClosureBehavior does not encode.") - } - - //MARK:- PageVisibilityBehavior - public func onPageShown() { - pageShownHandler() - } - - public func onPageHidden() { - pageHiddenHandler() - } -} diff --git a/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift b/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift index b6ea9f6d..30a5b035 100644 --- a/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift +++ b/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift @@ -6,52 +6,14 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { - +public class ScreenBrightnessModifierBehaviorModel: PageBehaviorModelProtocol { + public var shouldAllowMultipleInstances: Bool = false public static var identifier = "screenBrightnessModifier" - @Clamping(range: 0...1) var screenBrightness: CGFloat - var originalScreenBrightness: CGFloat? - //MARK:- PageVisibilityBehavior - - public func onPageShown() { - changeScreenBrightness() - } - - public func onPageHidden() { - restoreScreenBrightness() - } - - //MARK:- Behavior - - func changeScreenBrightness() { - guard originalScreenBrightness == nil else { return } - originalScreenBrightness = UIScreen.main.brightness - UIScreen.main.brightness = screenBrightness - NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil) - } - - func restoreScreenBrightness() { - guard let originalScreenBrightness = originalScreenBrightness else { return } - UIScreen.main.brightness = originalScreenBrightness - self.originalScreenBrightness = nil - NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil) - } - - @objc func willResignActive() { - restoreScreenBrightness() - NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) - } - - @objc func didBecomeActive() { - NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) - changeScreenBrightness() - } - //MARK:- Codable - + private enum CodingKeys: String, CodingKey { case screenBrightness } @@ -66,3 +28,49 @@ public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { try container.encode(screenBrightness, forKey: .screenBrightness) } } + +public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { + var model: PageBehaviorModelProtocol + + required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.model = model + } + + //MARK:- PageVisibilityBehavior + + public func onPageShown() { + changeScreenBrightness() + } + + public func onPageHidden() { + restoreScreenBrightness() + } + + //MARK:- Behavior + + func changeScreenBrightness() { + guard let model = model as? ScreenBrightnessModifierBehaviorModel, + model.originalScreenBrightness == nil else { return } + model.originalScreenBrightness = UIScreen.main.brightness + UIScreen.main.brightness = model.screenBrightness + NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil) + } + + func restoreScreenBrightness() { + guard let model = model as? ScreenBrightnessModifierBehaviorModel, + let originalScreenBrightness = model.originalScreenBrightness else { return } + UIScreen.main.brightness = originalScreenBrightness + model.originalScreenBrightness = nil + NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil) + } + + @objc func willResignActive() { + restoreScreenBrightness() + NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) + } + + @objc func didBecomeActive() { + NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) + changeScreenBrightness() + } +} From bc39332b17ff8445b3bac29aa5bc43b56da3cc10 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 15:20:58 -0400 Subject: [PATCH 09/20] get contact behavior temp --- MVMCoreUI.xcodeproj/project.pbxproj | 66 +++++++++++---- MVMCoreUI/Behaviors/GetContactBehavior.swift | 88 ++++++++++++++++++++ 2 files changed, 139 insertions(+), 15 deletions(-) create mode 100644 MVMCoreUI/Behaviors/GetContactBehavior.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9ba02cb8..4daf9aa5 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -123,7 +123,7 @@ 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; }; - 27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehavior.swift */; }; + 27F973532466074500CAB5C5 /* PageBehaviorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehaviorProtocol.swift */; }; 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; @@ -346,13 +346,20 @@ D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; }; D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; }; D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; + D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */; }; + D23A8FEE26122F7D007E14CE /* VisibleBehaviorForVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */; }; + D23A8FF126122FAE007E14CE /* ScrollBehaviorForVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF026122FAE007E14CE /* ScrollBehaviorForVideoModel.swift */; }; + D23A8FF426122FD8007E14CE /* ScrollBehaviorForVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF326122FD8007E14CE /* ScrollBehaviorForVideo.swift */; }; + D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */; }; + D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */; }; + D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */; }; + D23A9004261234CE007E14CE /* PageBehaviorHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */; }; + D23A900926125FFB007E14CE /* GetContactBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A900826125FFB007E14CE /* GetContactBehavior.swift */; }; D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */; }; D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */; }; D23EA800247EBD6C00D60C34 /* LabelBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */; }; D23EA802247EBED400D60C34 /* ImageBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA801247EBED400D60C34 /* ImageBarButtonItem.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; - D24918F625D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24918F525D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift */; }; - D24918FA25D5ADBB00CAB4B1 /* PageScrolledClosureBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24918F925D5ADBA00CAB4B1 /* PageScrolledClosureBehavior.swift */; }; D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */; }; D2509ED62472EE2F001BFB9D /* NavigationImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED52472EE2F001BFB9D /* NavigationImageButtonModel.swift */; }; D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106423D0CEA700764D80 /* StackModel.swift */; }; @@ -679,7 +686,7 @@ 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = ""; }; - 27F973522466074500CAB5C5 /* PageBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehavior.swift; sourceTree = ""; }; + 27F973522466074500CAB5C5 /* PageBehaviorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorProtocol.swift; sourceTree = ""; }; 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenBrightnessModifierBehavior.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; @@ -902,13 +909,20 @@ D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = ""; }; D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = ""; }; D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; + D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibleBehaviorForVideoModel.swift; sourceTree = ""; }; + D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibleBehaviorForVideo.swift; sourceTree = ""; }; + D23A8FF026122FAE007E14CE /* ScrollBehaviorForVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollBehaviorForVideoModel.swift; sourceTree = ""; }; + D23A8FF326122FD8007E14CE /* ScrollBehaviorForVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollBehaviorForVideo.swift; sourceTree = ""; }; + D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorProtocolRequirer.swift; sourceTree = ""; }; + D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorModelProtocol.swift; sourceTree = ""; }; + D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerModelProtocol.swift; sourceTree = ""; }; + D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerProtocol.swift; sourceTree = ""; }; + D23A900826125FFB007E14CE /* GetContactBehavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetContactBehavior.swift; sourceTree = ""; }; D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemProtocol.swift; sourceTree = ""; }; D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationLabelButtonModel.swift; sourceTree = ""; }; D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelBarButtonItem.swift; sourceTree = ""; }; D23EA801247EBED400D60C34 /* ImageBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageBarButtonItem.swift; sourceTree = ""; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; - D24918F525D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageVisibilityClosureBehavior.swift; sourceTree = ""; }; - D24918F925D5ADBA00CAB4B1 /* PageScrolledClosureBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageScrolledClosureBehavior.swift; sourceTree = ""; }; D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D2509ED52472EE2F001BFB9D /* NavigationImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationImageButtonModel.swift; sourceTree = ""; }; D253BB9B245874F8002DE544 /* BGImageMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMolecule.swift; sourceTree = ""; }; @@ -1281,10 +1295,13 @@ 27F973512466071600CAB5C5 /* Behaviors */ = { isa = PBXGroup; children = ( - 27F973522466074500CAB5C5 /* PageBehavior.swift */, + D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */, + D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */, + D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */, + D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */, + 27F973522466074500CAB5C5 /* PageBehaviorProtocol.swift */, 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */, - D24918F525D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift */, - D24918F925D5ADBA00CAB4B1 /* PageScrolledClosureBehavior.swift */, + D23A900826125FFB007E14CE /* GetContactBehavior.swift */, ); path = Behaviors; sourceTree = ""; @@ -1703,6 +1720,20 @@ path = TwoColumn; sourceTree = ""; }; + D23A8FE926122F41007E14CE /* Video */ = { + isa = PBXGroup; + children = ( + D29C559525C099630082E7D6 /* VideoDataManager.swift */, + D29C559225C0992D0082E7D6 /* VideoModel.swift */, + D29C558F25C095210082E7D6 /* Video.swift */, + D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */, + D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */, + D23A8FF026122FAE007E14CE /* ScrollBehaviorForVideoModel.swift */, + D23A8FF326122FD8007E14CE /* ScrollBehaviorForVideo.swift */, + ); + path = Video; + sourceTree = ""; + }; D23EA7FC247EBB7500D60C34 /* Buttons */ = { isa = PBXGroup; children = ( @@ -2050,6 +2081,7 @@ D29DF17D21E69E26003B2FB9 /* Views */ = { isa = PBXGroup; children = ( + D23A8FE926122F41007E14CE /* Video */, 0A9D09162433796500D2E6C0 /* CarouselIndicator */, 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */, 01509D922327ECFB00EF99AA /* ProgressBar.swift */, @@ -2082,9 +2114,6 @@ AA37CBD42519072F0027344C /* Stars.swift */, AA07EA902510A442009A2AE3 /* StarModel.swift */, AA07EA922510A451009A2AE3 /* Star.swift */, - D29C559525C099630082E7D6 /* VideoDataManager.swift */, - D29C559225C0992D0082E7D6 /* VideoModel.swift */, - D29C558F25C095210082E7D6 /* Video.swift */, ); path = Views; sourceTree = ""; @@ -2573,6 +2602,7 @@ AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, + D23A900926125FFB007E14CE /* GetContactBehavior.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, @@ -2584,11 +2614,13 @@ D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */, + D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */, 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */, + D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */, BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */, D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */, AA07EA932510A451009A2AE3 /* Star.swift in Sources */, @@ -2606,6 +2638,7 @@ D2ED27EC254B0CE700A1C293 /* UIAlertControllerStyle+Extension.swift in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, + D23A8FEE26122F7D007E14CE /* VisibleBehaviorForVideo.swift in Sources */, 0A9D091F2433796500D2E6C0 /* NumericIndicatorView.swift in Sources */, D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, @@ -2627,10 +2660,12 @@ AAC23FAF24D92A1E009208DF /* ListThreeColumnSpeedTest.swift in Sources */, 0A0FEC7425D42A5E00AF2548 /* BaseItemPickerEntryField.swift in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, + D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */, D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, D2ED27ED254B0CE700A1C293 /* ActionPopupModel.swift in Sources */, 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */, 943820842432382400B43AF3 /* WebView.swift in Sources */, + D23A8FF126122FAE007E14CE /* ScrollBehaviorForVideoModel.swift in Sources */, 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */, D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, 0A25209624645AFD000FA9F6 /* TextViewEntryField.swift in Sources */, @@ -2730,6 +2765,7 @@ 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */, D2874024249BA6F300BE950A /* MVMCoreUISplitViewController+Extension.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, + D23A8FF426122FD8007E14CE /* ScrollBehaviorForVideo.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */, D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */, @@ -2749,7 +2785,6 @@ 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */, 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */, 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */, - D24918F625D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift in Sources */, D20492A624329CE200A5EED6 /* LoadImageView.swift in Sources */, 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */, D274CA332236A78900B01B62 /* FooterView.swift in Sources */, @@ -2835,7 +2870,6 @@ 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, - D24918FA25D5ADBB00CAB4B1 /* PageScrolledClosureBehavior.swift in Sources */, 0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */, D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */, 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, @@ -2901,7 +2935,7 @@ D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, 0AB000BC24BF64A50090C5E7 /* ModalStackPageTemplateModel.swift in Sources */, - 27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */, + 27F973532466074500CAB5C5 /* PageBehaviorProtocol.swift in Sources */, 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */, D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */, D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, @@ -2910,6 +2944,7 @@ 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, + D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */, 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */, 0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */, @@ -2971,6 +3006,7 @@ 011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */, AA0A257A24766CA200862F64 /* ListLeftVariableIconWithRightCaretBodyText.swift in Sources */, 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */, + D23A9004261234CE007E14CE /* PageBehaviorHandlerProtocol.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */, 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */, diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift new file mode 100644 index 00000000..d92d2761 --- /dev/null +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -0,0 +1,88 @@ +// +// GetContactBehavior.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/22/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation +import Contacts + +public class SwapMDNWithContactNameLabelModel: LabelModel, PageGetContactBehaviorConsumerProtocol, PageBehaviorProtocolRequirer { + public class override var identifier: String { "swapMDNWithContactNameLabel" } + + public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { + return [PageGetContactBehaviorModel()] + } + + public func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])? { + guard let mdn = MVMCoreUIUtility.removeMdnFormat(text) else { return nil } + return (CNContact.predicateForContacts(matching: CNPhoneNumber(stringValue: mdn)), [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) + } + + public func consume(contacts: [CNContact]) { + guard let contact = contacts.first else { return } + let nameArray: [String?] = [contact.givenName, contact.middleName, contact.familyName] + let name = nameArray.compactMap { $0 }.joined(separator: " ") + guard name.count > 0 else { return } + text = name + } +} + +public protocol PageGetContactBehaviorConsumerProtocol { + func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])? + func consume(contacts: [CNContact]) +} + +public class PageGetContactBehaviorModel: PageBehaviorModelProtocol { + public class var identifier: String { "pageGetContactBehavior" } + public var shouldAllowMultipleInstances: Bool { false } +} + +public class PageGetContactBehavior: PageVisibilityBehavior { + var delegate: MVMCoreUIDelegateObject? + + public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.delegate = delegateObject + } + + public static func traverse(with page: PageProtocol?, closure: (MoleculeModelProtocol) -> Void) { + // Iterate models and provide contact + guard let template = page as? MoleculeListTemplate, + let models = template.templateModel?.molecules else { return } + for model in models { + if let model = model as? ListLeftVariableIconAllTextLinksModel, + let labelModel = model.eyebrowHeadlineBodyLink.headline { + closure(labelModel) + } else { + closure(model) + } + } + } + + public func onPageShown() { + // Ask for permission + CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in + guard access, + error == nil else { return } + // Iterate models and provide contact + let page = self?.delegate?.moleculeDelegate as? PageProtocol + let store = CNContactStore() + PageGetContactBehavior.traverse(with: page) { (model) in + guard let model = model as? PageGetContactBehaviorConsumerProtocol, + let parameters = model.getMatchParameters(), + let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } + model.consume(contacts: contacts) + } + + // Tell template to update + MVMCoreDispatchUtility.performBlock(onMainThread: { + // TODO: move to protocol function instead + (page as? ViewController)?.handleNewData() + }) + } + } + + public func onPageHidden() {} +} From f0b5e748398ee5966bd759d8c53aba741f960532 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 15:32:15 -0400 Subject: [PATCH 10/20] Change file name --- MVMCoreUI/Behaviors/PageBehavior.swift | 63 -------------------------- 1 file changed, 63 deletions(-) delete mode 100644 MVMCoreUI/Behaviors/PageBehavior.swift diff --git a/MVMCoreUI/Behaviors/PageBehavior.swift b/MVMCoreUI/Behaviors/PageBehavior.swift deleted file mode 100644 index aaf915a1..00000000 --- a/MVMCoreUI/Behaviors/PageBehavior.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// PageBehaviors.swift -// MVMCoreUI -// -// Created by Kyle on 5/8/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public protocol PageBehaviorProtocol: ModelProtocol { - - /// The type of rule - var behaviorName: String { get } -} - -public extension PageBehaviorProtocol { - - var behaviorName: String { - get { Self.identifier } - } - - static var categoryCodingKey: String { - "behaviorName" - } - - static var categoryName: String { - "\(PageBehaviorProtocol.self)" - } -} - -public protocol PageVisibilityBehavior: PageBehaviorProtocol { - - func onPageShown() - func onPageHidden() -} - -public protocol PageScrolledBehavior: PageBehaviorProtocol { - - func pageScrolled(scrollView: UIScrollView) -} - -public protocol PageBehaviorsTemplateProtocol { - - var behaviors: [PageBehaviorProtocol]? { get set } - -} - -public extension PageBehaviorsTemplateProtocol { - mutating func add(behavior: PageBehaviorProtocol) { - var newBehaviors = behaviors ?? [] - newBehaviors.append(behavior) - self.behaviors = newBehaviors - } -} - -public extension MVMCoreUIDelegateObject { - weak var behaviorTemplateDelegate: (PageBehaviorsTemplateProtocol & NSObjectProtocol)? { - get { - return (moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorsTemplateProtocol & NSObjectProtocol) - } - } -} From cb2c42793accacd8474aeb18b20463849cedc238 Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Mon, 29 Mar 2021 16:52:48 -0400 Subject: [PATCH 11/20] signature fix. template traversal conformance. --- .../ModelProtocols/MoleculeModelProtocol.swift | 4 ++-- .../ModelProtocols/TemplateModelProtocol.swift | 10 +++++++++- MVMCoreUI/BaseControllers/ViewController.swift | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index 4b432c2e..a24422e0 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -43,9 +43,9 @@ public extension Array where Element == MoleculeModelProtocol { } } - func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, callback: (Int, MoleculeModelProtocol)->Void) { + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) { forEach { (molecule) in - molecule.depthFirstTraverse(options: options, depth: depth, onVisit: callback) + molecule.depthFirstTraverse(options: options, depth: depth, onVisit: onVisit) } } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift index 31e5a131..1f9db75b 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation -public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol { +public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, MoleculeTreeTraversalProtocol { var template: String { get } var rootMolecules: [MoleculeModelProtocol] { get } } @@ -27,4 +27,12 @@ public extension TemplateModelProtocol { static var categoryName: String { return "\(TemplateModelProtocol.self)" } + + func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result { + return rootMolecules.reduceDepthFirstTraverse(options: options, depth: depth, initialResult: initialResult, nextPartialResult: nextPartialResult) + } + + func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol) -> Void) { + return rootMolecules.depthFirstTraverse(options: options, depth: depth, onVisit: onVisit) + } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 701d0fb2..fea06227 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -335,12 +335,12 @@ import UIKit initialLoadFinished = true initialLoad() } - - print("total molecules in tree: \(model?.rootMolecules.countMolecules() ?? 0)") + + print("total molecules in tree: \(model?.countMolecules() ?? 0)") model?.rootMolecules.printMolecules() - let allVideoMolecules:[BGVideoImageMoleculeModel] = model?.rootMolecules.allMoleculesOfType() ?? [] + let allVideoMolecules:[BGVideoImageMoleculeModel] = model?.allMoleculesOfType() ?? [] print("video molecules: \(allVideoMolecules.count)") handleNewDataAndUpdateUI() From 5a0399bad95db7f4b152c05978af05a65d1a9e1f Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 16:59:26 -0400 Subject: [PATCH 12/20] enable parents, for testing. Switch to KyleTraverse (tm) --- ...istLeftVariableIconAllTextLinksModel.swift | 6 ++++- .../EyebrowHeadlineBodyLinkModel.swift | 7 +++++- .../Atomic/Protocols/TemplateProtocol.swift | 18 +++++++++++-- MVMCoreUI/Behaviors/GetContactBehavior.swift | 25 +++++-------------- .../PageBehaviorHandlerModelProtocol.swift | 11 -------- 5 files changed, 33 insertions(+), 34 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift index 8581deb1..c0700d5a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift @@ -7,7 +7,7 @@ // -public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModelProtocol { +public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -16,6 +16,10 @@ public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModel public var image: ImageViewModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + public var children: [MoleculeModelProtocol] { + return [image] + eyebrowHeadlineBodyLink.children + } + //-------------------------------------------------- // MARK: - Method //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 2174514d..17aa4ea8 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -7,7 +7,7 @@ // -public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { +public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -20,6 +20,11 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { public var body: LabelModel? public var link: LinkModel? + public var children: [MoleculeModelProtocol] { + let molecules: [MoleculeModelProtocol?] = [eyebrow, headline, body, link] + return molecules.compactMap{ $0 } + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 6577b258..3aadd665 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -24,8 +24,8 @@ public extension TemplateProtocol where Self: ViewController { try decoder.add(delegateObject: delegateObjectIVar) templateModel = try decodeTemplate(using: decoder, from: data) model = templateModel as? MVMControllerModelProtocol - guard var model = model else { return } - model.traverseAndAdd(with: self) + guard let model = model else { return } + traverseAndAddRequiredBehaviors() var behaviorHandler = self behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar) } @@ -33,4 +33,18 @@ public extension TemplateProtocol where Self: ViewController { func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel { return try decoder.decode(TemplateModel.self, from: data) } + + /// Traverses all models and adds any required behavior models. + func traverseAndAddRequiredBehaviors() { + guard var model = model else { return } + let behaviorModels: [PageBehaviorModelProtocol] = model.rootMolecules.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in + if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer { + return accumulator + behaviorRequirer.getRequiredBehaviors() + } + return accumulator + } + for behavior in behaviorModels { + model.add(behavior: behavior) + } + } } diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index d92d2761..b83553db 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -46,34 +46,21 @@ public class PageGetContactBehavior: PageVisibilityBehavior { public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { self.delegate = delegateObject } - - public static func traverse(with page: PageProtocol?, closure: (MoleculeModelProtocol) -> Void) { - // Iterate models and provide contact - guard let template = page as? MoleculeListTemplate, - let models = template.templateModel?.molecules else { return } - for model in models { - if let model = model as? ListLeftVariableIconAllTextLinksModel, - let labelModel = model.eyebrowHeadlineBodyLink.headline { - closure(labelModel) - } else { - closure(model) - } - } - } public func onPageShown() { // Ask for permission CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in guard access, - error == nil else { return } + error == nil, + let model = (self?.delegate?.moleculeDelegate as? PageProtocol)?.pageModel as? TemplateModelProtocol else { return } // Iterate models and provide contact let page = self?.delegate?.moleculeDelegate as? PageProtocol let store = CNContactStore() - PageGetContactBehavior.traverse(with: page) { (model) in - guard let model = model as? PageGetContactBehaviorConsumerProtocol, - let parameters = model.getMatchParameters(), + let consumers: [PageGetContactBehaviorConsumerProtocol] = model.rootMolecules.allMoleculesOfType() + for consumer in consumers { + guard let parameters = consumer.getMatchParameters(), let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } - model.consume(contacts: contacts) + consumer.consume(contacts: contacts) } // Tell template to update diff --git a/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift index d156d366..17f1b85e 100644 --- a/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift +++ b/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift @@ -21,16 +21,5 @@ public extension PageBehaviorHandlerModelProtocol { newBehaviors.append(behavior) self.behaviors = newBehaviors } - - /// Traverses all models and adds any required behavior models. - mutating func traverseAndAdd(with page: PageProtocol?) { - PageGetContactBehavior.traverse(with: page, closure: { (model) in - guard let behaviorRequirer = model as? PageBehaviorProtocolRequirer, - var pageModel = page?.pageModel as? PageBehaviorHandlerModelProtocol else { return } - for behavior in behaviorRequirer.getRequiredBehaviors() { - pageModel.add(behavior: behavior) - } - }) - } } From 4a5f35820cfaa9b1515730ae70f4773cfac5f5f8 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 17:03:35 -0400 Subject: [PATCH 13/20] kyle enhancements --- .../EyebrowHeadlineBodyLinkModel.swift | 3 +-- MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift | 2 +- MVMCoreUI/Behaviors/GetContactBehavior.swift | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 17aa4ea8..ec646f86 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -21,8 +21,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule public var link: LinkModel? public var children: [MoleculeModelProtocol] { - let molecules: [MoleculeModelProtocol?] = [eyebrow, headline, body, link] - return molecules.compactMap{ $0 } + [eyebrow, headline, body, link].compactMap { (molecule: MoleculeModelProtocol?) in molecule } } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 3aadd665..9a7e9e33 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -37,7 +37,7 @@ public extension TemplateProtocol where Self: ViewController { /// Traverses all models and adds any required behavior models. func traverseAndAddRequiredBehaviors() { guard var model = model else { return } - let behaviorModels: [PageBehaviorModelProtocol] = model.rootMolecules.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in + let behaviorModels: [PageBehaviorModelProtocol] = model.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer { return accumulator + behaviorRequirer.getRequiredBehaviors() } diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index b83553db..71eb7180 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -56,7 +56,7 @@ public class PageGetContactBehavior: PageVisibilityBehavior { // Iterate models and provide contact let page = self?.delegate?.moleculeDelegate as? PageProtocol let store = CNContactStore() - let consumers: [PageGetContactBehaviorConsumerProtocol] = model.rootMolecules.allMoleculesOfType() + let consumers: [PageGetContactBehaviorConsumerProtocol] = model.allMoleculesOfType() for consumer in consumers { guard let parameters = consumer.getMatchParameters(), let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } From 7a689ea7ebccdc84cc8b1231e10721d80b384d55 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Mar 2021 17:19:23 -0400 Subject: [PATCH 14/20] one video behavior --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ------ .../Views/Video/ScrollBehaviorForVideo.swift | 25 ------------------- .../Video/ScrollBehaviorForVideoModel.swift | 20 --------------- .../Views/Video/VisibleBehaviorForVideo.swift | 10 +++++++- 4 files changed, 9 insertions(+), 54 deletions(-) delete mode 100644 MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift delete mode 100644 MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 52d154d6..d16065f6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -350,8 +350,6 @@ D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */; }; D23A8FEE26122F7D007E14CE /* VisibleBehaviorForVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */; }; - D23A8FF126122FAE007E14CE /* ScrollBehaviorForVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF026122FAE007E14CE /* ScrollBehaviorForVideoModel.swift */; }; - D23A8FF426122FD8007E14CE /* ScrollBehaviorForVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF326122FD8007E14CE /* ScrollBehaviorForVideo.swift */; }; D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */; }; D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */; }; D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */; }; @@ -915,8 +913,6 @@ D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibleBehaviorForVideoModel.swift; sourceTree = ""; }; D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibleBehaviorForVideo.swift; sourceTree = ""; }; - D23A8FF026122FAE007E14CE /* ScrollBehaviorForVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollBehaviorForVideoModel.swift; sourceTree = ""; }; - D23A8FF326122FD8007E14CE /* ScrollBehaviorForVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollBehaviorForVideo.swift; sourceTree = ""; }; D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorProtocolRequirer.swift; sourceTree = ""; }; D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorModelProtocol.swift; sourceTree = ""; }; D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerModelProtocol.swift; sourceTree = ""; }; @@ -1733,8 +1729,6 @@ D29C558F25C095210082E7D6 /* Video.swift */, D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */, D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */, - D23A8FF026122FAE007E14CE /* ScrollBehaviorForVideoModel.swift */, - D23A8FF326122FD8007E14CE /* ScrollBehaviorForVideo.swift */, ); path = Video; sourceTree = ""; @@ -2671,7 +2665,6 @@ D2ED27ED254B0CE700A1C293 /* ActionPopupModel.swift in Sources */, 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */, 943820842432382400B43AF3 /* WebView.swift in Sources */, - D23A8FF126122FAE007E14CE /* ScrollBehaviorForVideoModel.swift in Sources */, 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */, D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, 0A25209624645AFD000FA9F6 /* TextViewEntryField.swift in Sources */, @@ -2771,7 +2764,6 @@ 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */, D2874024249BA6F300BE950A /* MVMCoreUISplitViewController+Extension.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, - D23A8FF426122FD8007E14CE /* ScrollBehaviorForVideo.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */, D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift deleted file mode 100644 index 77487305..00000000 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideo.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ScrollBehaviorForVideo.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 3/29/21. -// Copyright © 2021 Verizon Wireless. All rights reserved. -// - -import Foundation - -open class ScrollBehaviorForVideo: PageScrolledBehavior { - var model: PageBehaviorModelProtocol - - required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { - self.model = model - } - - public func pageScrolled(scrollView: UIScrollView) { - // If visible to not visible, pause video. - // If not visible to visible, unpause if needed, add visible behavior - guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, - let view = model.view else { return } - model.halted = !view.isVisible(in: scrollView) - } -} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift deleted file mode 100644 index 6e460c22..00000000 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/ScrollBehaviorForVideoModel.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// ScrollBehaviorForVideoModel.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 3/29/21. -// Copyright © 2021 Verizon Wireless. All rights reserved. -// - -import Foundation - -open class ScrollBehaviorForVideoModel: PageBehaviorModelProtocol { - - public static var identifier: String = "visibleBehaviorForVideoModel" - public var shouldAllowMultipleInstances: Bool = true - public weak var videoModel: VideoModel? - - init(with videoModel: VideoModel) { - self.videoModel = videoModel - } -} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift index 022585fd..73e1714b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift @@ -8,7 +8,7 @@ import Foundation -open class VisibleBehaviorForVideo: PageVisibilityBehavior { +open class VisibleBehaviorForVideo: PageVisibilityBehavior, PageScrolledBehavior { var model: PageBehaviorModelProtocol required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { @@ -25,4 +25,12 @@ open class VisibleBehaviorForVideo: PageVisibilityBehavior { public func onPageHidden() { (model as? VisibleBehaviorForVideoModel)?.videoModel?.halted = true } + + public func pageScrolled(scrollView: UIScrollView) { + // If visible to not visible, pause video. + // If not visible to visible, unpause if needed, add visible behavior + guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, + let view = model.view else { return } + model.halted = !view.isVisible(in: scrollView) + } } From 5b7d036c8b5a026cd9ced7b8f77b861b1c854a55 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 30 Mar 2021 10:30:35 -0400 Subject: [PATCH 15/20] review comments --- MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift | 2 +- .../Atoms/Views/Video/VisibleBehaviorForVideo.swift | 6 +++--- .../ListLeftVariableIconAllTextLinksModel.swift | 2 +- MVMCoreUI/BaseControllers/ScrollingViewController.swift | 4 ++-- MVMCoreUI/BaseControllers/ViewController.swift | 8 ++++---- MVMCoreUI/Behaviors/GetContactBehavior.swift | 6 +++--- MVMCoreUI/Behaviors/PageBehaviorProtocol.swift | 6 +++--- .../Behaviors/ScreenBrightnessModifierBehavior.swift | 4 ++-- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift index 472ab3de..7c348760 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift @@ -80,7 +80,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { } public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { - return [VisibleBehaviorForVideoModel(with: self), ScrollBehaviorForVideoModel(with: self)] + return [VisibleBehaviorForVideoModel(with: self)] } open func addVisibilityHalting(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift index 73e1714b..4f01e375 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift @@ -15,18 +15,18 @@ open class VisibleBehaviorForVideo: PageVisibilityBehavior, PageScrolledBehavior self.model = model } - public func onPageShown() { + public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, let view = model.view, view.isVisibleInDelegate() else { return } model.halted = false } - public func onPageHidden() { + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) { (model as? VisibleBehaviorForVideoModel)?.videoModel?.halted = true } - public func pageScrolled(scrollView: UIScrollView) { + public func pageScrolled(scrollView: UIScrollView, _ delegateObject: MVMCoreUIDelegateObject?) { // If visible to not visible, pause video. // If not visible to visible, unpause if needed, add visible behavior guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift index c0700d5a..46de07fa 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift @@ -17,7 +17,7 @@ public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel public var children: [MoleculeModelProtocol] { - return [image] + eyebrowHeadlineBodyLink.children + return [image, eyebrowHeadlineBodyLink] } //-------------------------------------------------- diff --git a/MVMCoreUI/BaseControllers/ScrollingViewController.swift b/MVMCoreUI/BaseControllers/ScrollingViewController.swift index 19c9d001..4fd23be2 100644 --- a/MVMCoreUI/BaseControllers/ScrollingViewController.swift +++ b/MVMCoreUI/BaseControllers/ScrollingViewController.swift @@ -74,8 +74,8 @@ open class ScrollingViewController: ViewController { } open func scrollViewDidScroll(_ scrollView: UIScrollView) { - executeBehaviors { (behavior: PageScrolledBehavior) in - behavior.pageScrolled(scrollView: scrollView) + executeBehaviors { [weak self] (behavior: PageScrolledBehavior) in + behavior.pageScrolled(scrollView: scrollView, self?.delegateObjectIVar) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 84394a1a..bc79934c 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -389,16 +389,16 @@ import UIKit pageShown() } - executeBehaviors { (behavior: PageVisibilityBehavior) in - behavior.onPageShown() + executeBehaviors { [weak self] (behavior: PageVisibilityBehavior) in + behavior.onPageShown(self?.delegateObjectIVar) } } open override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - executeBehaviors { (behavior: PageVisibilityBehavior) in - behavior.onPageHidden() + executeBehaviors { [weak self] (behavior: PageVisibilityBehavior) in + behavior.onPageHidden(self?.delegateObjectIVar) } } diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index 71eb7180..40c61b5c 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -46,8 +46,8 @@ public class PageGetContactBehavior: PageVisibilityBehavior { public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { self.delegate = delegateObject } - - public func onPageShown() { + + public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { // Ask for permission CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in guard access, @@ -71,5 +71,5 @@ public class PageGetContactBehavior: PageVisibilityBehavior { } } - public func onPageHidden() {} + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {} } diff --git a/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift index 2a3e9d28..6085188c 100644 --- a/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift +++ b/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift @@ -16,13 +16,13 @@ public protocol PageBehaviorProtocol: ModelHandlerProtocol { public protocol PageVisibilityBehavior: PageBehaviorProtocol { - func onPageShown() - func onPageHidden() + func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) + func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) } public protocol PageScrolledBehavior: PageBehaviorProtocol { - func pageScrolled(scrollView: UIScrollView) + func pageScrolled(scrollView: UIScrollView,_ delegateObject: MVMCoreUIDelegateObject?) } public extension MVMCoreUIDelegateObject { diff --git a/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift b/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift index 30a5b035..59d80211 100644 --- a/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift +++ b/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift @@ -38,11 +38,11 @@ public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { //MARK:- PageVisibilityBehavior - public func onPageShown() { + public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { changeScreenBrightness() } - public func onPageHidden() { + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) { restoreScreenBrightness() } From b8051e42c56a57f2db7cab7d8745b47074461dd2 Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Tue, 30 Mar 2021 11:45:23 -0400 Subject: [PATCH 16/20] remove test statements --- MVMCoreUI/BaseControllers/ViewController.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index fea06227..a2d82952 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -335,13 +335,6 @@ import UIKit initialLoadFinished = true initialLoad() } - - print("total molecules in tree: \(model?.countMolecules() ?? 0)") - - model?.rootMolecules.printMolecules() - - let allVideoMolecules:[BGVideoImageMoleculeModel] = model?.allMoleculesOfType() ?? [] - print("video molecules: \(allVideoMolecules.count)") handleNewDataAndUpdateUI() } From 9dcd7afbacfc852bcd2be019d422ef4d344f0dcd Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 30 Mar 2021 14:41:22 -0400 Subject: [PATCH 17/20] move swap label to mf --- .../Atomic/Atoms/Views/Label/LabelModel.swift | 4 ++-- .../Atomic/Atoms/Views/Video/VideoModel.swift | 2 +- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 - MVMCoreUI/Behaviors/GetContactBehavior.swift | 23 ++----------------- 4 files changed, 5 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift index d38a90fd..fbbc9e03 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift @@ -7,12 +7,12 @@ // -@objcMembers public class LabelModel: MoleculeModelProtocol { +@objcMembers open class LabelModel: MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public class var identifier: String { "label" } + open class var identifier: String { "label" } public var backgroundColor: Color? public var text: String public var accessibilityText: String? diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift index 472ab3de..7c348760 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift @@ -80,7 +80,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { } public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { - return [VisibleBehaviorForVideoModel(with: self), ScrollBehaviorForVideoModel(with: self)] + return [VisibleBehaviorForVideoModel(with: self)] } open func addVisibilityHalting(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 13683ba3..539ed2ba 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -264,7 +264,6 @@ import Foundation // MARK:- Behaviors try? ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self) try? ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Label.self, viewModelClass: SwapMDNWithContactNameLabelModel.self) } /// Convenience function to get required modules for a give model diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index 71eb7180..bc3247c7 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -9,27 +9,6 @@ import Foundation import Contacts -public class SwapMDNWithContactNameLabelModel: LabelModel, PageGetContactBehaviorConsumerProtocol, PageBehaviorProtocolRequirer { - public class override var identifier: String { "swapMDNWithContactNameLabel" } - - public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { - return [PageGetContactBehaviorModel()] - } - - public func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])? { - guard let mdn = MVMCoreUIUtility.removeMdnFormat(text) else { return nil } - return (CNContact.predicateForContacts(matching: CNPhoneNumber(stringValue: mdn)), [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) - } - - public func consume(contacts: [CNContact]) { - guard let contact = contacts.first else { return } - let nameArray: [String?] = [contact.givenName, contact.middleName, contact.familyName] - let name = nameArray.compactMap { $0 }.joined(separator: " ") - guard name.count > 0 else { return } - text = name - } -} - public protocol PageGetContactBehaviorConsumerProtocol { func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])? func consume(contacts: [CNContact]) @@ -38,6 +17,8 @@ public protocol PageGetContactBehaviorConsumerProtocol { public class PageGetContactBehaviorModel: PageBehaviorModelProtocol { public class var identifier: String { "pageGetContactBehavior" } public var shouldAllowMultipleInstances: Bool { false } + + public init() {} } public class PageGetContactBehavior: PageVisibilityBehavior { From 31ccb1ecd229438045e74c4d7c044fc96b1f154a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 31 Mar 2021 10:40:23 -0400 Subject: [PATCH 18/20] unify the many registries and mappers --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 287 ------------------ .../MoleculeSectionFooter.swift | 2 +- .../MoleculeSectionHeader.swift | 2 +- .../Items/MoleculeCollectionViewCell.swift | 2 +- .../Items/MoleculeTableViewCell.swift | 2 +- .../LeftRightViews/CornerLabels.swift | 2 +- .../OtherContainers/ModuleMolecule.swift | 6 +- .../OtherContainers/MoleculeContainer.swift | 8 +- .../StringAndMoleculeStack.swift | 2 +- .../Atomic/Organisms/Carousel/Carousel.swift | 4 +- .../Atomic/Organisms/MoleculeStackView.swift | 2 +- MVMCoreUI/Atomic/Organisms/Stack.swift | 6 +- .../Protocols/MoleculeViewProtocol.swift | 33 ++ .../Atomic/Templates/CollectionTemplate.swift | 12 +- .../Templates/MoleculeListTemplate.swift | 12 +- .../Templates/MoleculeStackTemplate.swift | 10 +- .../Atomic/Templates/ThreeLayerTemplate.swift | 6 +- MVMCoreUI/Behaviors/GetContactBehavior.swift | 4 +- .../Containers/NavigationController.swift | 2 +- .../OtherHandlers/CoreUIModelMapping.swift | 247 +++++++++++++++ MVMCoreUI/OtherHandlers/CoreUIObject.swift | 5 +- .../MVMCoreUITopAlertView+Extension.swift | 6 +- 23 files changed, 330 insertions(+), 340 deletions(-) delete mode 100644 MVMCoreUI/Atomic/MoleculeObjectMapping.swift create mode 100644 MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d16065f6..1394ec88 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -53,7 +53,6 @@ 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */; }; 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */; }; 017BEB7B236763000024EF95 /* LineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7A236763000024EF95 /* LineModel.swift */; }; - 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */; }; 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C851D223CF9E740021F976 /* LabelToggleModel.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; }; @@ -355,6 +354,7 @@ D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */; }; D23A9004261234CE007E14CE /* PageBehaviorHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */; }; D23A900926125FFB007E14CE /* GetContactBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A900826125FFB007E14CE /* GetContactBehavior.swift */; }; + D23A90682614B0B4007E14CE /* CoreUIModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A90672614B0B4007E14CE /* CoreUIModelMapping.swift */; }; D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */; }; D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */; }; D23EA800247EBD6C00D60C34 /* LabelBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */; }; @@ -614,7 +614,6 @@ 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = ""; }; 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeViewProtocol.swift; sourceTree = ""; }; 017BEB7A236763000024EF95 /* LineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineModel.swift; sourceTree = ""; }; - 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeObjectMapping.swift; sourceTree = ""; }; 01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = ""; }; 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeModelProtocol.swift; sourceTree = ""; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; @@ -918,6 +917,7 @@ D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerModelProtocol.swift; sourceTree = ""; }; D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerProtocol.swift; sourceTree = ""; }; D23A900826125FFB007E14CE /* GetContactBehavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetContactBehavior.swift; sourceTree = ""; }; + D23A90672614B0B4007E14CE /* CoreUIModelMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIModelMapping.swift; sourceTree = ""; }; D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemProtocol.swift; sourceTree = ""; }; D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationLabelButtonModel.swift; sourceTree = ""; }; D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelBarButtonItem.swift; sourceTree = ""; }; @@ -2171,6 +2171,7 @@ D2ED2817254B112900A1C293 /* MVMCoreUIActionDelegateProtocol.h */, D2ED281B254B119D00A1C293 /* MVMCoreUIActionHandler.h */, D2ED281C254B119D00A1C293 /* MVMCoreUIActionHandler.m */, + D23A90672614B0B4007E14CE /* CoreUIModelMapping.swift */, ); path = OtherHandlers; sourceTree = ""; @@ -2287,7 +2288,6 @@ D2C78CD324252F4E00B69FDE /* Atomic */ = { isa = PBXGroup; children = ( - 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */, 94C01508242155FE005811A9 /* Actions */, D202AFE2242A5F1400E5BEDF /* Extensions */, D2C78CD424252F5D00B69FDE /* Protocols */, @@ -2515,6 +2515,7 @@ 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */, 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */, + D23A90682614B0B4007E14CE /* CoreUIModelMapping.swift in Sources */, 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */, 8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */, AAA7CD6B250642080045B959 /* Heart.swift in Sources */, @@ -2784,7 +2785,6 @@ 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */, 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */, D20492A624329CE200A5EED6 /* LoadImageView.swift in Sources */, - 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */, D274CA332236A78900B01B62 /* FooterView.swift in Sources */, 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */, D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift deleted file mode 100644 index 539ed2ba..00000000 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ /dev/null @@ -1,287 +0,0 @@ -// -// MoleculeObjectMapping.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 10/28/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers public class MoleculeObjectMapping: NSObject { - /// Returns the mapping object stored in the singleton - public static func shared() -> Self? { - return MVMCoreActionUtility.initializerClassCheck(CoreUIObject.sharedInstance()?.moleculeMap, classToVerify: self) as? Self - } - - /// Registers the model with the model registry and the view with the mapper. - public func register(viewClass: V.Type, viewModelClass: M.Type) { - try? ModelRegistry.register(handler: viewClass, for: viewModelClass) - } - - /// Returns the type of molecule view for the given model - public func getMoleculeClass(_ model: MoleculeModelProtocol) -> MoleculeViewProtocol.Type? { - return ModelRegistry.getHandler(model) as? MoleculeViewProtocol.Type - } - - /// Creates a molecule with the given model. - public func createMolecule(_ model: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> MoleculeViewProtocol? { - guard let type = getMoleculeClass(model) else { return nil } - return type.init(model: model, delegateObject, additionalData) - } - - /// Convenience function for legacy classes - public func getMoleculeModelForJSON(_ json: [String: Any], delegateObject: DelegateObject? = nil) throws -> MoleculeModelProtocol? { - guard let moleculeName = json.optionalStringForKey(KeyMoleculeName), - let type = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) else { - throw ModelRegistry.Error.decoderErrorModelNotMapped() - } - guard let model = try type.decode(jsonDict: json, delegateObject: delegateObject) as? MoleculeModelProtocol else { - throw ModelRegistry.Error.decoderError - } - return model - } - - /// Call to register all of the CoreUI molecules. - public static func registerObjects() { - // MARK:- Stacks - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: StackModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self) - - // MARK:- Label - MoleculeObjectMapping.shared()?.register(viewClass: Label.self, viewModelClass: LabelModel.self) - // need to move labelattributemodel to different method - try? ModelRegistry.register(LabelAttributeFontModel.self) - try? ModelRegistry.register(LabelAttributeColorModel.self) - try? ModelRegistry.register(LabelAttributeImageModel.self) - try? ModelRegistry.register(LabelAttributeUnderlineModel.self) - try? ModelRegistry.register(LabelAttributeStrikeThroughModel.self) - try? ModelRegistry.register(LabelAttributeActionModel.self) - - // MARK:- TextView - MoleculeObjectMapping.shared()?.register(viewClass: TextViewEntryField.self, viewModelClass: TextViewEntryFieldModel.self) - - // MARK:- Buttons - MoleculeObjectMapping.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ExternalLink.self, viewModelClass: ExternalLinkModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: CaretLink.self, viewModelClass: CaretLinkModel.self) - - // MARK:- Entry Field - MoleculeObjectMapping.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MdnEntryField.self, viewModelClass: MdnEntryFieldModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: DigitEntryField.self, viewModelClass: DigitEntryFieldModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ItemDropdownEntryField.self, viewModelClass: ItemDropdownEntryFieldModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: DateDropdownEntryField.self, viewModelClass: DateDropdownEntryFieldModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MultiItemDropdownEntryField.self, viewModelClass: MultiItemDropdownEntryFieldModel.self) - - // MARK:- Selectors - MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Tags.self, viewModelClass: TagsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Tag.self, viewModelClass: TagModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Heart.self, viewModelClass: HeartModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Stars.self, viewModelClass: StarsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Star.self, viewModelClass: StarModel.self) - - - // MARK:- Other Atoms - MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MultiProgress.self, viewModelClass: MultiProgressBarModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: CaretView.self, viewModelClass: CaretViewModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: DashLine.self, viewModelClass: DashLineModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: LoadImageView.self, viewModelClass: ImageViewModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Wheel.self, viewModelClass: WheelModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: RadioButtonLabel.self, viewModelClass: RadioButtonLabelModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: WebView.self, viewModelClass: WebViewModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: LoadingSpinner.self, viewModelClass: LoadingSpinnerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Video.self, viewModelClass: VideoModel.self) - - // MARK:- Horizontal Combination Molecules - MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: TwoLinkView.self, viewModelClass: TwoLinkViewModel.self) - - // MARK:- Vertical Combination Molecules - MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadLineBodyCaretLinkImage.self, viewModelClass: HeadlineBodyCaretLinkImageModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: EyebrowHeadlineBodyLink.self, viewModelClass: EyebrowHeadlineBodyLinkModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBodyLink.self, viewModelClass: HeadlineBodyLinkModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBodyButton.self, viewModelClass: HeadlineBodyButtonModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: BGImageHeadlineBodyButton.self, viewModelClass: BGImageHeadlineBodyButtonModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ThreeHeadlineBodyLink.self, viewModelClass: ThreeHeadlineBodyLinkModel.self) - - // MARK:- Left Right Molecules - MoleculeObjectMapping.shared()?.register(viewClass: CornerLabels.self, viewModelClass: CornerLabelsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: LeftRightLabelView.self, viewModelClass: LeftRightLabelModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: LabelToggle.self, viewModelClass: LabelToggleModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) - - // MARK:- List items - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: DropDownFilterTableViewCell.self, viewModelClass: DropDownListItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: AccordionMoleculeTableViewCell.self, viewModelClass: AccordionListItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: TabsTableViewCell.self, viewModelClass: TabsListItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListProgressBarData.self, viewModelClass: ListProgressBarDataModel.self) - - // MARK:- Other Items - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackItem.self, viewModelClass: MoleculeStackItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: StackItem.self, viewModelClass: StackItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: MoleculeCollectionItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: CarouselItem.self, viewModelClass: CarouselItemModel.self) - - - // MARK:- Other Container Molecules - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeContainer.self, viewModelClass: MoleculeContainerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: BGVideoImageMolecule.self, viewModelClass: BGVideoImageMoleculeModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeSectionHeader.self, viewModelClass: MoleculeSectionHeaderModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeSectionFooter.self, viewModelClass: MoleculeSectionFooterModel.self) - - - // MARK:- Other Molecules - MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self) - - // Navigation Molecules - try? ModelRegistry.register(NavigationItemModel.self) - try? ModelRegistry.register(NavigationImageButtonModel.self) - try? ModelRegistry.register(NavigationLabelButtonModel.self) - - // MARK:- Other Organisms - MoleculeObjectMapping.shared()?.register(viewClass: Carousel.self, viewModelClass: CarouselModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: BarsIndicatorView.self, viewModelClass: BarsCarouselIndicatorModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: NumericIndicatorView.self, viewModelClass: NumericCarouselIndicatorModel.self) - - // MARK:- Designed List Items - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableIconWithRightCaretBodyText.self, viewModelClass: ListLeftVariableIconWithRightCaretBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableIconWithRightCaretAllTextLinks.self, viewModelClass: ListLeftVariableIconWithRightCaretAllTextLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonAllTextAndLinks.self, viewModelClass: ListLeftVariableRadioButtonAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxBodyText.self, viewModelClass: ListLeftVariableCheckboxBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableIconAllTextLinks.self, viewModelClass: ListLeftVariableIconAllTextLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableNumberedListAllTextAndLinks.self, viewModelClass: ListLeftVariableNumberedListAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableNumberedListBodyText.self, viewModelClass: ListLeftVariableNumberedListBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableToggleAllTextAndLinks.self, viewModelClass: ListRightVariableToggleAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableRightCaretAllTextAndLinks.self, viewModelClass: ListRightVariableRightCaretAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnDropdownSelectors.self, viewModelClass: ListTwoColumnDropdownSelectorsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnBillChanges.self, viewModelClass: ListThreeColumnBillChangesModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnBillHistory.self, viewModelClass: ListThreeColumnBillHistoryModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnSpeedTest.self, viewModelClass: ListThreeColumnSpeedTestModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListProgressBarThin.self, viewModelClass: ListProgressBarThinModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListStoreLocator.self, viewModelClass: ListStoreLocatorModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListStarRating.self, viewModelClass: ListStarRatingModel.self) - - // MARK:- Designed Section Dividers - MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnTextWithWhitespaceDividerShort.self, viewModelClass: ListOneColumnTextWithWhitespaceDividerShortModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnTextWithWhitespaceDividerTall.self, viewModelClass: ListOneColumnTextWithWhitespaceDividerTallModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextDividerSubsection.self, viewModelClass: ListOneColumnFullWidthTextDividerSubsectionModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnSubsectionDivider.self, viewModelClass: ListTwoColumnSubsectionDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalDataDivider.self, viewModelClass: ListThreeColumnInternationalDataDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnSpeedTestDivider.self, viewModelClass: ListThreeColumnSpeedTestDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnBillChangesDivider.self, viewModelClass: ListThreeColumnBillChangesDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsageDivider.self, viewModelClass: ListThreeColumnDataUsageDividerModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnBillHistoryDivider.self, viewModelClass: ListThreeColumnBillHistoryDividerModel.self) - - // MARK:- Designed Headers - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH1Button.self, viewModelClass: HeadersH1ButtonModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH1LandingPageHeader.self, viewModelClass: HeadersH1LandingPageHeaderModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH1NoButtonsBodyText.self, viewModelClass: HeadersH1NoButtonsBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2TinyButton.self, viewModelClass: HeadersH2TinyButtonModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Buttons.self, viewModelClass: HeadersH2ButtonsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2PricingTwoRows.self, viewModelClass: HeadersH2PricingTwoRowsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Link.self, viewModelClass: HeadersH2LinkModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2CaretLink.self, viewModelClass: HeadersH2CaretLinkModel.self) - - // MARK:- Device Items - MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonSmall.self, viewModelClass: ListDeviceComplexButtonSmallModel.self) - - MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkSmall.self, viewModelClass: ListDeviceComplexLinkSmallModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self) - - // MARK:- LockUps - MoleculeObjectMapping.shared()?.register(viewClass: LockUpsPlanNames.self, viewModelClass: LockUpsPlanNamesModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: LockupsPlanSMLXL.self, viewModelClass: LockupsPlanSMLXLModel.self) - - // MARK: - Top Notifications - MoleculeObjectMapping.shared()?.register(viewClass: NotificationView.self, viewModelClass: NotificationModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: CollapsableNotification.self, viewModelClass: CollapsableNotificationModel.self) - - // TODO: move all of these out of here. - // MARK:- Helper models - try? ModelRegistry.register(RuleRequiredModel.self) - try? ModelRegistry.register(RuleAnyRequiredModel.self) - try? ModelRegistry.register(RuleAnyValueChangedModel.self) - try? ModelRegistry.register(RuleAllValueChangedModel.self) - try? ModelRegistry.register(RuleEqualsModel.self) - try? ModelRegistry.register(RuleEqualsIgnoreCaseModel.self) - try? ModelRegistry.register(RuleRegexModel.self) - - // MARK:- Actions - try? ModelRegistry.register(ActionPopupModel.self) - try? ModelRegistry.register(ActionAlertModel.self) - try? ModelRegistry.register(ActionTopAlertModel.self) - try? ModelRegistry.register(ActionCollapseNotificationModel.self) - try? ModelRegistry.register(ActionOpenPanelModel.self) - try? ModelRegistry.register(ActionTopNotificationModel.self) - - // MARK:- Behaviors - try? ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self) - try? ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self) - } - - /// Convenience function to get required modules for a give model - public static func getRequiredModules(for model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let model = model else { return nil } - return MoleculeObjectMapping.shared()?.getMoleculeClass(model)?.requiredModules(with: model, delegateObject, error: error) - } - - /// Convenience function to add require modules for the given model to the passed in array. - public static func addRequiredModules(for model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, moduleList: inout [String]?, errorList: inout [MVMCoreErrorObject]?) { - guard let model = model else { return } - let error: AutoreleasingUnsafeMutablePointer? = nil - if let modules = getRequiredModules(for: model, delegateObject, error: error) { - moduleList?.append(contentsOf: modules) - } - if let error = error?.pointee { - errorList?.append(error) - } - } -} - diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift index 33caba83..3d0247d1 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift @@ -31,7 +31,7 @@ import Foundation guard let model = model as? MoleculeSectionFooterModel else { return } if molecule != nil { molecule?.set(with: model.molecule, delegateObject, additionalData) - } else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) { + } else if let moleculeView = ModelRegistry.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) { addMolecule(moleculeView) } containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift index 16aaacfe..ee80ca46 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift @@ -42,7 +42,7 @@ import Foundation guard let model = model as? MoleculeSectionHeaderModel else { return } if molecule != nil { molecule?.set(with: model.molecule, delegateObject, additionalData) - } else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) { + } else if let moleculeView = ModelRegistry.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) { addMolecule(moleculeView) } containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol) diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift index 04694bc1..4ef4f84b 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift @@ -16,7 +16,7 @@ open class MoleculeCollectionViewCell: CollectionViewCell { guard let collectionModel = model as? MoleculeCollectionItemModel else { return } if molecule == nil { - if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(collectionModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { + if let moleculeView = ModelRegistry.createMolecule(collectionModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { addMolecule(moleculeView) } } else { diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift index 92d04bed..666996d9 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift @@ -23,7 +23,7 @@ import UIKit if molecule != nil { molecule?.set(with: castModel.molecule, delegateObject, additionalData) - } else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(castModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { + } else if let moleculeView = ModelRegistry.createMolecule(castModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { addMolecule(moleculeView) } super.set(with: model, delegateObject, additionalData) diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift index 3f8ff8a7..89c9eb4a 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift @@ -167,7 +167,7 @@ import UIKit if let moleculeModel = model.molecule { if middleView != nil { (middleView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData) - } else if let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { + } else if let molecule = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { addMiddleView(molecule) } } diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift index 7374b067..21b68780 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift @@ -29,7 +29,7 @@ open class ModuleMolecule: Container { } if moduleMolecule == nil { - if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(moduleModel, delegateObject: delegateObject, additionalData: additionalData) { + if let moleculeView = ModelRegistry.createMolecule(moduleModel, delegateObject: delegateObject, additionalData: additionalData) { addSubview(moleculeView) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values)) moduleMolecule = moleculeView @@ -50,7 +50,7 @@ open class ModuleMolecule: Container { guard let moduleMolecule = model as? ModuleMoleculeModel, let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName), - let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moduleModel), + let classType = ModelRegistry.getMoleculeClass(moduleModel), let height = classType.estimatedHeight(with: moduleModel, delegateObject) else { // Critical error return 0 @@ -61,7 +61,7 @@ open class ModuleMolecule: Container { public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let moduleMolecule = model as? ModuleMoleculeModel, let moduleModel = delegateObject?.moleculeDelegate?.getModuleWithName(moduleMolecule.moduleName), - let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moduleModel), + let classType = ModelRegistry.getMoleculeClass(moduleModel), let name = classType.nameForReuse(with: moduleModel, delegateObject) else { // Critical error return "moduleMolecule<>" diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift index bc50deba..ede2ba1f 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift @@ -21,7 +21,7 @@ open class MoleculeContainer: Container { if view != nil { (view as? MoleculeViewProtocol)?.set(with: casteModel.molecule, delegateObject, additionalData) } else { - if let molecule = MoleculeObjectMapping.shared()?.createMolecule(casteModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { + if let molecule = ModelRegistry.createMolecule(casteModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { addMolecule(molecule) } } @@ -32,7 +32,7 @@ open class MoleculeContainer: Container { public override static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let containerModel = model as? MoleculeContainerModelProtocol, - let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(containerModel.molecule), + let moleculeClass = ModelRegistry.getMoleculeClass(containerModel.molecule), let moleculeName = moleculeClass.nameForReuse(with: containerModel.molecule, delegateObject) else { return "\(model.moleculeName)<>" } @@ -43,7 +43,7 @@ open class MoleculeContainer: Container { guard let containerModel = model as? MoleculeContainerModelProtocol else { return 0 } - guard let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(containerModel.molecule), + guard let moleculeClass = ModelRegistry.getMoleculeClass(containerModel.molecule), let moleculeHeight = moleculeClass.estimatedHeight(with: containerModel.molecule, delegateObject) else { return (containerModel.topPadding ?? 0) + (containerModel.bottomPadding ?? 0) } @@ -53,7 +53,7 @@ open class MoleculeContainer: Container { public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { guard let containerModel = model as? MoleculeContainerModelProtocol, - let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(containerModel.molecule) + let moleculeClass = ModelRegistry.getMoleculeClass(containerModel.molecule) else { return nil } return moleculeClass.requiredModules(with: containerModel.molecule, delegateObject, error: error) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift index 51789688..35c3218e 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -19,7 +19,7 @@ open class StringAndMoleculeStack: MoleculeStackView { for stackItemModel in molcules { guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject + let molecule = ModelRegistry.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject , additionalData: additionalData) else { // Throw error return diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index a671726c..38081287 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -212,7 +212,7 @@ open class Carousel: View { var pagingView: (UIView & CarouselPageControlProtocol)? = nil if let molecule = molecule, (!molecule.hidesForSinglePage || numberOfPages > 1) { - pagingView = MoleculeObjectMapping.shared()?.createMolecule(molecule, delegateObject: delegateObject) as? (UIView & CarouselPageControlProtocol) + pagingView = ModelRegistry.createMolecule(molecule, delegateObject: delegateObject) as? (UIView & CarouselPageControlProtocol) } addPaging(view: pagingView, position: molecule?.position ?? 20) @@ -234,7 +234,7 @@ open class Carousel: View { /// Returns the (identifier, class) of the molecule for the given map. func getMoleculeInfo(with molecule: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { - guard let className = MoleculeObjectMapping.shared()?.getMoleculeClass(molecule) else { return nil } + guard let className = ModelRegistry.getMoleculeClass(molecule) else { return nil } return (className.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName, className, molecule) } diff --git a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift index f47b2e7e..e0198a62 100644 --- a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift @@ -43,7 +43,7 @@ open class MoleculeStackView: Stack { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { - if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem { + if let stackItem = ModelRegistry.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem { stackItems.append(stackItem) } } diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index e2772f5d..dcdc31df 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -199,7 +199,7 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto } var name = "stack<" for case let item in model.molecules { - if let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(item), + if let moleculeClass = ModelRegistry.getMoleculeClass(item), let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) { name.append(nameForReuse + ",") } else { @@ -218,7 +218,7 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto for case let item in model.molecules { if item.gone { continue } - let height = (MoleculeObjectMapping.shared()?.getMoleculeClass(item))?.estimatedHeight(with: item, delegateObject) ?? 0 + let height = (ModelRegistry.getMoleculeClass(item))?.estimatedHeight(with: item, delegateObject) ?? 0 if !horizontal { // Vertical stack aggregates the items let spacing = item.spacing ?? model.spacing @@ -237,7 +237,7 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto var modules: [String] = [] for case let item in model.molecules { - if let modulesForMolecule = (MoleculeObjectMapping.shared()?.getMoleculeClass(item))?.requiredModules(with: item, delegateObject, error: error) { + if let modulesForMolecule = (ModelRegistry.getMoleculeClass(item))?.requiredModules(with: item, delegateObject, error: error) { modules += modulesForMolecule } } diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift index da90798d..343a2cac 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift @@ -61,3 +61,36 @@ extension MoleculeViewProtocol { } } } + +// Convenience Functions +public extension ModelRegistry { + /// Returns the type of molecule view for the given model + static func getMoleculeClass(_ model: MoleculeModelProtocol) -> MoleculeViewProtocol.Type? { + return ModelRegistry.getHandler(model) as? MoleculeViewProtocol.Type + } + + /// Creates a molecule with the given model. + static func createMolecule(_ model: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> MoleculeViewProtocol? { + guard let type = getMoleculeClass(model) else { return nil } + return type.init(model: model, delegateObject, additionalData) + } + + // TODO: move below to KyleTraverse (tm) + /// Convenience function to get required modules for a give model + static func getRequiredModules(for model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let model = model else { return nil } + return ModelRegistry.getMoleculeClass(model)?.requiredModules(with: model, delegateObject, error: error) + } + + /// Convenience function to add require modules for the given model to the passed in array. + static func addRequiredModules(for model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, moduleList: inout [String]?, errorList: inout [MVMCoreErrorObject]?) { + guard let model = model else { return } + let error: AutoreleasingUnsafeMutablePointer? = nil + if let modules = getRequiredModules(for: model, delegateObject, error: error) { + moduleList?.append(contentsOf: modules) + } + if let error = error?.pointee { + errorList?.append(error) + } + } +} diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift index b65e96f1..8e0310a7 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift @@ -44,7 +44,7 @@ import Foundation open override func viewForTop() -> UIView? { guard let headerModel = templateModel?.header, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar) else { return super.viewForTop() } // Temporary, Default the horizontal padding @@ -57,7 +57,7 @@ import Foundation override open func viewForBottom() -> UIView? { guard let footerModel = templateModel?.footer, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar) else { return super.viewForBottom() } return molecule @@ -146,7 +146,7 @@ import Foundation /// Returns the (identifier, class) of the molecule for the given map. open func getMoleculeInfo(with item: (CollectionItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: CollectionItemModelProtocol & MoleculeModelProtocol)? { guard let item = item, - let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(item) else { return nil } + let moleculeClass = ModelRegistry.getMoleculeClass(item) else { return nil } let moleculeName = moleculeClass.nameForReuse(with: item, delegateObjectIVar) ?? item.moleculeName return (moleculeName, moleculeClass, item) } @@ -183,12 +183,12 @@ import Foundation open func requiredModules() -> [Any]? { var modules: [String]? = [] var errors: [MVMCoreErrorObject]? = nil - MoleculeObjectMapping.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors) - MoleculeObjectMapping.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors) if let molecules = templateModel?.molecules { for molecule in molecules { - MoleculeObjectMapping.addRequiredModules(for: molecule, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: molecule, delegateObjectIVar, moduleList: &modules, errorList: &errors) } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index ba057444..bb2eeb94 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -54,7 +54,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func viewForTop() -> UIView { guard let headerModel = templateModel?.header, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar) else { return super.viewForTop() } // Temporary, Default the horizontal padding @@ -67,7 +67,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol override open func viewForBottom() -> UIView { guard let footerModel = templateModel?.footer, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar) else { return super.viewForBottom() } return molecule @@ -222,7 +222,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol func createMoleculeInfo(with listItem: MoleculeModelProtocol?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { guard let listItem = listItem, - let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem) + let moleculeClass = ModelRegistry.getMoleculeClass(listItem) else { return nil } let moleculeName = moleculeClass.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName @@ -267,12 +267,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open func requiredModules() -> [Any]? { var modules: [String]? = [] var errors: [MVMCoreErrorObject]? = nil - MoleculeObjectMapping.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors) - MoleculeObjectMapping.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors) if let molecules = templateModel?.molecules { for molecule in molecules { - MoleculeObjectMapping.addRequiredModules(for: molecule, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: molecule, delegateObjectIVar, moduleList: &modules, errorList: &errors) } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift index 2b555e18..957b1bd9 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift @@ -57,7 +57,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { open override func viewForTop() -> UIView? { guard let headerModel = templateModel?.header, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar) else { return nil } return molecule @@ -82,7 +82,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { override open func viewForBottom() -> UIView? { guard let footerModel = templateModel?.footer, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar) else { return nil } return molecule @@ -103,9 +103,9 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { open func requiredModules() -> [Any]? { var modules: [String]? = [] var errors: [MVMCoreErrorObject]? = nil - MoleculeObjectMapping.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors) - MoleculeObjectMapping.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors) - MoleculeObjectMapping.addRequiredModules(for: templateModel?.moleculeStack, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors) + ModelRegistry.addRequiredModules(for: templateModel?.moleculeStack, delegateObjectIVar, moduleList: &modules, errorList: &errors) return modules } } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift index f1b2633c..5da54946 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift @@ -24,7 +24,7 @@ import UIKit open override func viewForTop() -> UIView? { guard let headerModel = templateModel?.header, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar) else { return nil } return molecule @@ -32,7 +32,7 @@ import UIKit open override func viewForMiddle() -> UIView? { guard let middleModel = templateModel?.middle, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(middleModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(middleModel, delegateObject: delegateObjectIVar) else { return nil } return molecule @@ -40,7 +40,7 @@ import UIKit override open func viewForBottom() -> UIView? { guard let footerModel = templateModel?.footer, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) + let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar) else { return nil } return molecule diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index 179fb8b2..91ef599d 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -33,9 +33,9 @@ public class PageGetContactBehavior: PageVisibilityBehavior { CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in guard access, error == nil, + // TODO: Clean up this interface let model = (self?.delegate?.moleculeDelegate as? PageProtocol)?.pageModel as? TemplateModelProtocol else { return } // Iterate models and provide contact - let page = self?.delegate?.moleculeDelegate as? PageProtocol let store = CNContactStore() let consumers: [PageGetContactBehaviorConsumerProtocol] = model.allMoleculesOfType() for consumer in consumers { @@ -47,7 +47,7 @@ public class PageGetContactBehavior: PageVisibilityBehavior { // Tell template to update MVMCoreDispatchUtility.performBlock(onMainThread: { // TODO: move to protocol function instead - (page as? ViewController)?.handleNewData() + (self?.delegate?.moleculeDelegate as? ViewController)?.handleNewData() }) } } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 7a403338..331656b7 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -99,7 +99,7 @@ import UIKit /// Convenience function for setting the navigation titleView. public static func setNavigationTitleView(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) { let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject - if let titleViewModel = navigationItemModel?.titleView, let molecule = MoleculeObjectMapping.shared()?.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) { + if let titleViewModel = navigationItemModel?.titleView, let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) { viewController.navigationItem.titleView = molecule } } diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift new file mode 100644 index 00000000..e06afca9 --- /dev/null +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -0,0 +1,247 @@ +// +// ModelMapping.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/31/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import MVMCore + +open class CoreUIModelMapping: ModelMapping { + open override class func registerObjects() { + super.registerObjects() + registerMolecules() + registerRules() + registerActions() + registerBehaviors() + registerLabelAttributes() + } + + open class func registerMolecules() { + // MARK:- Stacks + try? ModelRegistry.register(handler: MoleculeStackView.self, for: StackModel.self) + try? ModelRegistry.register(handler: UnOrderedList.self, for: UnOrderedListModel.self) + try? ModelRegistry.register(handler: NumberedList.self, for: NumberedListModel.self) + + // MARK:- Label + try? ModelRegistry.register(handler: Label.self, for: LabelModel.self) + + // MARK:- TextView + try? ModelRegistry.register(handler: TextViewEntryField.self, for: TextViewEntryFieldModel.self) + + // MARK:- Buttons + try? ModelRegistry.register(handler: PillButton.self, for: ButtonModel.self) + try? ModelRegistry.register(handler: TwoButtonView.self, for: TwoButtonViewModel.self) + try? ModelRegistry.register(handler: ExternalLink.self, for: ExternalLinkModel.self) + try? ModelRegistry.register(handler: Link.self, for: LinkModel.self) + try? ModelRegistry.register(handler: CaretLink.self, for: CaretLinkModel.self) + + // MARK:- Entry Field + try? ModelRegistry.register(handler: TextEntryField.self, for: TextEntryFieldModel.self) + try? ModelRegistry.register(handler: MdnEntryField.self, for: MdnEntryFieldModel.self) + try? ModelRegistry.register(handler: DigitEntryField.self, for: DigitEntryFieldModel.self) + try? ModelRegistry.register(handler: ItemDropdownEntryField.self, for: ItemDropdownEntryFieldModel.self) + try? ModelRegistry.register(handler: DateDropdownEntryField.self, for: DateDropdownEntryFieldModel.self) + try? ModelRegistry.register(handler: MultiItemDropdownEntryField.self, for: MultiItemDropdownEntryFieldModel.self) + + // MARK:- Selectors + try? ModelRegistry.register(handler: RadioButton.self, for: RadioButtonModel.self) + try? ModelRegistry.register(handler: RadioBoxes.self, for: RadioBoxesModel.self) + try? ModelRegistry.register(handler: Checkbox.self, for: CheckboxModel.self) + try? ModelRegistry.register(handler: RadioSwatches.self, for: RadioSwatchesModel.self) + try? ModelRegistry.register(handler: Tags.self, for: TagsModel.self) + try? ModelRegistry.register(handler: Tag.self, for: TagModel.self) + try? ModelRegistry.register(handler: Heart.self, for: HeartModel.self) + try? ModelRegistry.register(handler: Stars.self, for: StarsModel.self) + try? ModelRegistry.register(handler: Star.self, for: StarModel.self) + + + // MARK:- Other Atoms + try? ModelRegistry.register(handler: ProgressBar.self, for: ProgressBarModel.self) + try? ModelRegistry.register(handler: MultiProgress.self, for: MultiProgressBarModel.self) + try? ModelRegistry.register(handler: CaretView.self, for: CaretViewModel.self) + try? ModelRegistry.register(handler: DashLine.self, for: DashLineModel.self) + try? ModelRegistry.register(handler: LoadImageView.self, for: ImageViewModel.self) + try? ModelRegistry.register(handler: Line.self, for: LineModel.self) + try? ModelRegistry.register(handler: Wheel.self, for: WheelModel.self) + try? ModelRegistry.register(handler: Toggle.self, for: ToggleModel.self) + try? ModelRegistry.register(handler: CheckboxLabel.self, for: CheckboxLabelModel.self) + try? ModelRegistry.register(handler: Arrow.self, for: ArrowModel.self) + try? ModelRegistry.register(handler: RadioButtonLabel.self, for: RadioButtonLabelModel.self) + try? ModelRegistry.register(handler: WebView.self, for: WebViewModel.self) + try? ModelRegistry.register(handler: LoadingSpinner.self, for: LoadingSpinnerModel.self) + try? ModelRegistry.register(handler: Video.self, for: VideoModel.self) + + // MARK:- Horizontal Combination Molecules + try? ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self) + try? ModelRegistry.register(handler: ImageHeadlineBody.self, for: ImageHeadlineBodyModel.self) + try? ModelRegistry.register(handler: Tabs.self, for: TabsModel.self) + try? ModelRegistry.register(handler: TwoLinkView.self, for: TwoLinkViewModel.self) + + // MARK:- Vertical Combination Molecules + try? ModelRegistry.register(handler: HeadlineBody.self, for: HeadlineBodyModel.self) + try? ModelRegistry.register(handler: HeadLineBodyCaretLinkImage.self, for: HeadlineBodyCaretLinkImageModel.self) + try? ModelRegistry.register(handler: EyebrowHeadlineBodyLink.self, for: EyebrowHeadlineBodyLinkModel.self) + try? ModelRegistry.register(handler: HeadlineBodyLink.self, for: HeadlineBodyLinkModel.self) + try? ModelRegistry.register(handler: HeadlineBodyButton.self, for: HeadlineBodyButtonModel.self) + try? ModelRegistry.register(handler: BGImageHeadlineBodyButton.self, for: BGImageHeadlineBodyButtonModel.self) + try? ModelRegistry.register(handler: ThreeHeadlineBodyLink.self, for: ThreeHeadlineBodyLinkModel.self) + + // MARK:- Left Right Molecules + try? ModelRegistry.register(handler: CornerLabels.self, for: CornerLabelsModel.self) + try? ModelRegistry.register(handler: LeftRightLabelView.self, for: LeftRightLabelModel.self) + try? ModelRegistry.register(handler: LabelToggle.self, for: LabelToggleModel.self) + try? ModelRegistry.register(handler: HeadlineBodyToggle.self, for: HeadlineBodyToggleModel.self) + try? ModelRegistry.register(handler: HeadlineBodyLinkToggle.self, for: HeadlineBodyLinkToggleModel.self) + try? ModelRegistry.register(handler: ActionDetailWithImage.self, for: ActionDetailWithImageModel.self) + + // MARK:- List items + try? ModelRegistry.register(handler: MoleculeTableViewCell.self, for: MoleculeListItemModel.self) + try? ModelRegistry.register(handler: DropDownFilterTableViewCell.self, for: DropDownListItemModel.self) + try? ModelRegistry.register(handler: AccordionMoleculeTableViewCell.self, for: AccordionListItemModel.self) + try? ModelRegistry.register(handler: TabsTableViewCell.self, for: TabsListItemModel.self) + try? ModelRegistry.register(handler: ListProgressBarData.self, for: ListProgressBarDataModel.self) + + // MARK:- Other Items + try? ModelRegistry.register(handler: MoleculeStackItem.self, for: MoleculeStackItemModel.self) + try? ModelRegistry.register(handler: StackItem.self, for: StackItemModel.self) + try? ModelRegistry.register(handler: MoleculeCollectionViewCell.self, for: MoleculeCollectionItemModel.self) + try? ModelRegistry.register(handler: CarouselItem.self, for: CarouselItemModel.self) + + + // MARK:- Other Container Molecules + try? ModelRegistry.register(handler: MoleculeContainer.self, for: MoleculeContainerModel.self) + try? ModelRegistry.register(handler: MoleculeHeaderView.self, for: MoleculeHeaderModel.self) + try? ModelRegistry.register(handler: FooterView.self, for: FooterModel.self) + try? ModelRegistry.register(handler: Scroller.self, for: ScrollerModel.self) + try? ModelRegistry.register(handler: ModuleMolecule.self, for: ModuleMoleculeModel.self) + try? ModelRegistry.register(handler: BGImageMolecule.self, for: BGImageMoleculeModel.self) + try? ModelRegistry.register(handler: BGVideoImageMolecule.self, for: BGVideoImageMoleculeModel.self) + try? ModelRegistry.register(handler: MoleculeSectionHeader.self, for: MoleculeSectionHeaderModel.self) + try? ModelRegistry.register(handler: MoleculeSectionFooter.self, for: MoleculeSectionFooterModel.self) + + + // MARK:- Other Molecules + try? ModelRegistry.register(handler: DoughnutChartView.self, for: DoughnutChartModel.self) + + // Navigation Molecules + try? ModelRegistry.register(NavigationItemModel.self) + try? ModelRegistry.register(NavigationImageButtonModel.self) + try? ModelRegistry.register(NavigationLabelButtonModel.self) + + // MARK:- Other Organisms + try? ModelRegistry.register(handler: Carousel.self, for: CarouselModel.self) + try? ModelRegistry.register(handler: BarsIndicatorView.self, for: BarsCarouselIndicatorModel.self) + try? ModelRegistry.register(handler: NumericIndicatorView.self, for: NumericCarouselIndicatorModel.self) + + // MARK:- Designed List Items + try? ModelRegistry.register(handler: ListLeftVariableIconWithRightCaret.self, for: ListLeftVariableIconWithRightCaretModel.self) + try? ModelRegistry.register(handler: ListLeftVariableIconWithRightCaretBodyText.self, for: ListLeftVariableIconWithRightCaretBodyTextModel.self) + try? ModelRegistry.register(handler: ListLeftVariableIconWithRightCaretAllTextLinks.self, for: ListLeftVariableIconWithRightCaretAllTextLinksModel.self) + try? ModelRegistry.register(handler: ListLeftVariableCheckboxAllTextAndLinks.self, for: ListLeftVariableCheckboxAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListLeftVariableRadioButtonAndPaymentMethod.self, for: ListLeftVariableRadioButtonAndPaymentMethodModel.self) + try? ModelRegistry.register(handler: ListLeftVariableRadioButtonBodyText.self, for: ListLeftVariableRadioButtonBodyTextModel.self) + try? ModelRegistry.register(handler: ListLeftVariableRadioButtonAllTextAndLinks.self, for: ListLeftVariableRadioButtonAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListLeftVariableCheckboxBodyText.self, for: ListLeftVariableCheckboxBodyTextModel.self) + try? ModelRegistry.register(handler: ListLeftVariableIconAllTextLinks.self, for: ListLeftVariableIconAllTextLinksModel.self) + try? ModelRegistry.register(handler: ListLeftVariableNumberedListAllTextAndLinks.self, for: ListLeftVariableNumberedListAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListLeftVariableNumberedListBodyText.self, for: ListLeftVariableNumberedListBodyTextModel.self) + try? ModelRegistry.register(handler: ListRVWheel.self, for: ListRVWheelModel.self) + try? ModelRegistry.register(handler: ListRightVariablePayments.self, for: ListRightVariablePaymentsModel.self) + try? ModelRegistry.register(handler: ListRightVariableTotalData.self, for: ListRightVariableTotalDataModel.self) + try? ModelRegistry.register(handler: ListRightVariableTextLinkAllTextAndLinks.self, for: ListRightVariableTextLinkAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListRightVariableButtonAllTextAndLinks.self, for: ListRightVariableButtonAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListRightVariablePriceChangeBodyText.self, for: ListRightVariablePriceChangeBodyTextModel.self) + try? ModelRegistry.register(handler: ListRightVariablePriceChangeAllTextAndLinks.self, for: ListRightVariablePriceChangeAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListRightVariableToggleAllTextAndLinks.self, for: ListRightVariableToggleAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListRightVariableRightCaretAllTextAndLinks.self, for: ListRightVariableRightCaretAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListOneColumnFullWidthTextAllTextAndLinks.self, for: ListOneColumnFullWidthTextAllTextAndLinksModel.self) + try? ModelRegistry.register(handler: ListOneColumnFullWidthTextBodyText.self, for: ListOneColumnFullWidthTextBodyTextModel.self) + try? ModelRegistry.register(handler: ListTwoColumnCompareChanges.self, for: ListTwoColumnCompareChangesModel.self) + try? ModelRegistry.register(handler: ListTwoColumnPriceDetails.self, for: ListTwoColumnPriceDetailsModel.self) + try? ModelRegistry.register(handler: ListTwoColumnPriceDescription.self, for: ListTwoColumnPriceDescriptionModel.self) + try? ModelRegistry.register(handler: ListTwoColumnDropdownSelectors.self, for: ListTwoColumnDropdownSelectorsModel.self) + try? ModelRegistry.register(handler: ListThreeColumnInternationalData.self, for: ListThreeColumnInternationalDataModel.self) + try? ModelRegistry.register(handler: ListThreeColumnDataUsage.self, for: ListThreeColumnDataUsageModel.self) + try? ModelRegistry.register(handler: ListThreeColumnBillChanges.self, for: ListThreeColumnBillChangesModel.self) + try? ModelRegistry.register(handler: ListThreeColumnBillHistory.self, for: ListThreeColumnBillHistoryModel.self) + try? ModelRegistry.register(handler: ListThreeColumnSpeedTest.self, for: ListThreeColumnSpeedTestModel.self) + try? ModelRegistry.register(handler: ListFourColumnDataUsageListItem.self, for: ListFourColumnDataUsageListItemModel.self) + try? ModelRegistry.register(handler: ListProgressBarThin.self, for: ListProgressBarThinModel.self) + try? ModelRegistry.register(handler: ListStoreLocator.self, for: ListStoreLocatorModel.self) + try? ModelRegistry.register(handler: ListStarRating.self, for: ListStarRatingModel.self) + + // MARK:- Designed Section Dividers + try? ModelRegistry.register(handler: ListFourColumnDataUsageDivider.self, for: ListFourColumnDataUsageDividerModel.self) + try? ModelRegistry.register(handler: ListThreeColumnPlanDataDivider.self, for: ListThreeColumnPlanDataDividerModel.self) + try? ModelRegistry.register(handler: ListOneColumnTextWithWhitespaceDividerShort.self, for: ListOneColumnTextWithWhitespaceDividerShortModel.self) + try? ModelRegistry.register(handler: ListOneColumnTextWithWhitespaceDividerTall.self, for: ListOneColumnTextWithWhitespaceDividerTallModel.self) + try? ModelRegistry.register(handler: ListOneColumnFullWidthTextDividerSubsection.self, for: ListOneColumnFullWidthTextDividerSubsectionModel.self) + try? ModelRegistry.register(handler: ListTwoColumnSubsectionDivider.self, for: ListTwoColumnSubsectionDividerModel.self) + try? ModelRegistry.register(handler: ListThreeColumnInternationalDataDivider.self, for: ListThreeColumnInternationalDataDividerModel.self) + try? ModelRegistry.register(handler: ListThreeColumnSpeedTestDivider.self, for: ListThreeColumnSpeedTestDividerModel.self) + try? ModelRegistry.register(handler: ListThreeColumnBillChangesDivider.self, for: ListThreeColumnBillChangesDividerModel.self) + try? ModelRegistry.register(handler: ListThreeColumnDataUsageDivider.self, for: ListThreeColumnDataUsageDividerModel.self) + try? ModelRegistry.register(handler: ListThreeColumnBillHistoryDivider.self, for: ListThreeColumnBillHistoryDividerModel.self) + + // MARK:- Designed Headers + try? ModelRegistry.register(handler: HeadersH1Button.self, for: HeadersH1ButtonModel.self) + try? ModelRegistry.register(handler: HeadersH1LandingPageHeader.self, for: HeadersH1LandingPageHeaderModel.self) + try? ModelRegistry.register(handler: HeadersH1NoButtonsBodyText.self, for: HeadersH1NoButtonsBodyTextModel.self) + try? ModelRegistry.register(handler: HeadersH2NoButtonsBodyText.self, for: HeadersH2NoButtonsBodyTextModel.self) + try? ModelRegistry.register(handler: HeadersH2TinyButton.self, for: HeadersH2TinyButtonModel.self) + try? ModelRegistry.register(handler: HeadersH2Buttons.self, for: HeadersH2ButtonsModel.self) + try? ModelRegistry.register(handler: HeadersH2PricingTwoRows.self, for: HeadersH2PricingTwoRowsModel.self) + try? ModelRegistry.register(handler: HeadersH2Link.self, for: HeadersH2LinkModel.self) + try? ModelRegistry.register(handler: HeadersH2CaretLink.self, for: HeadersH2CaretLinkModel.self) + + // MARK:- Device Items + try? ModelRegistry.register(handler: ListDeviceComplexButtonMedium.self, for: ListDeviceComplexButtonMediumModel.self) + try? ModelRegistry.register(handler: ListDeviceComplexButtonSmall.self, for: ListDeviceComplexButtonSmallModel.self) + + try? ModelRegistry.register(handler: ListDeviceComplexLinkSmall.self, for: ListDeviceComplexLinkSmallModel.self) + try? ModelRegistry.register(handler: ListDeviceComplexLinkMedium.self, for: ListDeviceComplexLinkMediumModel.self) + + // MARK:- LockUps + try? ModelRegistry.register(handler: LockUpsPlanNames.self, for: LockUpsPlanNamesModel.self) + try? ModelRegistry.register(handler: LockupsPlanSMLXL.self, for: LockupsPlanSMLXLModel.self) + + // MARK: - Top Notifications + try? ModelRegistry.register(handler: NotificationView.self, for: NotificationModel.self) + try? ModelRegistry.register(handler: CollapsableNotification.self, for: CollapsableNotificationModel.self) + } + + open class func registerLabelAttributes() { + try? ModelRegistry.register(LabelAttributeFontModel.self) + try? ModelRegistry.register(LabelAttributeColorModel.self) + try? ModelRegistry.register(LabelAttributeImageModel.self) + try? ModelRegistry.register(LabelAttributeUnderlineModel.self) + try? ModelRegistry.register(LabelAttributeStrikeThroughModel.self) + try? ModelRegistry.register(LabelAttributeActionModel.self) + } + + open class func registerBehaviors() { + try? ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self) + try? ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self) + } + + open class func registerActions() { + try? ModelRegistry.register(ActionPopupModel.self) + try? ModelRegistry.register(ActionAlertModel.self) + try? ModelRegistry.register(ActionTopAlertModel.self) + try? ModelRegistry.register(ActionCollapseNotificationModel.self) + try? ModelRegistry.register(ActionOpenPanelModel.self) + try? ModelRegistry.register(ActionTopNotificationModel.self) + } + + open class func registerRules() { + try? ModelRegistry.register(RuleRequiredModel.self) + try? ModelRegistry.register(RuleAnyRequiredModel.self) + try? ModelRegistry.register(RuleAnyValueChangedModel.self) + try? ModelRegistry.register(RuleAllValueChangedModel.self) + try? ModelRegistry.register(RuleEqualsModel.self) + try? ModelRegistry.register(RuleEqualsIgnoreCaseModel.self) + try? ModelRegistry.register(RuleRegexModel.self) + } +} diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index 90532f98..d61d7be4 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -9,10 +9,10 @@ import UIKit @objcMembers open class CoreUIObject: MVMCoreObject { - public var moleculeMap: MoleculeObjectMapping? public var globalTopAlertDelegate: MVMCoreGlobalTopAlertDelegateProtocol? open override func defaultInitialSetup() { + CoreUIModelMapping.registerObjects() loadHandler = MVMCoreLoadHandler() cache = MVMCoreCache() sessionHandler = MVMCoreSessionTimeHandler() @@ -20,8 +20,5 @@ import UIKit session = MVMCoreUISession() viewControllerMapping = MVMCoreUIViewControllerMappingObject() loggingDelegate = MVMCoreUILoggingHandler() - moleculeMap = MoleculeObjectMapping() - MoleculeObjectMapping.registerObjects() - clientParameterRegistry = ClientParameterRegistry() } } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift index 107a3596..454ea7a2 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift @@ -88,10 +88,10 @@ public extension MVMCoreUITopAlertView { let delegateObject = getDelegateObject() guard let newJson = topAlertObject.json, let newModel = decodeTopNotification(with: newJson, delegateObject: delegateObject), - let newModelName = MoleculeObjectMapping.shared()?.getMoleculeClass(newModel.molecule)?.nameForReuse(with: newModel.molecule, delegateObject), + let newModelName = ModelRegistry.getMoleculeClass(newModel.molecule)?.nameForReuse(with: newModel.molecule, delegateObject), let currentJson = self.topAlertObject?.json, let currentModel = decodeTopNotification(with: currentJson, delegateObject: delegateObject), - let currentModelName = MoleculeObjectMapping.shared()?.getMoleculeClass(currentModel.molecule)?.nameForReuse(with: currentModel.molecule, delegateObject), + let currentModelName = ModelRegistry.getMoleculeClass(currentModel.molecule)?.nameForReuse(with: currentModel.molecule, delegateObject), newModelName == currentModelName, let molecule = currentAlert as? MoleculeViewProtocol else { // Log that we couldn't update. @@ -119,7 +119,7 @@ public extension MVMCoreUITopAlertView { let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self) guard let json = topAlertObject.json else { return nil } let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject) - guard let molecule = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil) else { + guard let molecule = ModelRegistry.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil) else { throw ModelRegistry.Error.decoderOther(message: "Molecule not mapped") } if let castView = molecule as? StatusBarUI { From 65c71d6ff80dfcd3d6cd1b7600d867509efcedfc Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 31 Mar 2021 14:00:11 -0400 Subject: [PATCH 19/20] unify the mappings --- .../Atomic/Protocols/MoleculeViewProtocol.swift | 10 +++++++++- .../Behaviors/PageBehaviorHandlerProtocol.swift | 12 +++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift index 343a2cac..57013638 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift @@ -66,7 +66,15 @@ extension MoleculeViewProtocol { public extension ModelRegistry { /// Returns the type of molecule view for the given model static func getMoleculeClass(_ model: MoleculeModelProtocol) -> MoleculeViewProtocol.Type? { - return ModelRegistry.getHandler(model) as? MoleculeViewProtocol.Type + do { + let type = try ModelRegistry.getHandler(model) as! MoleculeViewProtocol.Type + return type + } catch { + if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) { + MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject) + } + return nil + } } /// Creates a molecule with the given model. diff --git a/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift index b90ac1aa..3b809da0 100644 --- a/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift +++ b/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift @@ -21,9 +21,15 @@ public extension PageBehaviorHandlerProtocol { } var behaviors: [PageBehaviorProtocol] = [] for behaviorModel in behaviorModels { - guard let handlerType = ModelRegistry.getHandler(behaviorModel) as? PageBehaviorProtocol.Type else { continue } - let behavior = handlerType.init(model: behaviorModel, delegateObject: delegateObject) - behaviors.append(behavior) + do { + let handlerType = try ModelRegistry.getHandler(behaviorModel) as! PageBehaviorProtocol.Type + let behavior = handlerType.init(model: behaviorModel, delegateObject: delegateObject) + behaviors.append(behavior) + } catch { + if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) { + MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject) + } + } } self.behaviors = behaviors.count > 0 ? behaviors : nil } From b68c3866087d3f116789ac82346cb59e243e583a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 31 Mar 2021 14:33:31 -0400 Subject: [PATCH 20/20] re-org actions in core --- MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index e06afca9..45d1b0c4 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -226,7 +226,8 @@ open class CoreUIModelMapping: ModelMapping { try? ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self) } - open class func registerActions() { + open override class func registerActions() { + super.registerActions() try? ModelRegistry.register(ActionPopupModel.self) try? ModelRegistry.register(ActionAlertModel.self) try? ModelRegistry.register(ActionTopAlertModel.self)