merge
This commit is contained in:
commit
17b5c6401a
@ -139,6 +139,8 @@
|
||||
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; };
|
||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */; };
|
||||
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; };
|
||||
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */; };
|
||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; };
|
||||
8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; };
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; };
|
||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; };
|
||||
@ -190,16 +192,22 @@
|
||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; };
|
||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; };
|
||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; };
|
||||
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; };
|
||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; };
|
||||
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */; };
|
||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; };
|
||||
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; };
|
||||
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; };
|
||||
BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; };
|
||||
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; };
|
||||
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; };
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; };
|
||||
BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */; };
|
||||
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */; };
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */; };
|
||||
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */; };
|
||||
BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; };
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; };
|
||||
BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; };
|
||||
@ -224,6 +232,7 @@
|
||||
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; };
|
||||
D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; };
|
||||
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; };
|
||||
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092348244A51D40044AD09 /* RadioSwatchModel.swift */; };
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; };
|
||||
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
||||
@ -568,6 +577,8 @@
|
||||
8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItemModel.swift; sourceTree = "<group>"; };
|
||||
8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = "<group>"; };
|
||||
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalDataModel.swift; sourceTree = "<group>"; };
|
||||
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = "<group>"; };
|
||||
8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; };
|
||||
@ -618,16 +629,22 @@
|
||||
AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = "<group>"; };
|
||||
AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = "<group>"; };
|
||||
AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = "<group>"; };
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = "<group>"; };
|
||||
AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
||||
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = "<group>"; };
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = "<group>"; };
|
||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = "<group>"; };
|
||||
BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = "<group>"; };
|
||||
BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = "<group>"; };
|
||||
BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyText.swift; sourceTree = "<group>"; };
|
||||
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = "<group>"; };
|
||||
BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = "<group>"; };
|
||||
BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = "<group>"; };
|
||||
@ -652,6 +669,7 @@
|
||||
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = "<group>"; };
|
||||
D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = "<group>"; };
|
||||
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchModel.swift; sourceTree = "<group>"; };
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
|
||||
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||
@ -1097,6 +1115,10 @@
|
||||
AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */,
|
||||
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */,
|
||||
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */,
|
||||
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */,
|
||||
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */,
|
||||
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */,
|
||||
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */,
|
||||
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */,
|
||||
C7F8012023E8303200396FBD /* ListRVWheel.swift */,
|
||||
);
|
||||
@ -1435,6 +1457,11 @@
|
||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */,
|
||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
|
||||
);
|
||||
path = Selectors;
|
||||
sourceTree = "<group>";
|
||||
@ -2046,6 +2073,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */,
|
||||
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
|
||||
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
|
||||
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */,
|
||||
@ -2062,6 +2090,7 @@
|
||||
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */,
|
||||
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */,
|
||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */,
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */,
|
||||
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
||||
@ -2091,6 +2120,7 @@
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */,
|
||||
012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */,
|
||||
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */,
|
||||
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */,
|
||||
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
|
||||
D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */,
|
||||
@ -2106,6 +2136,7 @@
|
||||
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */,
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */,
|
||||
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */,
|
||||
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */,
|
||||
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
|
||||
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
|
||||
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */,
|
||||
@ -2165,6 +2196,7 @@
|
||||
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */,
|
||||
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */,
|
||||
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
|
||||
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */,
|
||||
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */,
|
||||
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
|
||||
01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */,
|
||||
@ -2211,12 +2243,14 @@
|
||||
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
|
||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
|
||||
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */,
|
||||
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
|
||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
|
||||
01EB368F23609801006832FA /* LabelModel.swift in Sources */,
|
||||
0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */,
|
||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
|
||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
|
||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */,
|
||||
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
|
||||
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */,
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
|
||||
@ -2224,6 +2258,7 @@
|
||||
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */,
|
||||
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
||||
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
|
||||
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
||||
D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */,
|
||||
@ -2326,6 +2361,7 @@
|
||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
|
||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
||||
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
||||
|
||||
@ -32,7 +32,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
|
||||
public var disabledFillColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
public var disabledBorderColor: Color?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var groupName: String = ""
|
||||
|
||||
public func setValidity(_ valid: Bool, group: FormGroupRule) {
|
||||
enabled = valid
|
||||
|
||||
@ -39,7 +39,7 @@ open class RadioBox: Control {
|
||||
super.setupView()
|
||||
|
||||
layer.delegate = self
|
||||
layer.borderColor = UIColor.black.cgColor
|
||||
layer.borderColor = UIColor.mvmCoolGray6.cgColor
|
||||
layer.borderWidth = 1
|
||||
|
||||
label.numberOfLines = 1
|
||||
@ -60,7 +60,7 @@ open class RadioBox: Control {
|
||||
|
||||
// MARK: - MoleculeViewProtocol
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? RadioBoxModel else { return }
|
||||
isSelected = model.selected
|
||||
@ -69,6 +69,15 @@ open class RadioBox: Control {
|
||||
subTextLabel.text = model.subText
|
||||
isOutOfStock = model.strikethrough
|
||||
subTextLabelHeightConstraint?.isActive = (subTextLabel.text?.count ?? 0) == 0
|
||||
if let color = model.selectedAccentColor?.uiColor {
|
||||
accentColor = color
|
||||
}
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .white
|
||||
accentColor = .mvmRed
|
||||
}
|
||||
|
||||
// MARK: - State Handling
|
||||
@ -77,11 +86,12 @@ open class RadioBox: Control {
|
||||
// Draw the strikethrough
|
||||
strikeLayer?.removeFromSuperlayer()
|
||||
if isOutOfStock {
|
||||
let line = getStrikeThrough(color: .black, thickness: 1)
|
||||
let line = getStrikeThrough(color: isSelected ? .black : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(line)
|
||||
strikeLayer = line
|
||||
}
|
||||
|
||||
|
||||
// Draw the border
|
||||
borderLayer?.removeFromSuperlayer()
|
||||
if isSelected {
|
||||
@ -98,6 +108,7 @@ open class RadioBox: Control {
|
||||
if !isEnabled {
|
||||
let mask = getMaskLayer()
|
||||
layer.mask = mask
|
||||
maskLayer = mask
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +119,7 @@ open class RadioBox: Control {
|
||||
}
|
||||
|
||||
@objc open func selectBox() {
|
||||
guard isEnabled else { return }
|
||||
isSelected = true
|
||||
radioBoxModel?.selected = isSelected
|
||||
layer.setNeedsDisplay()
|
||||
@ -131,7 +143,7 @@ open class RadioBox: Control {
|
||||
|
||||
let topLineLayer = CAShapeLayer()
|
||||
topLineLayer.fillColor = nil
|
||||
topLineLayer.strokeColor = UIColor.mvmRed.cgColor
|
||||
topLineLayer.strokeColor = accentColor.cgColor
|
||||
topLineLayer.lineWidth = 4
|
||||
topLineLayer.path = topLinePath.cgPath
|
||||
layer.addSublayer(topLineLayer)
|
||||
|
||||
@ -8,7 +8,12 @@
|
||||
|
||||
import Foundation
|
||||
open class RadioBoxCollectionViewCell: CollectionViewCell {
|
||||
let radioBox = RadioBox()
|
||||
public let radioBox = RadioBox()
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
@ -11,8 +11,8 @@ import Foundation
|
||||
public static var identifier: String = "radioBox"
|
||||
public var text: String
|
||||
public var subText: String?
|
||||
public var backgroundColor: Color? = Color(uiColor: .white)
|
||||
public var selectedAccentColor = Color(uiColor: .mvmRed)
|
||||
public var backgroundColor: Color?
|
||||
public var selectedAccentColor: Color?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var strikethrough: Bool = false
|
||||
@ -34,12 +34,8 @@ import Foundation
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
text = try typeContainer.decode(String.self, forKey: .text)
|
||||
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) {
|
||||
selectedAccentColor = color
|
||||
}
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
||||
backgroundColor = color
|
||||
}
|
||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||
selected = isSelected
|
||||
}
|
||||
@ -58,7 +54,7 @@ import Foundation
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(text, forKey: .text)
|
||||
try container.encodeIfPresent(subText, forKey: .subText)
|
||||
try container.encode(selectedAccentColor, forKey: .selectedAccentColor)
|
||||
try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
|
||||
@ -15,7 +15,11 @@ open class RadioBoxes: View {
|
||||
private let boxWidth: CGFloat = 151.0
|
||||
private let boxHeight: CGFloat = 64.0
|
||||
private let itemSpacing: CGFloat = 8.0
|
||||
|
||||
private var numberOfColumns: CGFloat = 2.0
|
||||
private var radioBoxesModel: RadioBoxesModel? {
|
||||
return model as? RadioBoxesModel
|
||||
}
|
||||
|
||||
private var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
/// The models for the molecules.
|
||||
@ -42,7 +46,7 @@ open class RadioBoxes: View {
|
||||
}
|
||||
|
||||
// MARK: - MoleculeViewProtocol
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
@ -94,7 +98,7 @@ open class RadioBoxes: View {
|
||||
}
|
||||
|
||||
// Calculate the height
|
||||
let rows = ceil(CGFloat(boxes.count) / 2.0)
|
||||
let rows = ceil(CGFloat(boxes.count) / numberOfColumns)
|
||||
let height = (rows * boxHeight) + ((rows - 1) * itemSpacing)
|
||||
collectionViewHeight?.constant = height
|
||||
}
|
||||
@ -102,7 +106,7 @@ open class RadioBoxes: View {
|
||||
|
||||
extension RadioBoxes: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / 2
|
||||
let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / numberOfColumns
|
||||
return CGSize(width: itemWidth, height: boxHeight)
|
||||
}
|
||||
}
|
||||
@ -117,7 +121,16 @@ extension RadioBoxes: UICollectionViewDataSource {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else {
|
||||
fatalError()
|
||||
}
|
||||
cell.reset()
|
||||
cell.radioBox.isUserInteractionEnabled = false
|
||||
|
||||
if let color = radioBoxesModel?.boxesColor {
|
||||
cell.radioBox.backgroundColor = color.uiColor
|
||||
}
|
||||
if let color = radioBoxesModel?.selectedAccentColor {
|
||||
cell.radioBox.accentColor = color.uiColor
|
||||
}
|
||||
|
||||
cell.set(with: molecule, delegateObject, nil)
|
||||
cell.updateView(size ?? collectionView.bounds.width)
|
||||
if molecule.selected {
|
||||
@ -129,13 +142,18 @@ extension RadioBoxes: UICollectionViewDataSource {
|
||||
}
|
||||
|
||||
extension RadioBoxes: UICollectionViewDelegate {
|
||||
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||
guard let molecule = boxes?[indexPath.row] else { return false }
|
||||
return molecule.enabled
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
||||
cell.radioBox.selectBox()
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
||||
cell.radioBox.deselectBox()
|
||||
}
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
import Foundation
|
||||
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
public static var identifier: String = "radioBoxes"
|
||||
public var boxes: [RadioBoxModel]
|
||||
public var backgroundColor: Color?
|
||||
public var selectedAccentColor: Color?
|
||||
public var boxes: [RadioBoxModel]
|
||||
public var boxesColor: Color?
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
@ -28,6 +29,7 @@ import Foundation
|
||||
case moleculeName
|
||||
case selectedAccentColor
|
||||
case backgroundColor
|
||||
case boxesColor
|
||||
case boxes
|
||||
case fieldKey
|
||||
case groupName
|
||||
@ -37,6 +39,7 @@ import Foundation
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
boxesColor = try typeContainer.decodeIfPresent(Color.self, forKey: .boxesColor)
|
||||
boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
|
||||
166
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift
Normal file
166
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift
Normal file
@ -0,0 +1,166 @@
|
||||
//
|
||||
// RadioSwatch.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 01/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
open class RadioSwatch: Control {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public let bottomText = Label.createLabelRegularMicro(true)
|
||||
|
||||
private var circleLayer: CAShapeLayer?
|
||||
private var selectedLayer: CALayer?
|
||||
private var strikeLayer: CALayer?
|
||||
private var maskLayer: CALayer?
|
||||
|
||||
public var radioSwatchModel: RadioSwatchModel? {
|
||||
return model as? RadioSwatchModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
bottomText.updateView(size)
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
addSubview(bottomText)
|
||||
bottomText.textAlignment = .center
|
||||
NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0)
|
||||
addTarget(self, action: #selector(selectSwatch), for: .touchUpInside)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? RadioSwatchModel else { return }
|
||||
isSelected = model.selected
|
||||
isEnabled = model.enabled
|
||||
bottomText.text = model.text
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
isSelected = false
|
||||
isEnabled = true
|
||||
bottomText.text = nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - State Handling
|
||||
//------------------------------------------------------
|
||||
open override func draw(_ layer: CALayer, in ctx: CGContext) {
|
||||
//Draw the swatch
|
||||
circleLayer?.removeFromSuperlayer()
|
||||
let circle = getCircle(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(circle)
|
||||
circleLayer = circle
|
||||
|
||||
//Draw the strikethrough
|
||||
strikeLayer?.removeFromSuperlayer()
|
||||
if radioSwatchModel?.strikethrough ?? false {
|
||||
let line = getStrikeThrough(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(line)
|
||||
strikeLayer = line
|
||||
}
|
||||
|
||||
//Draw the selected layer
|
||||
selectedLayer?.removeFromSuperlayer()
|
||||
if isSelected {
|
||||
let outerCircle = getSelectedLayer(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
|
||||
layer.addSublayer(outerCircle)
|
||||
selectedLayer = outerCircle
|
||||
bottomText.isHidden = false
|
||||
} else {
|
||||
bottomText.isHidden = true
|
||||
}
|
||||
|
||||
//Handle Mask
|
||||
maskLayer?.removeFromSuperlayer()
|
||||
if !isEnabled {
|
||||
let mask = getMaskLayer()
|
||||
layer.mask = mask
|
||||
maskLayer = mask
|
||||
}
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any size changes
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
@objc open func selectSwatch() {
|
||||
guard isEnabled else { return }
|
||||
isSelected = true
|
||||
radioSwatchModel?.selected = isSelected
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
@objc open func deselectSwatch() {
|
||||
isSelected = false
|
||||
radioSwatchModel?.selected = isSelected
|
||||
layer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||
let circle = CAShapeLayer()
|
||||
circle.name = "innercircle"
|
||||
circle.fillColor = radioSwatchModel?.color.cgColor ?? UIColor.blue.cgColor
|
||||
circle.opacity = 1.0
|
||||
circle.lineWidth = thickness
|
||||
circle.strokeColor = color.cgColor
|
||||
|
||||
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
|
||||
circle.path = circlePath.cgPath
|
||||
return circle
|
||||
}
|
||||
|
||||
func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||
let strikeThrough = CAShapeLayer()
|
||||
strikeThrough.name = "strikethrough"
|
||||
strikeThrough.fillColor = nil
|
||||
strikeThrough.opacity = 1.0
|
||||
strikeThrough.lineWidth = thickness
|
||||
strikeThrough.strokeColor = color.cgColor
|
||||
|
||||
let linePath = UIBezierPath()
|
||||
linePath.move(to: CGPoint(x: 12, y: 31))
|
||||
linePath.addLine(to: CGPoint(x: 42, y: 1))
|
||||
strikeThrough.path = linePath.cgPath
|
||||
return strikeThrough
|
||||
}
|
||||
|
||||
func getSelectedLayer(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
|
||||
circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath
|
||||
let circle = CAShapeLayer()
|
||||
circle.name = "outercircle"
|
||||
circle.fillColor = UIColor.clear.cgColor
|
||||
circle.opacity = 1.0
|
||||
circle.lineWidth = thickness
|
||||
circle.strokeColor = color.cgColor
|
||||
|
||||
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
|
||||
circle.path = circlePath.cgPath
|
||||
return circle
|
||||
}
|
||||
|
||||
func getMaskLayer() -> CALayer {
|
||||
let mask = CALayer()
|
||||
mask.backgroundColor = UIColor.white.cgColor
|
||||
mask.opacity = 0.3
|
||||
mask.frame = bounds
|
||||
return mask
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
//
|
||||
// RadioSwatchCollectionViewCell.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
open class RadioSwatchCollectionViewCell: CollectionViewCell {
|
||||
public let radioSwatch = RadioSwatch()
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(radioSwatch)
|
||||
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let model = model as? RadioSwatchModel else { return }
|
||||
radioSwatch.set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
64
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift
Normal file
64
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// RadioSwatchModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/17/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "radioSwatch"
|
||||
public var backgroundColor: Color?
|
||||
public var color: Color = Color(uiColor: .mvmBlue)
|
||||
public var text: String?
|
||||
public var selected: Bool = false
|
||||
public var enabled: Bool = true
|
||||
public var strikethrough: Bool = false
|
||||
public var fieldValue: String?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case color
|
||||
case text
|
||||
case selected
|
||||
case enabled
|
||||
case strikethrough
|
||||
case fieldValue
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
|
||||
self.color = color
|
||||
}
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||
self.selected = selected
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
||||
self.strikethrough = strikethrough
|
||||
}
|
||||
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(color, forKey: .color)
|
||||
try container.encodeIfPresent(text, forKey: .text)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(strikethrough, forKey: .strikethrough)
|
||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
152
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift
Normal file
152
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift
Normal file
@ -0,0 +1,152 @@
|
||||
//
|
||||
// RadioSwatches.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 01/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class RadioSwatches: View {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public var collectionView: CollectionView!
|
||||
public var swatches: [RadioSwatchModel]?
|
||||
private var size: CGFloat?
|
||||
private var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//------------------------------------------------------
|
||||
public var collectionViewHeight: NSLayoutConstraint?
|
||||
private let cellSize: CGFloat = 54.0
|
||||
private let itemSpacing: CGFloat = 8.0
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any collection size changes
|
||||
setHeight()
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
collectionView = createCollectionView()
|
||||
addSubview(collectionView)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
|
||||
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100)
|
||||
collectionViewHeight?.isActive = true
|
||||
}
|
||||
|
||||
@objc override open func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
self.size = size
|
||||
collectionView.updateView(size)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
guard let radioSwatchesModel = model as? RadioSwatchesModel else { return }
|
||||
swatches = radioSwatchesModel.swatches
|
||||
FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate)
|
||||
collectionView.reloadData()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//------------------------------------------------------
|
||||
/// Creates the collection view.
|
||||
open func createCollectionView() -> CollectionView {
|
||||
let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout())
|
||||
collection.dataSource = self
|
||||
collection.delegate = self
|
||||
collection.register(RadioSwatchCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchCollectionViewCell")
|
||||
return collection
|
||||
}
|
||||
|
||||
/// Creates the layout for the collection.
|
||||
open func createCollectionViewLayout() -> UICollectionViewLayout {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .vertical
|
||||
layout.minimumLineSpacing = itemSpacing
|
||||
layout.minimumInteritemSpacing = itemSpacing
|
||||
return layout
|
||||
}
|
||||
|
||||
open func setHeight() {
|
||||
guard let swatches = swatches, swatches.count > 0 else {
|
||||
collectionViewHeight?.constant = 0
|
||||
return
|
||||
}
|
||||
// Calculate the height
|
||||
let swatchesInRow = floor(CGFloat(collectionView.bounds.width/(cellSize + itemSpacing)))
|
||||
let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow)
|
||||
let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1))
|
||||
|
||||
if let oldHeight = collectionViewHeight?.constant,
|
||||
height != oldHeight {
|
||||
// Notify delegate of height change, called async to avoid various race conditions caused while happening while laying out initially.
|
||||
DispatchQueue.main.async {
|
||||
self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
|
||||
}
|
||||
}
|
||||
collectionViewHeight?.constant = CGFloat(height)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Delegate methods
|
||||
//------------------------------------------------------
|
||||
extension RadioSwatches: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
return CGSize(width: cellSize, height: cellSize)
|
||||
}
|
||||
}
|
||||
|
||||
extension RadioSwatches: UICollectionViewDataSource {
|
||||
open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return swatches?.count ?? 0
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchCollectionViewCell", for: indexPath) as? RadioSwatchCollectionViewCell else {
|
||||
fatalError()
|
||||
}
|
||||
cell.reset()
|
||||
cell.radioSwatch.isUserInteractionEnabled = false
|
||||
cell.set(with: molecule, delegateObject, nil)
|
||||
cell.updateView(size ?? collectionView.bounds.width)
|
||||
if molecule.selected {
|
||||
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
|
||||
}
|
||||
cell.layoutIfNeeded()
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
extension RadioSwatches: UICollectionViewDelegate {
|
||||
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||
guard let molecule = swatches?[indexPath.row] else { return false }
|
||||
return molecule.enabled
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
|
||||
cell.radioSwatch.selectSwatch()
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
|
||||
cell.radioSwatch.deselectSwatch()
|
||||
}
|
||||
}
|
||||
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift
Normal file
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// RadioSwatchesModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 31/03/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
public static var identifier: String = "radioSwatches"
|
||||
public var backgroundColor: Color?
|
||||
public var swatches: [RadioSwatchModel]
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
let selectedSwatch = swatches.first { (swatch) -> Bool in
|
||||
return swatch.selected
|
||||
}
|
||||
return selectedSwatch?.fieldValue ?? selectedSwatch?.text
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case swatches
|
||||
case fieldKey
|
||||
case groupName
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
baseValue = formFieldValue()
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(swatches, forKey: .swatches)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encode(groupName, forKey: .groupName)
|
||||
}
|
||||
}
|
||||
@ -70,6 +70,7 @@ import Foundation
|
||||
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)
|
||||
|
||||
// Other Atoms
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
|
||||
@ -142,6 +143,8 @@ import Foundation
|
||||
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: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self)
|
||||
@ -149,7 +152,7 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
|
||||
|
||||
|
||||
// Designed Section Dividers
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeAllTextAndLinks.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListRightVariablePriceChangeAllTextAndLinks: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
|
||||
public let arrow = Arrow(frame: .zero)
|
||||
public let rightLabel = Label.commonLabelB2(true)
|
||||
private let stack: Stack<StackModel>
|
||||
private let arrowStackItem: StackItem
|
||||
private let rightLabelStackItem: StackItem
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//-----------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
|
||||
StackItemModel(horizontalAlignment: .fill),
|
||||
StackItemModel(spacing: 6, horizontalAlignment: .fill)],
|
||||
axis: .horizontal)
|
||||
arrowStackItem = StackItem(andContain: arrow)
|
||||
rightLabelStackItem = StackItem(andContain: rightLabel)
|
||||
let stackItems = [StackItem(andContain: eyebrowHeadlineBodyLink), arrowStackItem, rightLabelStackItem]
|
||||
stack = Stack<StackModel>(with: stackModel, stackItems: stackItems)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-----------------------------------------------------
|
||||
|
||||
open override func alignAccessoryToHero() -> CGPoint? {
|
||||
let heroCenter = super.alignAccessoryToHero()
|
||||
|
||||
// Aligns the center of the right side items to the headline.
|
||||
if let heroCenter = heroCenter {
|
||||
let convertedPoint = stack.convert(heroCenter, from: self)
|
||||
arrowStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY
|
||||
rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY
|
||||
}
|
||||
return heroCenter
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.numberOfLines = 1
|
||||
|
||||
arrow.pinHeightAndWidth()
|
||||
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListRightVariablePriceChangeAllTextAndLinksModel else { return }
|
||||
eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
arrow.set(with: model.arrow, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 121
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeAllTextAndLinksModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListRightVariablePriceChangeAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listRVArwAll"
|
||||
public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel
|
||||
public var rightLabel: LabelModel
|
||||
public var arrow: ArrowModel
|
||||
|
||||
public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel, rightLabel: LabelModel, arrow: ArrowModel) {
|
||||
self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink
|
||||
self.rightLabel = rightLabel
|
||||
self.arrow = arrow
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case eyebrowHeadlineBodyLink
|
||||
case rightLabel
|
||||
case arrow
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
try container.encode(arrow, forKey: .arrow)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeBodyText.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@objcMembers open class ListRightVariablePriceChangeBodyText: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
private let stack: Stack<StackModel>
|
||||
public let headlineBody = HeadlineBody(frame: .zero)
|
||||
public let arrow = Arrow(frame: .zero)
|
||||
public let rightLabel = Label.commonLabelB2(true)
|
||||
let arrowAndRightLabelStack: Stack<StackModel>
|
||||
|
||||
|
||||
// MARK: - Initializers
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
arrowAndRightLabelStack = Stack<StackModel>.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)),
|
||||
(view: rightLabel, model: StackItemModel(horizontalAlignment: .fill))],
|
||||
axis: .horizontal, spacing: 6)
|
||||
stack = Stack<StackModel>.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: arrowAndRightLabelStack, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-----------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
headlineBody.styleListItem()
|
||||
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.numberOfLines = 1
|
||||
|
||||
arrow.pinHeightAndWidth()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
arrowAndRightLabelStack.restack()
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListRightVariablePriceChangeBodyTextModel else { return }
|
||||
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
arrow.set(with: model.arrow, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 80
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
headlineBody.styleListItem()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
//
|
||||
// ListRightVariablePriceChangeBodyTextModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 13/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listRVArwBdy"
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var rightLabel: LabelModel
|
||||
public var arrow: ArrowModel
|
||||
|
||||
public init(headlineBody: HeadlineBodyModel,rightLabel: LabelModel,arrow: ArrowModel) {
|
||||
self.headlineBody = headlineBody
|
||||
self.rightLabel = rightLabel
|
||||
self.arrow = arrow
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
public override func setDefaults() {
|
||||
super.setDefaults()
|
||||
if let headline = headlineBody.headline {
|
||||
headline.hero = 0
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case headlineBody
|
||||
case rightLabel
|
||||
case arrow
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(headlineBody, forKey: .headlineBody)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
try container.encode(arrow, forKey: .arrow)
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@ import UIKit
|
||||
/// For subclasses that want to use a custom accessory view.
|
||||
open var customAccessoryView = false
|
||||
|
||||
private var heroAccessoryCenter: CGPoint?
|
||||
public var heroAccessoryCenter: CGPoint?
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
@ -97,7 +97,7 @@ import UIKit
|
||||
|
||||
// Ensures accessory view aligns to the center y derived from the
|
||||
if let _ = heroAccessoryCenter {
|
||||
alignAccessoryToHero()
|
||||
_ = alignAccessoryToHero()
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,14 +215,16 @@ import UIKit
|
||||
}
|
||||
|
||||
/// NOTE: Should only be called when displayed or about to be displayed.
|
||||
public func alignAccessoryToHero() {
|
||||
public func alignAccessoryToHero() -> CGPoint? {
|
||||
|
||||
// Layout call required to force draw in memory to get dimensions of subviews.
|
||||
layoutIfNeeded()
|
||||
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return }
|
||||
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return nil }
|
||||
let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel)
|
||||
accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y
|
||||
let y = convert(UIView(frame: rect).center, from: heroLabel).y
|
||||
accessoryView?.center.y = y
|
||||
heroAccessoryCenter = accessoryView?.center
|
||||
return heroAccessoryCenter ?? CGPoint(x: 0, y: y)
|
||||
}
|
||||
|
||||
/// Traverses the view hierarchy for a 🦸♂️ heroic Label.
|
||||
@ -269,7 +271,7 @@ import UIKit
|
||||
}
|
||||
|
||||
public func willDisplay() {
|
||||
alignAccessoryToHero()
|
||||
_ = alignAccessoryToHero()
|
||||
}
|
||||
|
||||
// MARK: - Separator
|
||||
|
||||
@ -266,9 +266,7 @@ import UIKit
|
||||
}
|
||||
|
||||
// Handle data for first load. Dispatched to allow subclasses to finish their view did load implementations.
|
||||
DispatchQueue.main.async {
|
||||
self.handleNewDataAndUpdateUI()
|
||||
}
|
||||
self.handleNewDataAndUpdateUI()
|
||||
}
|
||||
|
||||
open override func viewDidLayoutSubviews() {
|
||||
@ -292,8 +290,10 @@ import UIKit
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
// Update the navigation bar ui when view is appearing
|
||||
setNavigationController()
|
||||
// Update the navigation bar ui when view is appearing. Can remove check in the future, see viewControllerReady
|
||||
if manager == nil {
|
||||
setNavigationController()
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewDidAppear(_ animated: Bool) {
|
||||
@ -326,6 +326,10 @@ import UIKit
|
||||
|
||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||
open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||
// TODO: This check and set aren't technically needed anymore. The one in viewwillappear should be enough. However, there is a timing issue with the manager where the screen lays out before the menu shows, so the screen grows off the screen. Can fix in the future.
|
||||
if let _ = self.view {
|
||||
setNavigationController()
|
||||
}
|
||||
// Janky way to track current page.
|
||||
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
||||
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user