diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index b67f6235..cbb26b62 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -305,6 +305,8 @@ D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; + D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2169300251E51E7002A6324 /* SectionListTemplate.swift */; }; + D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */; }; D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; }; D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; }; D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; }; @@ -464,6 +466,8 @@ D2CAC7CF2511052300C75681 /* CollapsableNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */; }; D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */; }; D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */; }; + D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */; }; + D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */; }; D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; }; D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; }; D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; }; @@ -481,6 +485,9 @@ D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; }; D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; }; D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; }; + D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */; }; + D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */; }; + D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */; }; D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; }; D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; }; DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; }; @@ -793,6 +800,8 @@ D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertView+Extension.swift"; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModel.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; + D2169300251E51E7002A6324 /* SectionListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionListTemplate.swift; sourceTree = ""; }; + D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionListTemplateModel.swift; sourceTree = ""; }; D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = ""; }; D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = ""; }; @@ -954,6 +963,8 @@ D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationModel.swift; sourceTree = ""; }; D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertMainView+Extension.swift"; sourceTree = ""; }; D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertExpandableView+Extension.swift"; sourceTree = ""; }; + D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooterModel.swift; sourceTree = ""; }; + D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooter.swift; sourceTree = ""; }; D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = ""; }; D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = ""; }; D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = ""; }; @@ -970,6 +981,9 @@ D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = ""; }; D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = ""; }; D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = ""; }; + D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeaderModel.swift; sourceTree = ""; }; + D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeader.swift; sourceTree = ""; }; + D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderFooterView.swift; sourceTree = ""; }; D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = ""; }; D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = ""; }; DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = ""; }; @@ -1680,6 +1694,8 @@ D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */, D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */, D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */, + D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */, + D2169300251E51E7002A6324 /* SectionListTemplate.swift */, ); path = Templates; sourceTree = ""; @@ -1707,6 +1723,7 @@ D29DF10E21E67A77003B2FB9 /* Molecules */ = { isa = PBXGroup; children = ( + D2EC7BD22527A1E400F540AF /* HeadersAndFooters */, D2CAC7C9251104CB00C75681 /* TopNotification */, D2509ED42472EE0B001BFB9D /* NavigationBar */, D253BB9A24587023002DE544 /* OtherContainers */, @@ -1715,12 +1732,6 @@ D224798F2316A99F003FCCF9 /* LeftRightViews */, D224798E2316A995003FCCF9 /* HorizontalCombinationViews */, D224798D2316A988003FCCF9 /* VerticalCombinationViews */, - 01EB368C23609801006832FA /* HeaderModel.swift */, - D256E9922412880000360572 /* Header.swift */, - D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */, - D2A514662213885800345BFB /* MoleculeHeaderView.swift */, - 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, - D274CA322236A78900B01B62 /* FooterView.swift */, D260105723CF9CC500764D80 /* Doughnut */, ); path = Molecules; @@ -2022,6 +2033,7 @@ 0A5D59C323AD488600EFD9E9 /* Protocols */, 0A7918F423F5E7EA00772FF4 /* ImageView.swift */, D272F5F82473163100BD1A8F /* BarButtonItem.swift */, + D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */, ); path = BaseClasses; sourceTree = ""; @@ -2085,6 +2097,23 @@ path = TopNotification; sourceTree = ""; }; + D2EC7BD22527A1E400F540AF /* HeadersAndFooters */ = { + isa = PBXGroup; + children = ( + 01EB368C23609801006832FA /* HeaderModel.swift */, + D256E9922412880000360572 /* Header.swift */, + D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */, + D2A514662213885800345BFB /* MoleculeHeaderView.swift */, + 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, + D274CA322236A78900B01B62 /* FooterView.swift */, + D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */, + D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */, + D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */, + D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */, + ); + path = HeadersAndFooters; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2238,6 +2267,7 @@ D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */, AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, + D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */, D28764AA2458980300CB882D /* ThreeLayerFillMiddleTemplate.swift in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */, D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */, @@ -2253,6 +2283,7 @@ AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */, AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */, D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */, + D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */, 0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, @@ -2406,6 +2437,7 @@ D260105323CEA61600764D80 /* ToggleModel.swift in Sources */, 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */, 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */, + D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */, AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */, D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, @@ -2418,6 +2450,7 @@ D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */, 0A775F2824893937009EFB58 /* ThreeHeadlineBodyLinkModel.swift in Sources */, 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */, + D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */, D23EA802247EBED400D60C34 /* ImageBarButtonItem.swift in Sources */, AA45AA0B24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, @@ -2522,6 +2555,7 @@ D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, 0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */, + D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */, 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */, D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */, @@ -2604,6 +2638,7 @@ AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, + D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */, BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */, 0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */, 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, @@ -2645,6 +2680,7 @@ AA0A257A24766CA200862F64 /* ListLeftVariableIconWithRightCaretBodyText.swift in Sources */, 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, + D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */, 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */, D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */, ); diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index a598b113..96506df0 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -149,6 +149,9 @@ import Foundation 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: 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) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift index 986ee73b..7a9e8b7e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift @@ -77,7 +77,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 120 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift index cd43215b..dc086400 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift @@ -77,7 +77,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 120 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift index 9f469d28..79530eb6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -94,7 +94,7 @@ updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 120 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillChanges.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillChanges.swift index c9368057..3db13a01 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillChanges.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillChanges.swift @@ -59,7 +59,7 @@ updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillHistory.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillHistory.swift index 98ec315a..b80c1ac6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillHistory.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnBillHistory.swift @@ -55,7 +55,7 @@ updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift index 24da6877..5ebaf0f6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift @@ -58,7 +58,7 @@ updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnSpeedTest.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnSpeedTest.swift index ba7c8794..64a7cd9f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnSpeedTest.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnSpeedTest.swift @@ -64,7 +64,7 @@ updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift index 10c4511f..9f7895af 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift @@ -90,7 +90,7 @@ rightHeadlineBodyLink.body.setFontStyle(.RegularBodySmall) } - public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift index 6b77e709..eb8fb0ea 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift @@ -54,7 +54,7 @@ rightDropDown.set(with:model.rightDropDown, delegateObject, additionalData) } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift index 95b512b0..3e67b86f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift @@ -59,7 +59,7 @@ rightLabel.setFontStyle(.RegularBodySmall) } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 15 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift index 96c72865..f97fea4a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/FourColumn/ListFourColumnDataUsageDivider.swift @@ -66,7 +66,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift index 3ed2065e..3f48c3d8 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift @@ -53,9 +53,7 @@ import Foundation super.set(with: model, delegateObject, additionalData) guard let model = model as? ListOneColumnFullWidthTextDividerSubsectionModel else { return } - - headline.set(with: model.headline, delegateObject, additionalData) - body.set(with: model.body, delegateObject, additionalData) + stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData) updateAccessibilityLabel() } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift index 063c8cfa..5040fbd4 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsectionModel.swift @@ -16,13 +16,13 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo public static var identifier: String = "list1CTxtDiv3" public var headline: LabelModel - public var body: LabelModel + public var body: LabelModel? //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(headline: LabelModel, body: LabelModel) { + public init(headline: LabelModel, body: LabelModel?) { self.headline = headline self.body = body super.init() @@ -54,7 +54,7 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) headline = try typeContainer.decode(LabelModel.self, forKey: .headline) - body = try typeContainer.decode(LabelModel.self, forKey: .body) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) try super.init(from: decoder) } @@ -63,6 +63,6 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(headline, forKey: .headline) - try container.encode(body, forKey: .body) + try container.encodeIfPresent(body, forKey: .body) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift index 02d320a9..2f023b78 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift @@ -53,9 +53,7 @@ import Foundation super.set(with: model, delegateObject, additionalData) guard let model = model as? ListOneColumnTextWithWhitespaceDividerShortModel else { return } - - headline.set(with: model.headline, delegateObject, additionalData) - body.set(with: model.body, delegateObject, additionalData) + stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData) updateAccessibilityLabel() } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift index f6303a85..66025760 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShortModel.swift @@ -16,13 +16,13 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo public static var identifier: String = "list1CTxtDiv1" public var headline: LabelModel - public var body: LabelModel + public var body: LabelModel? //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(headline: LabelModel, body: LabelModel) { + public init(headline: LabelModel, body: LabelModel?) { self.headline = headline self.body = body super.init() @@ -54,7 +54,7 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) headline = try typeContainer.decode(LabelModel.self, forKey: .headline) - body = try typeContainer.decode(LabelModel.self, forKey: .body) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) try super.init(from: decoder) } @@ -63,6 +63,6 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(headline, forKey: .headline) - try container.encode(body, forKey: .body) + try container.encodeIfPresent(body, forKey: .body) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift index 704057db..62ee43f5 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift @@ -52,9 +52,7 @@ import Foundation super.set(with: model, delegateObject, additionalData) guard let model = model as? ListOneColumnTextWithWhitespaceDividerTallModel else { return } - - headline.set(with: model.headline, delegateObject, additionalData) - body.set(with: model.body, delegateObject, additionalData) + stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData) updateAccessibilityLabel() } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift index e3bb634d..c713b0d2 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTallModel.swift @@ -16,13 +16,13 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol public static var identifier: String = "list1CTxtDiv2" public var headline: LabelModel - public var body: LabelModel + public var body: LabelModel? //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(headline: LabelModel, body: LabelModel) { + public init(headline: LabelModel, body: LabelModel?) { self.headline = headline self.body = body super.init() @@ -54,7 +54,7 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) headline = try typeContainer.decode(LabelModel.self, forKey: .headline) - body = try typeContainer.decode(LabelModel.self, forKey: .body) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) try super.init(from: decoder) } @@ -63,6 +63,6 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(headline, forKey: .headline) - try container.encode(body, forKey: .body) + try container.encodeIfPresent(body, forKey: .body) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillChangesDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillChangesDivider.swift index c4a42835..32425fca 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillChangesDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillChangesDivider.swift @@ -62,7 +62,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 120 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillHistoryDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillHistoryDivider.swift index 1246e98c..64830441 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillHistoryDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnBillHistoryDivider.swift @@ -49,7 +49,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift index 7fe35b92..dd2ecc03 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift @@ -61,7 +61,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnInternationalDataDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnInternationalDataDivider.swift index 1d842266..51913799 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnInternationalDataDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnInternationalDataDivider.swift @@ -60,7 +60,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift index 9e5c2f05..c75c77df 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift @@ -62,7 +62,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnSpeedTestDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnSpeedTestDivider.swift index 91a86643..c23a5cdc 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnSpeedTestDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnSpeedTestDivider.swift @@ -61,7 +61,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/TwoColumn/ListTwoColumnSubsectionDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/TwoColumn/ListTwoColumnSubsectionDivider.swift index b3972ae6..ddcc27c1 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/TwoColumn/ListTwoColumnSubsectionDivider.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/TwoColumn/ListTwoColumnSubsectionDivider.swift @@ -58,7 +58,7 @@ import Foundation updateAccessibilityLabel() } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } diff --git a/MVMCoreUI/Atomic/Molecules/FooterModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/FooterModel.swift rename to MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift diff --git a/MVMCoreUI/Atomic/Molecules/FooterView.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterView.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/FooterView.swift rename to MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterView.swift diff --git a/MVMCoreUI/Atomic/Molecules/Header.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/Header.swift rename to MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift diff --git a/MVMCoreUI/Atomic/Molecules/HeaderModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/HeaderModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/HeaderModel.swift rename to MVMCoreUI/Atomic/Molecules/HeadersAndFooters/HeaderModel.swift diff --git a/MVMCoreUI/Atomic/Molecules/MoleculeHeaderModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/MoleculeHeaderModel.swift rename to MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderModel.swift diff --git a/MVMCoreUI/Atomic/Molecules/MoleculeHeaderView.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/MoleculeHeaderView.swift rename to MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift new file mode 100644 index 00000000..2e2f48b2 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooter.swift @@ -0,0 +1,57 @@ +// +// MoleculeSectionFooter.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/5/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class MoleculeSectionFooter: SectionHeaderFooterView { + open var molecule: MoleculeViewProtocol? + public let containerHelper = ContainerHelper() + + /// Adds the molecule to the view. + open func addMolecule(_ molecule: MoleculeViewProtocol) { + contentView.addSubview(molecule) + containerHelper.constrainView(molecule) + molecule.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) + self.molecule = molecule + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + containerHelper.updateViewMargins(self, model: model as? MoleculeSectionFooterModel, size: size) + contentView.directionalLayoutMargins = directionalLayoutMargins + (molecule as? MVMCoreViewProtocol)?.updateView(size) + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + 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) { + addMolecule(moleculeView) + } + containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol) + } + + open override func reset() { + super.reset() + molecule?.reset() + } + + public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return MoleculeContainer.nameForReuse(with: model, delegateObject) + } + + public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + return MoleculeContainer.requiredModules(with: model, delegateObject, error: error) + } + + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 80.0 + } +} diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooterModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooterModel.swift new file mode 100644 index 00000000..edf9fc7a --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionFooterModel.swift @@ -0,0 +1,31 @@ +// +// MoleculeSectionFooterModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/5/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class MoleculeSectionFooterModel: MoleculeContainerModel, SectionListHeaderFooterModel { + public class override var identifier: String { + return "sectionFooter" + } + + /// Defaults to set + public override func setDefaults() { + if useHorizontalMargins == nil { + useHorizontalMargins = true + } + if useVerticalMargins == nil { + useVerticalMargins = true + } + if topPadding == nil { + topPadding = PaddingDefaultVerticalSpacing3 + } + if bottomPadding == nil { + bottomPadding = PaddingDefaultVerticalSpacing3 + } + } +} diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift new file mode 100644 index 00000000..a8623517 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeader.swift @@ -0,0 +1,72 @@ +// +// MoleculeSectionHeader.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/2/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class MoleculeSectionHeader: SectionHeaderFooterView { + open var molecule: MoleculeViewProtocol? + public let containerHelper = ContainerHelper() + public let line = Line() + + /// Adds the molecule to the view. + open func addMolecule(_ molecule: MoleculeViewProtocol) { + contentView.addSubview(molecule) + containerHelper.constrainView(molecule) + molecule.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) + self.molecule = molecule + } + + public override func setupView() { + super.setupView() + line.setStyle(.thin) + contentView.addSubview(line) + NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true + NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true + NSLayoutConstraint.pinViewRight(toSuperview: line, useMargins: true, constant: 0).isActive = true + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + containerHelper.updateViewMargins(self, model: model as? MoleculeSectionHeaderModel, size: size) + contentView.directionalLayoutMargins = directionalLayoutMargins + (molecule as? MVMCoreViewProtocol)?.updateView(size) + line.updateView(size) + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + 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) { + addMolecule(moleculeView) + } + containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol) + if let lineModel = model.line { + line.set(with: lineModel, delegateObject, additionalData) + } + } + + open override func reset() { + super.reset() + line.setStyle(.thin) + molecule?.reset() + } + + public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return MoleculeContainer.nameForReuse(with: model, delegateObject) + } + + public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + return MoleculeContainer.requiredModules(with: model, delegateObject, error: error) + } + + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 80.0 + } +} diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeaderModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeaderModel.swift new file mode 100644 index 00000000..ef6b057e --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeSectionHeaderModel.swift @@ -0,0 +1,52 @@ +// +// MoleculeSectionHeaderModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/2/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class MoleculeSectionHeaderModel: MoleculeContainerModel, SectionListHeaderFooterModel { + public class override var identifier: String { + return "sectionHeader" + } + public var line: LineModel? + + private enum CodingKeys: String, CodingKey { + case line + case backgroundColor + } + + /// Defaults to set + public override func setDefaults() { + if useHorizontalMargins == nil { + useHorizontalMargins = true + } + if useVerticalMargins == nil { + useVerticalMargins = true + } + if topPadding == nil { + topPadding = PaddingDefaultVerticalSpacing3 + } + if bottomPadding == nil { + bottomPadding = PaddingDefaultVerticalSpacing3 + } + if line == nil { + line = LineModel(type: .thin) + } + } + + required public init(from decoder: Decoder) throws { + try super.init(from: decoder) + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(line, forKey: .line) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift index bf3714bd..f6fe580f 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift @@ -34,26 +34,14 @@ open class MoleculeCollectionViewCell: CollectionViewCell { } open override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule else { return "\(self)<>" } - let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel) - let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName - return "\(self)<\(moleculeName)>" + return MoleculeContainer.nameForReuse(with: model, delegateObject) } open override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule, - let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel) - else { return nil } - - return theClass.requiredModules(with: moleculeModel, delegateObject, error: error) + return MoleculeContainer.requiredModules(with: model, delegateObject, error: error) } - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - guard let model = model as? MoleculeCollectionItemModel, - let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(model.molecule), - let height = classType.estimatedHeight(with: model.molecule, delegateObject) - else { return 100 } - - return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0) + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 100 } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift index bee9d612..1028362e 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift @@ -10,7 +10,7 @@ import Foundation import MVMCore -@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeModelProtocol { +@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeContainerModelProtocol, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift index 532c21f4..92d04bed 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift @@ -30,28 +30,16 @@ import UIKit } public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule else { return "\(self)<>" } - - let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel) - let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName - - return "\(self)<\(moleculeName)>" + return MoleculeContainer.nameForReuse(with: model, delegateObject) } public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule, - let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel) - else { return nil } - - return theClass.requiredModules(with: moleculeModel, delegateObject, error: error) + return MoleculeContainer.requiredModules(with: model, delegateObject, error: error) } - public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule, - let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel), - let height = classType.estimatedHeight(with: moleculeModel, delegateObject) + public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let height = MoleculeContainer.estimatedHeight(with: model, delegateObject) else { return 80 } - - return max(2 * PaddingDefaultVerticalSpacing3, height) + return height } } diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift index be3ac62e..3f8ff8a7 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift @@ -157,7 +157,7 @@ import UIKit bottomRightLabel.setFontStyle(.RegularMicro) } - public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 34 } diff --git a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift index b2b52573..14be7809 100644 --- a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift @@ -18,6 +18,15 @@ import Foundation } public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]? public var line: LineModel? + + /// This template requires content. + func validateModelHasContent() throws { + if header == nil, + molecules?.count ?? 0 == 0, + footer == nil { + throw ModelRegistry.Error.decoderOther(message: "List template requires atleast one of the following: header, footer, molecules") + } + } //-------------------------------------------------- // MARK: - Initializer @@ -47,6 +56,7 @@ import Foundation molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) try super.init(from: decoder) + try validateModelHasContent() } open override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index 372ae778..70416491 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -14,24 +14,15 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Stored Properties //-------------------------------------------------- - public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? + public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)]? var observer: NSKeyValueObservation? public var templateModel: ListPageTemplateModel? - + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- - open override func parsePageJSON() throws { - try parseTemplate(json: loadObject?.pageJSON) - try super.parsePageJSON() - } - - // For subclassing the model. - open func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ListPageTemplateModel { - return try decoder.decode(ListPageTemplateModel.self, from: data) - } open override var loadObject: MVMCoreLoadObject? { didSet { @@ -50,6 +41,16 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- + + open override func parsePageJSON() throws { + try parseTemplate(json: loadObject?.pageJSON) + try super.parsePageJSON() + } + + // For subclassing the model. + open func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ListPageTemplateModel { + return try decoder.decode(ListPageTemplateModel.self, from: data) + } open override func viewForTop() -> UIView { guard let headerModel = templateModel?.header, @@ -72,21 +73,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol return molecule } - open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { - - guard super.shouldFinishProcessingLoad(loadObject, error: error) else { return false } - - // This template requires atleast one of the three layers. - if templateModel?.header == nil, - templateModel?.molecules?.count ?? 0 == 0, - templateModel?.footer == nil, - let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), messageToLog: "List template requires atleast one of the following: header, footer, molecules", code: CoreUIErrorCode.ErrorCodeListMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) { - error.pointee = errorObject - return false - } - return true - } - open override func handleNewData() { topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false @@ -109,7 +95,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - guard let moleculeInfo = moleculesInfo?[indexPath.row], + guard let moleculeInfo = getMoleculeInfo(for: indexPath), let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) else { return 0 } @@ -122,7 +108,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let moleculeInfo = moleculesInfo?[indexPath.row], + guard let moleculeInfo = getMoleculeInfo(for: indexPath), let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) else { return UITableViewCell() } @@ -175,7 +161,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var indexPaths: [IndexPath] = [] for molecule in molecules { - if let info = self.getMoleculeInfo(with: molecule) { + if let info = self.createMoleculeInfo(with: molecule) { self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier) let index = indexPath.row + 1 + indexPaths.count self.moleculesInfo?.insert(info, at: index) @@ -211,8 +197,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Convenience //-------------------------------------------------- - /// Returns the (identifier, class) of the molecule for the given map. - func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? { + /// Returns the (identifier, class) of the molecule for the given model. + func createMoleculeInfo(with listItem: MoleculeModelProtocol?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { guard let listItem = listItem, let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem) @@ -223,14 +209,19 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol return (moleculeName, moleculeClass, listItem) } + /// Returns the (identifier, class) of the molecule for the indexPath. + func getMoleculeInfo(for indexPath: IndexPath) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { + return moleculesInfo?[indexPath.row] + } + /// Sets up the molecule list and ensures no errors loading all content. - func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? { + func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)]? { - var moleculeList: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)] = [] + var moleculeList: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)] = [] if let molecules = templateModel?.molecules { for molecule in molecules { - if let info = getMoleculeInfo(with: molecule) { + if let info = createMoleculeInfo(with: molecule) { moleculeList.append(info) } } diff --git a/MVMCoreUI/Atomic/Templates/SectionListTemplate.swift b/MVMCoreUI/Atomic/Templates/SectionListTemplate.swift new file mode 100644 index 00000000..bc12146f --- /dev/null +++ b/MVMCoreUI/Atomic/Templates/SectionListTemplate.swift @@ -0,0 +1,137 @@ +// +// SectionListTemplate.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 9/25/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class SectionListTemplate: MoleculeListTemplate { + + public var sectionMoleculesInfo: [(header: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, footer: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)])]? + + open override func viewDidLoad() { + super.viewDidLoad() + tableView.sectionHeaderHeight = UITableView.automaticDimension + } + + override func setup() { + // Create quick reference + var sectionList: [(header: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, footer: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)])] = [] + + if let sections = (templateModel as? SectionListTemplateModel)?.sections { + for section in sections { + let header = createMoleculeInfo(with: section.header) + let footer = createMoleculeInfo(with: section.footer) + var rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)] = [] + for row in section.rows { + if let rowInfo = createMoleculeInfo(with: row) { + rows.append(rowInfo) + } + } + sectionList.append((header: header, footer: footer, rows: rows)) + } + } + + sectionMoleculesInfo = sectionList.count > 0 ? sectionList : nil + } + + override func getMoleculeInfo(for indexPath: IndexPath) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { + return sectionMoleculesInfo?[indexPath.section].rows[indexPath.row] + } + + open override func createTableView() -> TableView { + let tableView = TableView(frame: .zero, style: .plain) + tableView.backgroundColor = .clear + tableView.separatorStyle = UITableViewCell.SeparatorStyle.none + tableView.delegate = self + tableView.dataSource = self + tableView.insetsContentViewsToSafeArea = false + return tableView + } + + // For subclassing the model. + open override func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> SectionListTemplateModel { + return try decoder.decode(SectionListTemplateModel.self, from: data) + } + + open override func registerWithTable() { + super.registerWithTable() + guard let sections = sectionMoleculesInfo else { return } + for section in sections { + if let header = section.header { + tableView.register(header.class, forHeaderFooterViewReuseIdentifier: header.identifier) + } + if let footer = section.footer { + tableView.register(footer.class, forHeaderFooterViewReuseIdentifier: footer.identifier) + } + for row in section.rows { + tableView.register(row.class, forCellReuseIdentifier: row.identifier) + } + } + } + + public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { + guard let moleculeInfo = sectionMoleculesInfo?[section].header else { + return CGFloat.leastNormalMagnitude + } + let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) + return estimatedHeight ?? 80 + } + + public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + guard (sectionMoleculesInfo?[section].header) != nil else { + return CGFloat.leastNormalMagnitude + } + return UITableView.automaticDimension + } + + public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat { + guard let moleculeInfo = sectionMoleculesInfo?[section].footer else { + return CGFloat.leastNormalMagnitude + } + let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) + return estimatedHeight ?? 80 + } + + public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + guard (sectionMoleculesInfo?[section].footer) != nil else { + return CGFloat.leastNormalMagnitude + } + return UITableView.automaticDimension + } + + public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let sectionInfo = sectionMoleculesInfo?[section], + let headerInfo = sectionInfo.header else { return nil } + let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerInfo.identifier) + (header as? MoleculeViewProtocol)?.reset() + (header as? MoleculeViewProtocol)?.set(with: headerInfo.molecule, delegateObjectIVar, nil) + (header as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width) + // Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells + header?.layoutIfNeeded() + return header + } + + public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + guard let sectionInfo = sectionMoleculesInfo?[section], + let footerInfo = sectionInfo.footer else { return nil } + let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerInfo.identifier) + (footer as? MoleculeViewProtocol)?.reset() + (footer as? MoleculeViewProtocol)?.set(with: footerInfo.molecule, delegateObjectIVar, nil) + (footer as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width) + // Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells + footer?.layoutIfNeeded() + return footer + } + + open override func getNumberOfSections() -> Int { + return sectionMoleculesInfo?.count ?? 0 + } + + open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return sectionMoleculesInfo?[section].rows.count ?? 0 + } +} diff --git a/MVMCoreUI/Atomic/Templates/SectionListTemplateModel.swift b/MVMCoreUI/Atomic/Templates/SectionListTemplateModel.swift new file mode 100644 index 00000000..280ea4e5 --- /dev/null +++ b/MVMCoreUI/Atomic/Templates/SectionListTemplateModel.swift @@ -0,0 +1,91 @@ +// +// SectionListTemplateModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 9/25/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol SectionListHeaderFooterModel { + +} + +@objcMembers open class SectionModel: Codable { + public var header: (SectionListHeaderFooterModel & MoleculeModelProtocol)? + public var footer: (SectionListHeaderFooterModel & MoleculeModelProtocol)? + public var rows: [ListItemModelProtocol & MoleculeModelProtocol] + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case header + case footer + case rows + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + header = try typeContainer.decodeModelIfPresent(codingKey: .header) + footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) + rows = try typeContainer.decodeModels(codingKey: .rows) + } + + open func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModelIfPresent(header, forKey: .header) + try container.encodeModelIfPresent(footer, forKey: .footer) + try container.encodeModels(rows, forKey: .rows) + } +} + +@objcMembers open class SectionListTemplateModel: ListPageTemplateModel { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + open override class var identifier: String { + return "sectionList" + } + + public var sections: [SectionModel] + + override func validateModelHasContent() throws { + if header == nil, + sections.count == 0, + footer == nil { + throw ModelRegistry.Error.decoderOther(message: "Section List template requires atleast one of the following: header, footer, sections") + } + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case sections + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + sections = try typeContainer.decode([SectionModel].self, forKey: .sections) + 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) + try container.encode(sections, forKey: .sections) + } +} diff --git a/MVMCoreUI/BaseClasses/SectionHeaderFooterView.swift b/MVMCoreUI/BaseClasses/SectionHeaderFooterView.swift new file mode 100644 index 00000000..b4b7f8eb --- /dev/null +++ b/MVMCoreUI/BaseClasses/SectionHeaderFooterView.swift @@ -0,0 +1,85 @@ +// +// SectionHeaderFooterView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/2/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class SectionHeaderFooterView: UITableViewHeaderFooterView, MoleculeViewProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + open var model: MoleculeModelProtocol? + + private var initialSetupPerformed = false + + //-------------------------------------------------- + // MARK: - Initialization + //-------------------------------------------------- + + public override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + public func initialSetup() { + if !initialSetupPerformed { + initialSetupPerformed = true + setupView() + } + } + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + self.model = model + if let backgroundColor = model.backgroundColor { + contentView.backgroundColor = backgroundColor.uiColor + } + } + + open func reset() { + contentView.backgroundColor = .white + } + + // MARK: Overridables + // Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead. + open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + return model.moleculeName + } + + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return nil + } + + open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + return nil + } +} + +// MARK:- MVMCoreViewProtocol +extension SectionHeaderFooterView: MVMCoreViewProtocol { + + open func updateView(_ size: CGFloat) { } + + /// Will be called only once. + open func setupView() { + translatesAutoresizingMaskIntoConstraints = false + insetsLayoutMarginsFromSafeArea = false + preservesSuperviewLayoutMargins = false + contentView.insetsLayoutMarginsFromSafeArea = false + contentView.preservesSuperviewLayoutMargins = false + MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0) + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift index 36f13be0..efd70570 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift @@ -20,6 +20,7 @@ public extension MVMCoreUIViewControllerMappingObject { register(template: MoleculeListTemplate.self) add(toTemplateViewControllerMapping: ["modalList": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeListTemplate.self)!]) + add(toTemplateViewControllerMapping: [SectionListTemplateModel.identifier: MVMCoreViewControllerProgrammaticMappingObject(with: SectionListTemplate.self)!]) register(template: ThreeLayerTemplate.self) register(template: ThreeLayerCenterTemplate.self)