Merge branch 'develop' into feature/list_device_complex_link_medium

# Conflicts:
#	MVMCoreUI.xcodeproj/project.pbxproj
This commit is contained in:
Lekshmi S 2020-04-24 12:08:32 +05:30
commit e34e859aa1
41 changed files with 746 additions and 205 deletions

View File

@ -94,6 +94,7 @@
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; }; 0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; };
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */; }; 0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */; };
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */; };
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; }; 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; }; 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; };
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; }; 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; };
@ -102,6 +103,8 @@
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; }; 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; };
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; }; 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; };
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; }; 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */; };
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */; };
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
@ -142,6 +145,8 @@
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; }; 8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; };
8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; }; 8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; };
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; }; 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; };
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */; };
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */; };
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; }; 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; };
8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */; }; 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */; };
942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; }; 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; };
@ -201,6 +206,8 @@
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; };
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; }; AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; };
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; };
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; };
BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; }; BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; };
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; };
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; };
@ -531,6 +538,7 @@
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; };
0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = "<group>"; }; 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = "<group>"; };
0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = "<group>"; }; 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = "<group>"; };
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = "<group>"; };
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = "<group>"; }; 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = "<group>"; }; 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; }; 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; };
@ -541,6 +549,8 @@
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; };
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; }; 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; }; 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = "<group>"; };
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIPickerView+Extension.swift"; sourceTree = "<group>"; };
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; }; 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; };
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; };
0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
@ -581,6 +591,8 @@
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinks.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>"; }; 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>"; }; 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = "<group>"; };
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsage.swift; sourceTree = "<group>"; };
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageModel.swift; sourceTree = "<group>"; };
8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; }; 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; };
8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = "<group>"; }; 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = "<group>"; };
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
@ -639,6 +651,8 @@
AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.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>"; }; 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>"; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = "<group>"; };
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = "<group>"; };
BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.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>"; }; 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>"; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = "<group>"; };
@ -1069,6 +1083,8 @@
children = ( children = (
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */, 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */,
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */, 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */,
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */,
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */,
); );
path = ThreeColumn; path = ThreeColumn;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1153,6 +1169,9 @@
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */, D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */,
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */, D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */,
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */, 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */,
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */,
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */,
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1166,6 +1185,15 @@
path = FourColumn; path = FourColumn;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D20FFFB42451E32100A31DA2 /* Device */ = {
isa = PBXGroup;
children = (
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */,
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */,
);
path = Device;
sourceTree = "<group>";
};
D213347423842FE3008E41B3 /* Controllers */ = { D213347423842FE3008E41B3 /* Controllers */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1364,6 +1392,7 @@
D22B38EA23F4E08B00490EF6 /* List */ = { D22B38EA23F4E08B00490EF6 /* List */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D20FFFB42451E32100A31DA2 /* Device */,
AA2AD114244EE43900BBFFE3 /* DeviceItems */, AA2AD114244EE43900BBFFE3 /* DeviceItems */,
52267A0523FFE0A900906CBA /* OneColumn */, 52267A0523FFE0A900906CBA /* OneColumn */,
D22D8396241FDE4700D3DF69 /* TwoColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */,
@ -2164,6 +2193,7 @@
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */, AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */,
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */,
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */, D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */,
014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */, 014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */,
@ -2199,6 +2229,7 @@
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */,
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */,
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */, AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */, 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */,
@ -2207,6 +2238,7 @@
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */, 525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */,
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */,
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */,
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */, BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */,
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */,
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
@ -2238,6 +2270,7 @@
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */, AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
D2B18B812360945C00A9AEDC /* View.swift in Sources */, D2B18B812360945C00A9AEDC /* View.swift in Sources */,
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */,
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
@ -2343,6 +2376,7 @@
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
0AE14F64238315D2005417F8 /* TextField.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */,
C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */,
@ -2408,6 +2442,7 @@
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */, D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */,
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */, 0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
@ -2424,6 +2459,7 @@
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */, 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */,
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */, 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */,
011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */, 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */,

View File

@ -9,6 +9,7 @@
import UIKit import UIKit
@objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol { @objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol {
public static var identifier: String = "collapseNotification" public static var identifier: String = "collapseNotification"
public var actionType: String public var actionType: String
public var extraParameters: JSONValueDictionary? public var extraParameters: JSONValueDictionary?

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
public class ActionOpenPanelModel: ActionModelProtocol { public class ActionOpenPanelModel: ActionModelProtocol {
public enum Panel: String, Codable { public enum Panel: String, Codable {
case left case left
case right case right

View File

@ -9,6 +9,7 @@
import Foundation import Foundation
@objcMembers public class ActionTopAlertModel: ActionModelProtocol { @objcMembers public class ActionTopAlertModel: ActionModelProtocol {
public static var identifier: String = "topAlert" public static var identifier: String = "topAlert"
public var actionType: String = ActionTopAlertModel.identifier public var actionType: String = ActionTopAlertModel.identifier
public var pageType: String public var pageType: String

View File

@ -69,7 +69,7 @@ import UIKit
textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6) textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6)
textFieldTrailingConstraint?.isActive = true textFieldTrailingConstraint?.isActive = true
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: Padding.Four).isActive = true
dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
} }

View File

@ -31,10 +31,9 @@ import UIKit
return formatter return formatter
}() }()
/// Update the property value to alter the format of how the date is presented.
public var dateFormat: String = "MMM d, y" { public var dateFormat: String = "MMM d, y" {
didSet { didSet { dateFormatter.dateFormat = dateFormat }
dateFormatter.dateFormat = dateFormat
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -69,10 +68,10 @@ import UIKit
public override func setupFieldContainerContent(_ container: UIView) { public override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField) datePicker = UIDatePicker.addDatePicker(to: textField)
datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged) datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged)
datePicker?.timeZone = NSTimeZone.system datePicker?.timeZone = NSTimeZone.system
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: self) UIToolbar.addDismissToolbar(to: textField, delegate: self, action: #selector(dismissFieldInput))
} }
@objc public func setDatePickerDuration(from startDate: Date?, to endDate: Date?, showStartDate: Bool = true) { @objc public func setDatePickerDuration(from startDate: Date?, to endDate: Date?, showStartDate: Bool = true) {
@ -104,7 +103,7 @@ import UIKit
} }
} }
@objc override func dismissFieldInput(_ sender: Any?) { @objc public override func dismissFieldInput(_ sender: Any?) {
setTextWith(date: datePicker?.date) setTextWith(date: datePicker?.date)
super.dismissFieldInput(sender) super.dismissFieldInput(sender)

View File

@ -22,24 +22,25 @@
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case dateFormat case dateFormat
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
if let dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) {
self.dateFormat = dateFormat
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(dateFormat, forKey: .dateFormat) try container.encode(dateFormat, forKey: .dateFormat)
} }
} }

View File

@ -211,7 +211,9 @@ import UIKit
let digitBox = DigitBox() let digitBox = DigitBox()
digitBox.isAccessibilityElement = true digitBox.isAccessibilityElement = true
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: self) let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput))
digitBox.digitField.delegate = self digitBox.digitField.delegate = self
digitBox.digitBoxDelegate = self digitBox.digitBoxDelegate = self
return digitBox return digitBox
@ -246,15 +248,6 @@ import UIKit
} }
} }
@objc public override func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count
}
}
@objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) { @objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectPreviousField = false var selectPreviousField = false
@ -322,7 +315,7 @@ import UIKit
return true return true
} }
@objc override func dismissFieldInput(_ sender: Any?) { @objc public override func dismissFieldInput(_ sender: Any?) {
digitBoxes.forEach { digitBoxes.forEach {
if $0.isSelected { if $0.isSelected {
@ -337,12 +330,18 @@ import UIKit
guard let model = model as? DigitEntryFieldModel else { return } guard let model = model as? DigitEntryFieldModel else { return }
numberOfDigits = model.digits numberOfDigits = model.digits
setAsSecureTextEntry(model.secureEntry)
for digitBox in digitBoxes { if let entryType = model.type {
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self) setAsSecureTextEntry(entryType == .secure || entryType == .password)
} }
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
digitBoxes.forEach {
$0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput))
}
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
} }

View File

@ -17,34 +17,31 @@
} }
public var digits: Int = 4 public var digits: Int = 4
public var secureEntry: Bool = false
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case digits case digits
case secureEntry
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) ?? 4
secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) ?? false if let digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) {
self.digits = digits
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(digits, forKey: .digits) try container.encode(digits, forKey: .digits)
try container.encode(secureEntry, forKey: .secureEntry)
} }
} }

View File

@ -20,7 +20,7 @@ import UIKit
public private(set) var titleLabel: Label = { public private(set) var titleLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontRegularMicro() label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical) label.setContentCompressionResistancePriority(.required, for: .vertical)
return label return label
@ -31,12 +31,12 @@ import UIKit
/// Provides contextual information on the TextField. /// Provides contextual information on the TextField.
public private(set) var feedbackLabel: Label = { public private(set) var feedbackLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontRegularMicro() label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical) label.setContentCompressionResistancePriority(.required, for: .vertical)
return label return label
}() }()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate // MARK: - Delegate
//-------------------------------------------------- //--------------------------------------------------
@ -48,14 +48,6 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
public var isValid: Bool = false public var isValid: Bool = false
public var errorMessage: String?
public var standardMessage: String? {
didSet {
if !showError {
feedback = standardMessage
}
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
@ -75,7 +67,7 @@ import UIKit
public var showError: Bool { public var showError: Bool {
get { return entryFieldContainer.showError } get { return entryFieldContainer.showError }
set (error) { set (error) {
self.feedback = error ? self.errorMessage : self.standardMessage self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
self.entryFieldContainer.showError = error self.entryFieldContainer.showError = error
} }
} }
@ -121,6 +113,10 @@ import UIKit
} }
} }
public var entryFieldModel: EntryFieldModel? {
return model as? EntryFieldModel
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Constraints // MARK: - Constraints
//-------------------------------------------------- //--------------------------------------------------
@ -174,8 +170,6 @@ import UIKit
@objc final public override func setupView() { @objc final public override func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return }
isAccessibilityElement = false isAccessibilityElement = false
setContentCompressionResistancePriority(.required, for: .vertical) setContentCompressionResistancePriority(.required, for: .vertical)
accessibilityElements = [titleLabel, feedbackLabel] accessibilityElements = [titleLabel, feedbackLabel]
@ -193,7 +187,7 @@ import UIKit
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical) entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
setupFieldContainerContent(entryFieldContainer) setupFieldContainerContent(entryFieldContainer)
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4) titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
titleContainerDistance?.isActive = true titleContainerDistance?.isActive = true
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
entryFieldContainerLeading?.isActive = true entryFieldContainerLeading?.isActive = true
@ -202,7 +196,7 @@ import UIKit
addSubview(feedbackLabel) addSubview(feedbackLabel)
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: PaddingOne) feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
feedbackContainerDistance?.isActive = true feedbackContainerDistance?.isActive = true
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
feedbackLabelLeading?.isActive = true feedbackLabelLeading?.isActive = true
@ -217,11 +211,11 @@ import UIKit
entryFieldContainer.refreshUI() entryFieldContainer.refreshUI()
} }
/// Method to override. /**
/// Intended to add the interactive content (i.e. textField) to the entryFieldContainer. Method to override.
@objc open func setupFieldContainerContent(_ container: UIView) { Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
// To be overridden by subclass. */
} @objc open func setupFieldContainerContent(_ container: UIView) { }
@objc open override func updateView(_ size: CGFloat) { @objc open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
@ -240,10 +234,11 @@ import UIKit
backgroundColor = .clear backgroundColor = .clear
isAccessibilityElement = false isAccessibilityElement = false
titleLabel.font = MFStyler.fontRegularMicro() titleLabel.font = Styler.Font.RegularMicro.getFont()
titleLabel.textColor = .mvmBlack titleLabel.textColor = .mvmBlack
feedbackLabel.font = MFStyler.fontRegularMicro() feedbackLabel.font = Styler.Font.RegularMicro.getFont()
feedbackLabel.textColor = .mvmBlack feedbackLabel.textColor = .mvmBlack
feedbackLabel.text = nil
entryFieldContainer.reset() entryFieldContainer.reset()
} }
@ -257,7 +252,6 @@ import UIKit
title = model.title title = model.title
feedback = model.feedback feedback = model.feedback
errorMessage = model.errorMessage
isEnabled = model.enabled isEnabled = model.enabled
if let isLocked = model.locked { if let isLocked = model.locked {

View File

@ -22,29 +22,22 @@ import Foundation
public var backgroundColor: Color? public var backgroundColor: Color?
public var title: String? public var title: String?
public var feedback: String? public var feedback: String?
public var errorMessage: String = "" public var errorMessage: String?
public var enabled: Bool = true public var enabled: Bool = true
public var locked: Bool? public var locked: Bool?
public var selected: Bool? public var selected: Bool?
public var text: String? public var text: String?
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
public var isValid: Bool? { public var isValid: Bool? {
didSet { didSet { updateUI?() }
updateUI?()
}
} }
/// Temporary binding mechanism for the view to update on enable changes. /// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: (() -> Void)? public var updateUI: (() -> ())?
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
@ -62,11 +55,19 @@ import Foundation
case fieldKey case fieldKey
case groupName case groupName
} }
//--------------------------------------------------
// MARK: - Validation Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { public func formFieldValue() -> AnyHashable? {
return text return text
} }
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -76,17 +77,20 @@ import Foundation
baseValue = text baseValue = text
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title) title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? "" errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked) locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text) text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
baseValue = text baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
@ -100,11 +104,11 @@ import Foundation
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(title, forKey: .title)
try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(feedback, forKey: .feedback)
try container.encode(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled)
try container.encode(locked, forKey: .locked)
try container.encode(selected, forKey: .selected)
try container.encodeIfPresent(text, forKey: .text) try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(locked, forKey: .locked)
try container.encodeIfPresent(selected, forKey: .selected)
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(groupName, forKey: .groupName)
} }

View File

@ -8,6 +8,8 @@
import UIKit import UIKit
public typealias TextFieldAndPickerDelegate = (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)
open class ItemDropdownEntryField: BaseDropdownEntryField { open class ItemDropdownEntryField: BaseDropdownEntryField {
//-------------------------------------------------- //--------------------------------------------------
@ -62,7 +64,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
@objc open override func setupFieldContainerContent(_ container: UIView) { @objc open override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)
pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self) pickerView = UIPickerView.addPicker(to: textField, delegate: self, dismissAction: #selector(dismissFieldInput))
textField.hideBlinkingCaret = true textField.hideBlinkingCaret = true
textField.autocorrectionType = .no textField.autocorrectionType = .no
uiTextFieldDelegate = self uiTextFieldDelegate = self

View File

@ -17,17 +17,21 @@
public var options: [String] = [] public var options: [String] = []
public var selectedIndex: Int = 0 public var selectedIndex: Int = 0
public override func formFieldValue() -> AnyHashable? {
guard !options.isEmpty else { return nil }
return options[selectedIndex]
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case options case options
case selectedIndex case selectedIndex
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -35,14 +39,17 @@
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
options = try typeContainer.decode([String].self, forKey: .options) options = try typeContainer.decode([String].self, forKey: .options)
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0
if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
self.selectedIndex = selectedIndex
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(options, forKey: .options) try container.encode(options, forKey: .options)
try container.encode(options, forKey: .selectedIndex) try container.encode(options, forKey: .selectedIndex)
} }

View File

@ -48,6 +48,18 @@ import MVMCore
set { text = MVMCoreUIUtility.formatMdn(newValue) } set { text = MVMCoreUIUtility.formatMdn(newValue) }
} }
/// Toggles selected or original (unselected) UI.
public override var isSelected: Bool {
get { return entryFieldContainer.isSelected }
set (selected) {
if selected && showError {
showError = false
}
super.isSelected = selected
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -77,11 +89,14 @@ import MVMCore
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)
textField.keyboardType = .numberPad textField.keyboardType = .numberPad
}
open override func setupTextFieldToolbar() {
let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() let toolbar = UIToolbar.createEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:))) let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts))
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:))) let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput))
toolbar.items = [contacts, space, dismissButton] toolbar.items = [contacts, space, dismissButton]
textField.inputAccessoryView = toolbar textField.inputAccessoryView = toolbar
} }
@ -107,18 +122,18 @@ import MVMCore
isValid = true isValid = true
return true return true
} }
let isValid = hasValidMDN() isValid = hasValidMDN()
if isValid { if self.isValid {
showError = false showError = false
} else { } else {
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") entryFieldModel?.errorMessage = entryFieldModel?.errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
showError = true showError = true
UIAccessibility.post(notification: .layoutChanged, argument: textField) UIAccessibility.post(notification: .layoutChanged, argument: textField)
} }
return isValid return isValid
} }
@ -196,7 +211,7 @@ import MVMCore
} }
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
} }

View File

@ -15,7 +15,7 @@ import UIKit
/// Called when the entered text becomes invalid based on the validation block /// Called when the entered text becomes invalid based on the validation block
@objc optional func isInvalid(textfield: TextEntryField?) @objc optional func isInvalid(textfield: TextEntryField?)
/// Dismisses the keyboard. /// Dismisses the keyboard.
@objc optional func dismissFieldInput(sender: Any?) @objc optional func dismissFieldInput(_ sender: Any?)
} }
@ -28,7 +28,7 @@ import UIKit
let textField = TextField() let textField = TextField()
textField.isAccessibilityElement = true textField.isAccessibilityElement = true
textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
textField.textColor = .mvmBlack textField.textColor = .mvmBlack
textField.smartQuotesType = .no textField.smartQuotesType = .no
textField.smartDashesType = .no textField.smartDashesType = .no
@ -36,13 +36,19 @@ import UIKit
return textField return textField
}() }()
public lazy var errorImage: UIImageView = {
let image = MVMCoreUIUtility.imageNamed("alert_standard")
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true
return imageView
}()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Stored Properties // MARK: - Stored Properties
//-------------------------------------------------- //--------------------------------------------------
/// Set enabled and disabled colors to be utilized when setting this texfield's isEnabled property.
public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.mvmBlack, .mvmCoolGray3)
private var observingForChange: Bool = false private var observingForChange: Bool = false
/// Validate on each entry in the textField. Default: true /// Validate on each entry in the textField. Default: true
@ -54,7 +60,7 @@ import UIKit
public var textEntryFieldModel: TextEntryFieldModel? { public var textEntryFieldModel: TextEntryFieldModel? {
return model as? TextEntryFieldModel return model as? TextEntryFieldModel
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
//-------------------------------------------------- //--------------------------------------------------
@ -68,7 +74,7 @@ import UIKit
guard let self = self else { return } guard let self = self else { return }
self.textField.isEnabled = enabled self.textField.isEnabled = enabled
self.textField.textColor = enabled ? self.textColor.enabled : self.textColor.disabled self.textField.textColor = enabled ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor
} }
} }
} }
@ -78,11 +84,15 @@ import UIKit
set (error) { set (error) {
if error { if error {
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", errorMessage ?? "") textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", entryFieldModel?.errorMessage ?? "")
} else { } else {
textField.accessibilityValue = nil textField.accessibilityValue = nil
} }
if textField.isSecureTextEntry {
showErrorView(error)
}
super.showError = error super.showError = error
} }
} }
@ -102,12 +112,6 @@ import UIKit
set { textField.placeholder = newValue } set { textField.placeholder = newValue }
} }
//--------------------------------------------------
// MARK: - Property Observers
//--------------------------------------------------
public var validationBlock: ((_ value: String?) -> Bool)?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate Properties // MARK: - Delegate Properties
//-------------------------------------------------- //--------------------------------------------------
@ -169,21 +173,21 @@ import UIKit
@objc open override func setupFieldContainerContent(_ container: UIView) { @objc open override func setupFieldContainerContent(_ container: UIView) {
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
container.addSubview(textField) container.addSubview(textField)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
textField.heightAnchor.constraint(equalToConstant: 24), textField.heightAnchor.constraint(equalToConstant: Padding.Five),
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12), textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three),
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16), textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three),
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12) container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: Padding.Three)
]) ])
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16) textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Three)
textFieldTrailingConstraint?.isActive = true textFieldTrailingConstraint?.isActive = true
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin) textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
textField.addTarget(self, action: #selector(dismissFieldInput(_:)), for: .editingDidEnd) textField.addTarget(self, action: #selector(dismissFieldInput), for: .editingDidEnd)
let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing)) let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
entryFieldContainer.addGestureRecognizer(tap) entryFieldContainer.addGestureRecognizer(tap)
@ -194,37 +198,31 @@ import UIKit
@objc open override func updateView(_ size: CGFloat) { @objc open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
layoutIfNeeded() layoutIfNeeded()
} }
open override func reset() { open override func reset() {
super.reset() super.reset()
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
} }
@objc deinit {
setBothTextDelegates(to: nil)
}
@objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) { @objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
observingTextFieldDelegate = delegate observingTextFieldDelegate = delegate
uiTextFieldDelegate = delegate uiTextFieldDelegate = delegate
} }
open func setupTextFieldToolbar() {
let observingDelegate = observingTextFieldDelegate ?? self
textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput))
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Observing for Change (TextFieldDelegate) // MARK: - Observing for Change (TextFieldDelegate)
//-------------------------------------------------- //--------------------------------------------------
public func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0
}
}
@discardableResult @discardableResult
@objc override open func resignFirstResponder() -> Bool { @objc override open func resignFirstResponder() -> Bool {
if validateWhenDoneEditing { if validateWhenDoneEditing {
@ -240,11 +238,11 @@ import UIKit
text = textField.text text = textField.text
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
} }
@objc public func updateValidation(_ isValid: Bool) { @objc public func updateValidation(_ isValid: Bool) {
let previousValidity = self.isValid let previousValidity = self.isValid
self.isValid = isValid self.isValid = isValid
if previousValidity && !isValid { if previousValidity && !isValid {
showError = true showError = true
observingTextFieldDelegate?.isInvalid?(textfield: self) observingTextFieldDelegate?.isInvalid?(textfield: self)
@ -276,10 +274,30 @@ import UIKit
} }
} }
@objc func dismissFieldInput(_ sender: Any?) { @objc public func dismissFieldInput(_ sender: Any?) {
resignFirstResponder() resignFirstResponder()
} }
private func showErrorView(_ show: Bool) {
if show {
entryFieldContainer.addSubview(errorImage)
textFieldTrailingConstraint?.isActive = false
textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
textFieldTrailingConstraint?.isActive = true
entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Three).isActive = true
errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true
} else {
errorImage.removeFromSuperview()
textFieldTrailingConstraint?.isActive = false
textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
textFieldTrailingConstraint?.isActive = true
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MoleculeViewProtocol // MARK: - MoleculeViewProtocol
//-------------------------------------------------- //--------------------------------------------------
@ -288,37 +306,39 @@ import UIKit
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? TextEntryFieldModel else { return } guard let model = model as? TextEntryFieldModel else { return }
model.updateUI = { [weak self] in model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: { MVMCoreDispatchUtility.performBlock(onMainThread: {
if self?.isSelected ?? false { guard let self = self else { return }
self?.updateValidation(model.isValid ?? true)
if self.isSelected {
self.updateValidation(model.isValid ?? true)
} }
}) })
} }
self.delegateObject = delegateObject self.delegateObject = delegateObject
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
textColor.enabled = model.enabledTextColor?.uiColor
textColor.disabled = model.disabledTextColor?.uiColor
text = model.text text = model.text
placeholder = model.placeholder placeholder = model.placeholder
switch model.type { switch model.type {
case .password: case .password, .secure:
textField.isSecureTextEntry = true textField.isSecureTextEntry = true
case .number: case .number:
textField.keyboardType = .numberPad textField.keyboardType = .numberPad
case .email: case .email:
textField.keyboardType = .emailAddress textField.keyboardType = .emailAddress
default: default:
break break
} }
defaultValidationBlock()
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self) setupTextFieldToolbar()
} }
} }

View File

@ -8,9 +8,13 @@
@objcMembers public class TextEntryFieldModel: EntryFieldModel { @objcMembers public class TextEntryFieldModel: EntryFieldModel {
//--------------------------------------------------
// MARK: - Types
//--------------------------------------------------
public enum EntryType: String, Codable { public enum EntryType: String, Codable {
case password case password
case secure
case number case number
case email case email
} }
@ -24,8 +28,8 @@
} }
public var placeholder: String? public var placeholder: String?
public var enabledTextColor: Color? public var enabledTextColor: Color = Color(uiColor: .mvmBlack)
public var disabledTextColor: Color? public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var type: EntryType? public var type: EntryType?
//-------------------------------------------------- //--------------------------------------------------
@ -34,7 +38,6 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case text
case placeholder case placeholder
case enabledTextColor case enabledTextColor
case disabledTextColor case disabledTextColor
@ -42,27 +45,31 @@
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder) placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder)
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) {
self.enabledTextColor = enabledTextColor
}
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
self.disabledTextColor = disabledTextColor
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(placeholder, forKey: .placeholder) try container.encodeIfPresent(placeholder, forKey: .placeholder)
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) try container.encode(enabledTextColor, forKey: .enabledTextColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encode(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(type, forKey: .type) try container.encodeIfPresent(type, forKey: .type)
} }
} }

View File

@ -131,8 +131,26 @@ public typealias ActionBlockConfirmation = () -> (Bool)
private var widthConstraint: NSLayoutConstraint? private var widthConstraint: NSLayoutConstraint?
private func constrainKnob() { private func constrainKnob() {
knobLeadingConstraint?.isActive = !isOn
knobTrailingConstraint?.isActive = isOn knobLeadingConstraint?.isActive = false
knobTrailingConstraint?.isActive = false
_ = isOn ? constrainKnobOn() : constrainKnobOff()
knobTrailingConstraint?.isActive = true
knobLeadingConstraint?.isActive = true
}
private func constrainKnobOn() {
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor)
}
private func constrainKnobOff() {
knobTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: knobView.trailingAnchor)
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
} }
//-------------------------------------------------- //--------------------------------------------------
@ -189,6 +207,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
layer.cornerRadius = Self.getContainerHeight() / 2.0 layer.cornerRadius = Self.getContainerHeight() / 2.0
knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0 knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0
changeStateNoAnimation(isOn)
} }
public override func setupView() { public override func setupView() {
@ -218,9 +238,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1) constrainKnobOff()
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
knobLeadingConstraint?.isActive = true
} }
public override func reset() { public override func reset() {
@ -228,9 +246,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
backgroundColor = containerTintColor.off backgroundColor = containerTintColor.off
knobView.backgroundColor = knobTintColor.off knobView.backgroundColor = knobTintColor.off
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
isAnimated = true isAnimated = true
isOn = false
constrainKnob()
didToggleAction = nil didToggleAction = nil
shouldToggleAction = { return true } shouldToggleAction = { return true }
} }
@ -352,10 +369,15 @@ public typealias ActionBlockConfirmation = () -> (Bool)
containerTintColor.off = model.offTintColor.uiColor containerTintColor.off = model.offTintColor.uiColor
knobTintColor.on = model.onKnobTintColor.uiColor knobTintColor.on = model.onKnobTintColor.uiColor
knobTintColor.off = model.offKnobTintColor.uiColor knobTintColor.off = model.offKnobTintColor.uiColor
changeStateNoAnimation(model.state) isOn = model.state
changeStateNoAnimation(isOn)
isAnimated = model.animated isAnimated = model.animated
isEnabled = model.enabled isEnabled = model.enabled
if let accessibileString = model.accessibilityText {
accessibilityLabel = accessibileString
}
if let actionMap = model.action?.toJSON() { if let actionMap = model.action?.toJSON() {
didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
} }

View File

@ -0,0 +1,37 @@
//
// UIDatePicker+Extension.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/14/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public extension UIDatePicker {
class func addDatePicker(to textField: UITextField) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.backgroundColor = .mvmWhite
datePicker.datePickerMode = .date
let locale = NSLocale.current as NSLocale
datePicker.locale = locale as Locale
datePicker.calendar = locale.object(forKey: .calendar) as? Calendar
textField.inputView = datePicker
return datePicker
}
class func addTimeAndDatePicker(to textField: UITextField) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.backgroundColor = .mvmWhite
datePicker.datePickerMode = .time
textField.inputView = datePicker
return datePicker
}
}

View File

@ -0,0 +1,38 @@
//
// UIPickerView.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/14/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public extension UIPickerView {
class func createPickerView() -> UIPickerView {
let picker = UIPickerView(frame: .zero)
picker.backgroundColor = .mvmWhite
picker.showsSelectionIndicator = true
return picker
}
class func addPicker(to textField: UITextField, delegate: TextFieldAndPickerDelegate?, dismissAction: Selector?) -> UIPickerView {
// Sets up the picker (same tag as the textfield)
let picker = createPickerView()
picker.delegate = delegate
picker.dataSource = delegate
picker.tag = textField.tag
textField.inputView = picker
// Adds a dismiss toolbar, since all fields with pickers should have one.
if let dismissAction = dismissAction {
UIToolbar.addDismissToolbar(to: textField, delegate: delegate, action: dismissAction)
}
return picker
}
}

View File

@ -0,0 +1,56 @@
//
// UIToolbar+Extension.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/10/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol TextFieldOrView { }
extension UITextView: TextFieldOrView { }
extension UITextField: TextFieldOrView { }
public extension UIToolbar {
class func createEmptyToolbar() -> UIToolbar {
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth]
toolbar.barStyle = .default
toolbar.barTintColor = .mvmCoolGray3
toolbar.tintColor = .mvmBlack
toolbar.isTranslucent = true
return toolbar
}
class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar {
let toolbar = createEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action)
toolbar.setItems([space, button], animated: false)
return toolbar
}
class func addDismissToolbar(to object: TextFieldOrView, delegate: Any?, action: Selector) {
let toolbar = Self.getToolbarWithDoneButton(delegate: delegate, action: action)
switch object {
case is UITextField:
(object as? UITextField)?.inputAccessoryView = toolbar
case is UITextView:
(object as? UITextView)?.inputAccessoryView = toolbar
default:
return
}
}
}

View File

@ -150,6 +150,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self)
@ -167,6 +168,10 @@ import Foundation
// Designed Headers // Designed Headers
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self)
// Device Items
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self)
// TODO: Need View // TODO: Need View
try? ModelRegistry.register(TabsModel.self) try? ModelRegistry.register(TabsModel.self)

View File

@ -0,0 +1,79 @@
//
// ListDeviceComplexButtonMedium.swift
// MVMCoreUI
//
// Created by Dhamodaram Nandi on 21/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListDeviceComplexButtonMedium: TableViewCell {
public var verticalStack: Stack<StackModel>
public let eyebrow = Label.createLabelRegularMicro(true)
public let headline = Label.createLabelBoldTitleMedium(true)
public let body = Label.createLabelRegularBodySmall(true)
public let body2 = Label.createLabelRegularBodySmall(true)
public let button = PillButton(frame: .zero)
public let rightImageView = MFLoadImageView()
public var stack: Stack<StackModel>
// MARK: - Initializers
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
rightImageView.addSizeConstraintsForAspectRatio = true
rightImageView.heightAnchor.constraint(equalToConstant: 116.0).isActive = true
rightImageView.widthAnchor.constraint(equalToConstant: 116.0).isActive = true
verticalStack = Stack<StackModel>.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .leading)),
(view: headline, model: StackItemModel(horizontalAlignment: .leading)),
(view: body, model: StackItemModel(horizontalAlignment: .leading)),
(view: body2, model: StackItemModel(horizontalAlignment: .leading)),
(view: button, model: StackItemModel(spacing:16, horizontalAlignment: .leading))],
axis: .vertical, spacing: 0)
stack = Stack<StackModel>.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .leading)),
(view: rightImageView, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center))],
axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - MFViewProtocol
open override func setupView() {
super.setupView()
addMolecule(stack)
stack.restack()
verticalStack.restack()
}
// MARK: - ModelMoleculeViewProtocol
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListDeviceComplexButtonMediumModel else { return }
verticalStack.updateContainedMolecules(with: [model.eyebrow,
model.headline,
model.body,
model.body2,
model.button],
delegateObject, additionalData)
rightImageView.set(with: model.image, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 120
}
public func setDefault() {
eyebrow.styleRegularMicro(true)
headline.styleBoldTitleMedium(true)
body.styleRegularBodySmall(true)
body2.styleRegularBodySmall(true)
eyebrow.textColor = .mvmCoolGray6
}
open override func reset() {
super.reset()
setDefault()
}
}

View File

@ -0,0 +1,68 @@
//
// ListDeviceComplexButtonMediumModel.swift
// MVMCoreUI
//
// Created by Dhamodaram Nandi on 21/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listDvcBtnM"
public var eyebrow: LabelModel?
public var headline: LabelModel?
public var body: LabelModel?
public var body2: LabelModel?
public var button: ButtonModel
public var image: ImageViewModel
public init(eyebrow: LabelModel, headline:LabelModel, body: LabelModel, body2: LabelModel, button: ButtonModel, image: ImageViewModel) {
self.eyebrow = eyebrow
self.headline = headline
self.body = body
self.body2 = body2
self.button = button
self.image = image
super.init()
}
/// Defaults to set
override public func setDefaults() {
super.setDefaults()
button.size = .tiny
button.style = .secondary
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case eyebrow
case headline
case body
case body2
case button
case image
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
body2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body2)
button = try typeContainer.decode(ButtonModel.self, forKey: .button)
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
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.encodeIfPresent(eyebrow, forKey: .eyebrow)
try container.encodeIfPresent(headline, forKey: .headline)
try container.encodeIfPresent(body, forKey: .body)
try container.encodeIfPresent(body2, forKey: .body2)
try container.encode(button, forKey: .button)
try container.encode(image, forKey: .image)
}
}

View File

@ -40,24 +40,18 @@ import Foundation
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
addMolecule(stack) addMolecule(stack)
stack.restack()
} }
open 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) super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return } guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return }
eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) stack.updateContainedMolecules(with: [model.eyebrow,
headline.setOptional(with: model.headline, delegateObject, additionalData) model.headline,
subHeadline.setOptional(with: model.subHeadline, delegateObject, additionalData) model.subHeadline,
body.setOptional(with: model.body, delegateObject, additionalData) model.body,
link.setOptional(with: model.link, delegateObject, additionalData) model.link],
delegateObject, additionalData)
// Hide labels if neeeded.
stack.stackModel?.molecules[0].gone = !eyebrow.hasText
stack.stackModel?.molecules[1].gone = !headline.hasText
stack.stackModel?.molecules[2].gone = !subHeadline.hasText
stack.stackModel?.molecules[3].gone = !body.hasText
stack.stackModel?.molecules[4].gone = (link.titleLabel?.text?.count ?? 0) == 0
stack.restack()
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {

View File

@ -0,0 +1,61 @@
//
// ListThreeColumnDataUsage.swift
// MVMCoreUI
//
// Created by Kruthika KP on 20/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListThreeColumnDataUsage: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-------------------------------------------------------
public let leftLabel = Label.createLabelRegularBodySmall(true)
public let centerLabel = Label.createLabelRegularBodySmall(true)
public let rightLabel = Label.createLabelRegularBodySmall(true)
var stack: Stack<StackModel>
//------------------------------------------------------
// MARK: - Initializers
//------------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
stack = Stack<StackModel>.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 40, horizontalAlignment: .leading)),
(view: centerLabel, model: StackItemModel(percent: 37, horizontalAlignment: .leading)),
(view: rightLabel, model: StackItemModel(percent: 23, horizontalAlignment: .leading))],
axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func setupView() {
super.setupView()
addMolecule(stack)
stack.restack()
}
// MARK: - ModelMoleculeViewProtocol
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListThreeColumnDataUsageModel else { return }
leftLabel.set(with: model.leftLabel, delegateObject, additionalData)
centerLabel.set(with: model.centerLabel, delegateObject, additionalData)
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 121
}
open override func reset() {
super.reset()
leftLabel.styleRegularBodySmall(true)
centerLabel.styleRegularBodySmall(true)
rightLabel.styleRegularBodySmall(true)
}
}

View File

@ -0,0 +1,48 @@
//
// ListThreeColumnDataUsageModel.swift
// MVMCoreUI
//
// Created by Kruthika KP on 20/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListThreeColumnDataUsageModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "list3CDataUsg"
public var leftLabel: LabelModel
public var centerLabel: LabelModel
public var rightLabel: LabelModel
public init(leftLabel:LabelModel, centerLabel:LabelModel, rightLabel:LabelModel) {
self.leftLabel = leftLabel
self.centerLabel = centerLabel
self.rightLabel = rightLabel
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case leftLabel
case centerLabel
case rightLabel
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
centerLabel = try typeContainer.decode(LabelModel.self, forKey: .centerLabel)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
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(leftLabel, forKey: .leftLabel)
try container.encode(centerLabel, forKey: .centerLabel)
try container.encode(rightLabel, forKey: .rightLabel)
}
}

View File

@ -17,6 +17,7 @@ import Foundation
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor
case spacing case spacing
case percent case percent
case gone case gone
@ -33,6 +34,7 @@ import Foundation
if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) { if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) {
self.gone = gone self.gone = gone
} }
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -43,5 +45,6 @@ import Foundation
try container.encodeIfPresent(spacing, forKey: .spacing) try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percent, forKey: .percent) try container.encodeIfPresent(percent, forKey: .percent)
try container.encode(gone, forKey: .gone) try container.encode(gone, forKey: .gone)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }

View File

@ -8,11 +8,19 @@
import UIKit import UIKit
@objcMembers open class LabelToggle: View { @objcMembers open class LabelToggle: View {
public let label = Label.commonLabelB1(true) //--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public let label = Label.createLabelBoldBodySmall(true)
public let toggle = Toggle() public let toggle = Toggle()
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
label.updateView(size) label.updateView(size)
@ -21,28 +29,26 @@ import UIKit
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
guard toggle.superview == nil else {
return
}
addSubview(label) addSubview(label)
addSubview(toggle) addSubview(toggle)
label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) label.setContentHuggingPriority(.required, for: .vertical)
NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false) NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false)
} }
// MARK:- MoleculeViewProtocol
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let model = model as? LabelToggleModel, guard let model = model as? LabelToggleModel,
let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject), let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject),
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject) else { return nil } let labelHeight = Label.estimatedHeight(with: model.label, delegateObject)
else { return nil }
return max(toggleHeight, labelHeight) return max(toggleHeight, labelHeight)
} }
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let labelToggleModel = model as? LabelToggleModel else {
return guard let labelToggleModel = model as? LabelToggleModel else { return }
}
label.set(with: labelToggleModel.label, delegateObject, additionalData) label.set(with: labelToggleModel.label, delegateObject, additionalData)
toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData) toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData)
} }
@ -52,6 +58,6 @@ import UIKit
super.reset() super.reset()
label.reset() label.reset()
toggle.reset() toggle.reset()
label.styleB1(true) label.styleBoldBodySmall(true)
} }
} }

View File

@ -33,6 +33,7 @@ import UIKit
stack.stackModel?.spacing = 0 stack.stackModel?.spacing = 0
addSubview(stack) addSubview(stack)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
stack.restack()
} }
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
@ -58,18 +59,11 @@ import UIKit
open 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) super.set(with: model, delegateObject, additionalData)
stack.updateContainedMolecules(with: [castModel?.eyebrow,
eyebrow.setOptional(with: castModel?.eyebrow, delegateObject, additionalData) castModel?.headline,
headline.setOptional(with: castModel?.headline, delegateObject, additionalData) castModel?.body,
body.setOptional(with: castModel?.body, delegateObject, additionalData) castModel?.link],
link.setOptional(with: castModel?.link, delegateObject, additionalData) delegateObject, additionalData)
// Hide labels if neeeded.
stack.stackModel?.molecules[0].gone = !eyebrow.hasText
stack.stackModel?.molecules[1].gone = !headline.hasText
stack.stackModel?.molecules[2].gone = !body.hasText
stack.stackModel?.molecules[3].gone = (link.titleLabel?.text?.count ?? 0) == 0
stack.restack()
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {

View File

@ -62,6 +62,32 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
} }
} }
/// A convenience function for when the stackItems are containers and we want to update them based on the contained molecules models. If model is nil, stackItem is set to gone. Restacks if necessary.
open func updateContainedMolecules(with models: [MoleculeModelProtocol?], _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard var stackModel = stackModel else { return }
var needsRestack = false
for (index, item) in stackItems.enumerated() {
guard let container = item as? UIView & ContainerProtocol,
let contained = container.view as? MoleculeViewProtocol else {
continue
}
if let model = models[index] {
contained.set(with: model, delegateObject, additionalData)
if stackModel.molecules[index].gone {
stackModel.molecules[index].gone = false
needsRestack = true
}
} else if !stackModel.molecules[index].gone {
stackModel.molecules[index].gone = true
needsRestack = true
}
}
if needsRestack {
restack()
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------

View File

@ -48,6 +48,7 @@ import Foundation
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
self.spacing = spacing self.spacing = spacing
} }
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -58,5 +59,6 @@ import Foundation
try container.encodeIfPresent(axis.rawValueString, forKey: .axis) try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
try container.encodeIfPresent(spacing, forKey: .spacing) try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }

View File

@ -36,7 +36,7 @@ open class ScrollingViewController: ViewController {
super.viewDidLoad() super.viewDidLoad()
// Adds the tap gesture to dismiss the keyboard. // Adds the tap gesture to dismiss the keyboard.
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput(sender:))) dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput))
view.addGestureRecognizer(dismissKeyboardTapGesture!) view.addGestureRecognizer(dismissKeyboardTapGesture!)
dismissKeyboardTapGesture?.isEnabled = false dismissKeyboardTapGesture?.isEnabled = false
scrollView.alwaysBounceVertical = false scrollView.alwaysBounceVertical = false

View File

@ -405,7 +405,7 @@ import UIKit
} }
} }
@objc open func dismissFieldInput(sender: Any?) { @objc open func dismissFieldInput(_ sender: Any?) {
selectedField?.resignFirstResponder() selectedField?.resignFirstResponder()
} }

View File

@ -25,9 +25,7 @@ import UIKit
/// Total control over the drawn top, bottom, left and right borders. /// Total control over the drawn top, bottom, left and right borders.
public var disableAllBorders = false { public var disableAllBorders = false {
didSet { didSet { bottomBar?.isHidden = disableAllBorders }
bottomBar?.isHidden = disableAllBorders
}
} }
private(set) var fieldState: FieldState = .original { private(set) var fieldState: FieldState = .original {

View File

@ -10,10 +10,8 @@ import Foundation
open class Styler { open class Styler {
//--------------------------------------------------
// MARK: - Enums
//--------------------------------------------------
// MARK:- Font Enum
public enum Font: String, Codable { public enum Font: String, Codable {
case Title2XLarge case Title2XLarge
case TitleXLarge case TitleXLarge

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "alert_standard @1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "alert_standard @2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "alert_standard @3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

View File

@ -198,7 +198,7 @@
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=space-[button]->=space-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingFive)} views:NSDictionaryOfVariableBindings(button)]]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=space-[button]->=space-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingFive)} views:NSDictionaryOfVariableBindings(button)]];
[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:PaddingThree].active = YES; [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:PaddingThree].active = YES;
[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingThree)].active = YES; [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)].active = YES;
self.button = button; self.button = button;
} }
} else { } else {
@ -210,7 +210,7 @@
} }
if (!self.labelRightConstraint) { if (!self.labelRightConstraint) {
self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingThree)]; self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)];
} }
self.labelRightConstraint.active = YES; self.labelRightConstraint.active = YES;
} }

View File

@ -14,7 +14,7 @@ public extension MVMCoreUICommonViewsUtility {
let toolbar = self.makeEmptyToolbar() let toolbar = self.makeEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput(sender:))) let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput))
button.tintColor = .black button.tintColor = .black
toolbar.setItems([space, button], animated: false) toolbar.setItems([space, button], animated: false)