From 0131137ae6902479841db18fe45a06fbd745958d Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 24 Mar 2020 18:21:52 +0530 Subject: [PATCH 001/136] 19060(List - Left Variable - Checkbox - Body Text Only) initial commit --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ .../ListLeftVariableCheckboxBodyText.swift | 55 +++++++++++++++++++ ...istLeftVariableCheckboxBodyTextModel.swift | 55 +++++++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 4 files changed, 119 insertions(+) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5308ee86..d083e86b 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -175,6 +175,8 @@ 94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; }; AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; + AA4B6A67242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4B6A66242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift */; }; + AA4B6A69242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4B6A68242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; @@ -566,6 +568,8 @@ 94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = ""; }; AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = ""; }; AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; + AA4B6A66242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; + AA4B6A68242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = ""; }; @@ -1233,6 +1237,8 @@ 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, + AA4B6A66242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift */, + AA4B6A68242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift */, ); path = LeftVariable; sourceTree = ""; @@ -1946,6 +1952,7 @@ BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* ValidProtocol.swift in Sources */, + AA4B6A67242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, @@ -2006,6 +2013,7 @@ D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, + AA4B6A69242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */, 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift new file mode 100644 index 00000000..6b05820f --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift @@ -0,0 +1,55 @@ +// +// ListLeftVariableCheckboxBodyText.swift +// MVMCoreUI +// +// Created by Lekshmi S on 24/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ListLeftVariableCheckboxBodyText: TableViewCell { + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + public let checkbox = Checkbox(frame: .zero) + public var headlineBody = HeadlineBody(frame: .zero) + public var stack: Stack + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: checkbox, model: StackItemModel(horizontalAlignment: .fill)), + (view: headlineBody, model: StackItemModel(horizontalAlignment: .leading))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //----------------------------------------------------- + override open func setupView() { + super.setupView() + addMolecule(stack) + stack.restack() + } + + //---------------------------------------------------- + // MARK: - Molecule + //---------------------------------------------------- + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListLeftVariableCheckboxBodyTextModel else { return} + checkbox.set(with: model.checkbox, delegateObject, additionalData) + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 140 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift new file mode 100644 index 00000000..1e149d98 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift @@ -0,0 +1,55 @@ +// +// ListLeftVariableCheckboxBodyTextModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 24/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "listLVCBBdy" + public var checkbox: CheckboxModel + public var headlineBody: HeadlineBodyModel + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(checkbox: CheckboxModel, headlineBody: HeadlineBodyModel) { + self.checkbox = checkbox + self.headlineBody = headlineBody + super.init() + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case moleculeName + case headlineBody + case checkbox + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + checkbox = try typeContainer.decodeIfPresent(CheckboxModel.self, forKey: .checkbox) ?? CheckboxModel() + try super.init(from: decoder) + } + + open override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(headlineBody, forKey: .headlineBody) + try container.encode(checkbox, forKey: .checkbox) + } +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index f2bf9e78..acc75475 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -110,6 +110,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxBodyText.self, viewModelClass: ListLeftVariableCheckboxBodyTextModel.self) // Designed Section Dividers MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) From c180abf30240a76f7fc4cd1a995381b781f4e981 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 31 Mar 2020 13:50:34 +0530 Subject: [PATCH 002/136] Radioswatches model initial commit --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +++ .../Atoms/Buttons/RadioSwatchesModel.swift | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 03335a4d..7bd74df8 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -173,6 +173,7 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; + AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; }; BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; }; @@ -556,6 +557,7 @@ AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; + AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = ""; }; BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = ""; }; BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = ""; }; @@ -1492,6 +1494,7 @@ 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */, 011D95AE2407266E000E3791 /* RadioButtonModel.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, + AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, ); path = Buttons; sourceTree = ""; @@ -1879,6 +1882,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */, 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */, 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift new file mode 100644 index 00000000..734ecbfd --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift @@ -0,0 +1,35 @@ +// +// RadioSwatchesModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 31/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol { + public var backgroundColor: Color? + public static var identifier: String = "radioSwatches" + public var moleculeName: String = RadioSwatchesModel.identifier + public var swatches: [RadioSwatchItemModel] + + public init(swatches: [RadioSwatchItemModel]) { + self.swatches = swatches + } +} + +@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol { + public var backgroundColor: Color? + public static var identifier: String = "radioSwatchItem" + public var moleculeName: String = RadioSwatchItemModel.identifier + public var text: String + public var enabled: Bool + public var color: Color + + public init(enabled: Bool, color: Color, text: String) { + self.enabled = enabled + self.color = color + self.text = text + } +} From b302d2ff61575b9168ec5a4da3a0bf1713a5b23f Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 2 Apr 2020 19:47:52 -0400 Subject: [PATCH 003/136] april jira tasks --- MVMCoreUI.xcodeproj/project.pbxproj | 8 --- .../ActionCollapseNotificationModel.swift | 1 - MVMCoreUI/Actions/ActionOpenPanelModel.swift | 2 - MVMCoreUI/Actions/ActionTopAlertModel.swift | 2 - MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 - .../Doughnut/DoughnutChartView.swift | 4 +- .../Lists/NumberedListModel.swift | 9 ++-- .../StringAndMoleculeStack.swift | 7 +-- .../StringAndMoleculeView.swift | 3 +- .../Lists/UnOrderedListModel.swift | 7 ++- .../Atomic/Organisms/MoleculeStackModel.swift | 54 ------------------- .../Atomic/Organisms/MoleculeStackView.swift | 44 --------------- MVMCoreUI/Atomic/Organisms/Stack.swift | 13 +++-- MVMCoreUI/Atomic/Organisms/StackModel.swift | 20 ++++--- .../Atomic/Organisms/StackModelProtocol.swift | 4 +- .../Templates/MoleculeStackTemplate.swift | 2 +- .../Templates/StackPageTemplateModel.swift | 6 +-- 17 files changed, 41 insertions(+), 146 deletions(-) delete mode 100644 MVMCoreUI/Atomic/Organisms/MoleculeStackModel.swift delete mode 100644 MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 60829e96..f3716e02 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -61,7 +61,6 @@ 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; }; 01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; }; 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* MoleculeListItemModel.swift */; }; - 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368B23609801006832FA /* MoleculeStackModel.swift */; }; 01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; }; 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; }; 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */; }; @@ -358,7 +357,6 @@ D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */; }; D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */; }; D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */; }; - D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */; }; D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */; }; D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */; }; D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MoleculeHeaderView.swift */; }; @@ -460,7 +458,6 @@ 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; 01EB368923609801006832FA /* MoleculeListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeListItemModel.swift; sourceTree = ""; }; 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackItemModel.swift; sourceTree = ""; }; - 01EB368B23609801006832FA /* MoleculeStackModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackModel.swift; sourceTree = ""; }; 01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = ""; }; 01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = ""; }; 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretLinkModel.swift; sourceTree = ""; }; @@ -761,7 +758,6 @@ D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeView.swift; sourceTree = ""; }; D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeModel.swift; sourceTree = ""; }; D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerHelper.swift; sourceTree = ""; }; - D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = ""; }; D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackTemplate.swift; sourceTree = ""; }; D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = ""; }; D2A514662213885800345BFB /* MoleculeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderView.swift; sourceTree = ""; }; @@ -1185,8 +1181,6 @@ D260105A23D0BB7100764D80 /* StackModelProtocol.swift */, D260106423D0CEA700764D80 /* StackModel.swift */, D260105C23D0BCD400764D80 /* Stack.swift */, - 01EB368B23609801006832FA /* MoleculeStackModel.swift */, - D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */, D2A6390022CBB1820052ED1F /* Carousel.swift */, ); @@ -1977,7 +1971,6 @@ 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */, D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */, - D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, @@ -2003,7 +1996,6 @@ 0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, - 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, diff --git a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift index 9a6e6793..1a665b80 100644 --- a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift +++ b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift @@ -13,5 +13,4 @@ import UIKit public var actionType: String public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? - public var title: String? } diff --git a/MVMCoreUI/Actions/ActionOpenPanelModel.swift b/MVMCoreUI/Actions/ActionOpenPanelModel.swift index 55fd272a..6ada6f04 100644 --- a/MVMCoreUI/Actions/ActionOpenPanelModel.swift +++ b/MVMCoreUI/Actions/ActionOpenPanelModel.swift @@ -22,8 +22,6 @@ public class ActionOpenPanelModel: ActionModelProtocol { public var panel: Panel public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? - // Temporary fix till server changes - public var title: String? public init(panel: Panel) { self.panel = panel diff --git a/MVMCoreUI/Actions/ActionTopAlertModel.swift b/MVMCoreUI/Actions/ActionTopAlertModel.swift index 628633c2..29838c76 100644 --- a/MVMCoreUI/Actions/ActionTopAlertModel.swift +++ b/MVMCoreUI/Actions/ActionTopAlertModel.swift @@ -14,8 +14,6 @@ import Foundation public var pageType: String public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? - // Temporary fix till server changes - public var title: String? public init(pageType: String) { self.pageType = pageType diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 7f56f142..7d35dbce 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -37,7 +37,6 @@ import Foundation /// Call to register all of the CoreUI molecules. public static func registerObjects() { // Stacks - MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: MoleculeStackModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Stack.self, viewModelClass: StackModel.self) MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self) MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift index 280385cb..bffea398 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift @@ -76,7 +76,7 @@ import Foundation for item in model.sections { stackItems.append(MoleculeStackItemModel(with: item)) } - let stack = MoleculeStackModel(molecules: stackItems) + let stack = StackModel(molecules: stackItems) stack.verticalAlignment = .fill colorLablesStack.set(with: stack, delegateObject, additionalData) } @@ -88,7 +88,7 @@ extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { } } -class ColorViewLabelsStack: MoleculeStackView { +class ColorViewLabelsStack: Stack { override func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift index 8a7b6125..f58a62ff 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class NumberedListModel: MoleculeStackModel { +@objcMembers public class NumberedListModel: StackModel { public override class var identifier: String { return "numberedList" } @@ -28,8 +28,7 @@ import Foundation for (index, molecule) in list.enumerated() { models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: "\(index+1).", molecule: molecule))) } - super.init(molecules: models) - spacing = 0 + super.init(molecules: models, spacing: 0) } public override func encode(to encoder: Encoder) throws { @@ -39,9 +38,9 @@ import Foundation var models: [MoleculeModelProtocol] = [] for molecule in molecules { - models.append(molecule.molecule) + models.append((molecule as! MoleculeStackItemModel).molecule) } - try container.encodeModels(models, forKey: .list) + try container.encodeModels(molecules, forKey: .list) } } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift index 4ff045ce..8bd6d005 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -9,10 +9,11 @@ import UIKit // This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need. -open class StringAndMoleculeStack: MoleculeStackView { +open class StringAndMoleculeStack: Stack { override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - guard let model = stackModel else { return } - for stackItemModel in model.molecules { + guard let model = model as? StackModelProtocol, + let molcules = model.molecules as? [MoleculeStackItemModel] else { return } + for stackItemModel in molcules { guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel, let molecule = MoleculeObjectMapping.shared()?.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject , additionalData: additionalData) else { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift index 6db91703..a7c9e20d 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift @@ -10,7 +10,6 @@ import Foundation open class StringAndMoleculeView: View { var label = Label.commonLabelB2(true) - var string: String var molecule: MoleculeViewProtocol var leftWidthConstraint: NSLayoutConstraint? @@ -28,7 +27,7 @@ open class StringAndMoleculeView: View { // MARK: - Inits public init(string: String, molecule: MoleculeViewProtocol) { - self.string = string + self.label.text = string self.molecule = molecule super.init(frame: .zero) } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift index 84d23a11..32764641 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class UnOrderedListModel: MoleculeStackModel { +@objcMembers public class UnOrderedListModel: StackModel { public override class var identifier: String { return "unOrderedList" } @@ -33,8 +33,7 @@ import Foundation for molecule in list { models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule))) } - super.init(molecules: models) - spacing = 0 + super.init(molecules: models, spacing: 0) } public override func encode(to encoder: Encoder) throws { @@ -45,7 +44,7 @@ import Foundation var models: [MoleculeModelProtocol] = [] for molecule in molecules { - models.append(molecule.molecule) + models.append((molecule as! MoleculeStackItemModel).molecule) } try container.encodeModels(models, forKey: .list) } diff --git a/MVMCoreUI/Atomic/Organisms/MoleculeStackModel.swift b/MVMCoreUI/Atomic/Organisms/MoleculeStackModel.swift deleted file mode 100644 index 134cc701..00000000 --- a/MVMCoreUI/Atomic/Organisms/MoleculeStackModel.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// MoleculeStack.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 10/3/19. -// Copyright © 2019 Suresh, Kamlesh. All rights reserved. -// -// A stack that has a list molecule stack items. - -import Foundation - -@objcMembers public class MoleculeStackModel: ContainerModel, MoleculeModelProtocol, StackModelProtocol { - public class var identifier: String { - return "stack" - } - public var backgroundColor: Color? - public var molecules: [MoleculeStackItemModel] - public var axis: NSLayoutConstraint.Axis = .vertical - public var spacing: CGFloat = 16.0 - public var useStackSpacingBeforeFirstItem = false - - public init(molecules: [MoleculeStackItemModel]) { - self.molecules = molecules - super.init() - } - - private enum CodingKeys: String, CodingKey { - case moleculeName - case molecules - case axis - case spacing - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - molecules = try typeContainer.decode([MoleculeStackItemModel].self, forKey: .molecules) - if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { - axis = optionalAxis - } - if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { - self.spacing = spacing - } - 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(molecules, forKey: .molecules) - try container.encodeIfPresent(axis.rawValueString, forKey: .axis) - try container.encodeIfPresent(spacing, forKey: .spacing) - } -} diff --git a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift deleted file mode 100644 index 0f13cde5..00000000 --- a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// MoleculeStackView.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 2/11/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -open class MoleculeStackView: Stack { - open override var stackModel: MoleculeStackModel? { - get { return model as? MoleculeStackModel } - } - - /// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack - func setup(with views: [View], lastItem: Bool) { - var models: [MoleculeStackItemModel] = [] - for view in views { - guard let model = view.model else { return } - let stackItemModel = MoleculeStackItemModel(with: model) - let stackItem = MoleculeStackItem(andContain: view) - stackItems.append(stackItem) - models.append(stackItemModel) - } - if let stackModel = stackModel { - stackModel.molecules = models - } else { - model = MoleculeStackModel(molecules: models) - } - restack() - } - - // MARK: - Adding to stack - /// Creates all of the stackItems for the stackItemModels - override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - guard let stackItemModels = stackModel?.molecules else { return } - for model in stackItemModels { - if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem { - stackItems.append(stackItem) - } - } - } -} diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index e957a2a6..d1c127fd 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -217,7 +217,14 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto //-------------------------------------------------- /// Can be subclassed to create views when we get stack item models and have no views yet - open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { } + open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let stackItemModels = (model as? StackModelProtocol)?.molecules else { return } + for model in stackItemModels { + if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? (MoleculeViewProtocol & StackModelProtocol) { + stackItems.append(stackItem) + } + } + } /// Can be subclassed to set stack items with model when we already have views open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { @@ -243,10 +250,10 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto } /// Sets the stack with StackItems containing the passed in views and sets the StackModel with models. - open func set(with viewModels:[(view: UIView, model: T.AnyStackItemModel)]) { + open func set(with viewModels:[(view: UIView, model: StackItemModel)]) { guard var stackModel = self.stackModel else { return } var stackItems: [StackItem] = [] - var models: [T.AnyStackItemModel] = [] + var models: [StackItemModel] = [] for item in viewModels { stackItems.append(StackItem(andContain: item.view)) models.append(item.model) diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index 46f68c3b..43dd7058 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -8,17 +8,19 @@ import Foundation -@objcMembers public class StackModel: StackModelProtocol, MoleculeModelProtocol { +@objcMembers public class StackModel: ContainerModel, StackModelProtocol, MoleculeModelProtocol { static let defaultSpacing: CGFloat = 16.0 - public static var identifier: String = "simpleStack" + public class var identifier: String { + return "stack" + } public var backgroundColor: Color? - public var molecules: [StackItemModel] + public var molecules: [StackItemModelProtocol] public var axis: NSLayoutConstraint.Axis = .vertical public var spacing: CGFloat = StackModel.defaultSpacing public var useStackSpacingBeforeFirstItem = false - public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) { + public init(molecules: [StackItemModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) { self.molecules = molecules if let axis = axis { self.axis = axis @@ -26,6 +28,7 @@ import Foundation if let spacing = spacing { self.spacing = spacing } + super.init() } private enum CodingKeys: String, CodingKey { @@ -38,19 +41,20 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - - molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules) + molecules = try typeContainer.decodeModel(codingKey: .molecules) if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { axis = optionalAxis } if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { self.spacing = spacing } + try super.init(from: decoder) } - public func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(molecules, forKey: .molecules) + try container.encodeModels(molecules, forKey: .molecules) try container.encodeIfPresent(axis.rawValueString, forKey: .axis) try container.encodeIfPresent(spacing, forKey: .spacing) try container.encode(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift index b7385466..75c29a3e 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift @@ -9,9 +9,7 @@ import Foundation public protocol StackModelProtocol { - associatedtype AnyStackItemModel: StackItemModelProtocol - - var molecules: [AnyStackItemModel] { get set } + var molecules: [StackItemModelProtocol] { get set } var axis: NSLayoutConstraint.Axis { get set } var spacing: CGFloat { get set } var useStackSpacingBeforeFirstItem: Bool { get set } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift index b26bbc8a..b095f19e 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift @@ -49,7 +49,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { return nil } - let stack = MoleculeStackView(frame: .zero) + let stack = Stack(frame: .zero) moleculeStackModel.useStackSpacingBeforeFirstItem = true moleculeStackModel.useHorizontalMargins = true stack.set(with: moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil) diff --git a/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift index 2b683d98..c7b5239a 100644 --- a/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift @@ -15,10 +15,10 @@ import Foundation } public var header: MoleculeModelProtocol? - public var moleculeStack: MoleculeStackModel + public var moleculeStack: StackModel public var footer: MoleculeModelProtocol? - public init(pageType: String, moleculeStack: MoleculeStackModel) { + public init(pageType: String, moleculeStack: StackModel) { self.moleculeStack = moleculeStack super.init(pageType: pageType) } @@ -31,7 +31,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack) + moleculeStack = try typeContainer.decode(StackModel.self, forKey: .stack) header = try typeContainer.decodeModelIfPresent(codingKey: .header) footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) try super.init(from: decoder) From 9e241e6d8e2a69d51e1d3bd6c68c95227272e845 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 11:03:12 -0400 Subject: [PATCH 004/136] Molecule stack fix --- .../Atomic/Molecules/Items/StackItemModelProtocol.swift | 2 +- MVMCoreUI/Atomic/Organisms/Stack.swift | 2 +- MVMCoreUI/Atomic/Organisms/StackModel.swift | 6 +++--- MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/Items/StackItemModelProtocol.swift b/MVMCoreUI/Atomic/Molecules/Items/StackItemModelProtocol.swift index 170fce69..2223ed39 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/StackItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/StackItemModelProtocol.swift @@ -8,7 +8,7 @@ import Foundation -public protocol StackItemModelProtocol: MoleculeModelProtocol { +public protocol StackItemModelProtocol { var spacing: CGFloat? { get set } var percent: Int? { get set } var gone: Bool { get set } diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index d1c127fd..ab17be3b 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -220,7 +220,7 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let stackItemModels = (model as? StackModelProtocol)?.molecules else { return } for model in stackItemModels { - if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? (MoleculeViewProtocol & StackModelProtocol) { + if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) { stackItems.append(stackItem) } } diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index 43dd7058..cc8f7d0e 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -15,12 +15,12 @@ import Foundation return "stack" } public var backgroundColor: Color? - public var molecules: [StackItemModelProtocol] + public var molecules: [StackItemModelProtocol & MoleculeModelProtocol] public var axis: NSLayoutConstraint.Axis = .vertical public var spacing: CGFloat = StackModel.defaultSpacing public var useStackSpacingBeforeFirstItem = false - public init(molecules: [StackItemModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) { + public init(molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) { self.molecules = molecules if let axis = axis { self.axis = axis @@ -41,7 +41,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - molecules = try typeContainer.decodeModel(codingKey: .molecules) + molecules = try typeContainer.decodeModels(codingKey: .molecules) if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { axis = optionalAxis } diff --git a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift index 75c29a3e..54f6c9d0 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation public protocol StackModelProtocol { - var molecules: [StackItemModelProtocol] { get set } + var molecules: [StackItemModelProtocol & MoleculeModelProtocol] { get set } var axis: NSLayoutConstraint.Axis { get set } var spacing: CGFloat { get set } var useStackSpacingBeforeFirstItem: Bool { get set } From 24bce846f4438d2cbce4133a1af34442202f1f62 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 11:42:31 -0400 Subject: [PATCH 005/136] progress updates --- MVMCoreUI.xcodeproj/project.pbxproj | 24 ++++++++-------- .../Atomic/Atoms/Views/MultiProgress.swift | 14 ++++------ .../Atoms/Views/MultiProgressModel.swift | 18 ++++++------ .../Atomic/Atoms/Views/ProgressBar.swift | 9 +++--- .../Atomic/Atoms/Views/ProgressBarModel.swift | 18 ++++++------ .../Views/{GraphView.swift => Wheel.swift} | 28 +++++++++---------- ...dler.swift => WheelAnimationHandler.swift} | 6 ++-- ...leProgressModel.swift => WheelModel.swift} | 6 ++-- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 2 +- .../List/RightVariable/ListRVWheel.swift | 2 +- .../List/RightVariable/ListRVWheelModel.swift | 6 ++-- 11 files changed, 65 insertions(+), 68 deletions(-) rename MVMCoreUI/Atomic/Atoms/Views/{GraphView.swift => Wheel.swift} (87%) rename MVMCoreUI/Atomic/Atoms/Views/{GraphViewAnimationHandler.swift => WheelAnimationHandler.swift} (82%) rename MVMCoreUI/Atomic/Atoms/Views/{CircleProgressModel.swift => WheelModel.swift} (96%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f3716e02..33daa259 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -136,8 +136,8 @@ 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; }; 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */; }; 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; - 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; - 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; + 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; }; + 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; }; 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; }; 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445891E2385D2E900DE9FD4 /* CaretViewModel.swift */; }; @@ -249,7 +249,7 @@ D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */; }; D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837E23CCA96400DFE4FC /* TabsModel.swift */; }; D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */; }; - D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */; }; + D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* WheelModel.swift */; }; D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */; }; D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838823CCCFCB00DFE4FC /* LinkModel.swift */; }; D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */; }; @@ -525,8 +525,8 @@ 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeListTemplate.swift; sourceTree = ""; }; 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeStackTemplate.swift; sourceTree = ""; }; 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = ""; }; - 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; - 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; + 943784F3236B77BB006A1E82 /* Wheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wheel.swift; sourceTree = ""; }; + 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WheelAnimationHandler.swift; sourceTree = ""; }; 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = ""; }; 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgressModel.swift; sourceTree = ""; }; 9445891E2385D2E900DE9FD4 /* CaretViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretViewModel.swift; sourceTree = ""; }; @@ -635,7 +635,7 @@ D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsListItemModel.swift; sourceTree = ""; }; D28A837E23CCA96400DFE4FC /* TabsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsModel.swift; sourceTree = ""; }; D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionListItemModel.swift; sourceTree = ""; }; - D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleProgressModel.swift; sourceTree = ""; }; + D28A838223CCBD3F00DFE4FC /* WheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WheelModel.swift; sourceTree = ""; }; D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollerModel.swift; sourceTree = ""; }; D28A838823CCCFCB00DFE4FC /* LinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkModel.swift; sourceTree = ""; }; D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModel.swift; sourceTree = ""; }; @@ -1539,9 +1539,9 @@ 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */, - D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */, - 943784F3236B77BB006A1E82 /* GraphView.swift */, - 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, + D28A838223CCBD3F00DFE4FC /* WheelModel.swift */, + 943784F3236B77BB006A1E82 /* Wheel.swift */, + 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */, D260105223CEA61600764D80 /* ToggleModel.swift */, 0AA33B392398524F0067DD0F /* Toggle.swift */, 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */, @@ -1902,7 +1902,7 @@ 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */, 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */, - 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, + 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */, 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */, 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */, D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, @@ -2008,7 +2008,7 @@ D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, - D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, + D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, @@ -2149,7 +2149,7 @@ D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, 94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */, - 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, + 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */, 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift index 72f84f5e..adf480c2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift @@ -24,14 +24,12 @@ import UIKit } var previous: UIView? for progressObject in progressList! { - guard progressObject.progress > 0.0 else { - continue - } + guard progressObject.percent > 0.0 else { continue } let view = UIView(frame: .zero) view.translatesAutoresizingMaskIntoConstraints = false addSubview(view) - view.backgroundColor = progressObject.progressColor.uiColor - view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress/100.0).isActive = true + view.backgroundColor = progressObject.color.uiColor + view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.percent/100.0).isActive = true view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true previous = view NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) @@ -39,9 +37,9 @@ import UIKit } } - var roundedRect: Bool = false { + var roundedCorners: Bool = false { didSet { - if roundedRect { + if roundedCorners { layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2 } else { layer.cornerRadius = 0 @@ -69,7 +67,7 @@ import UIKit guard let multiProgressModel = multiProgressModel else { return } - roundedRect = multiProgressModel.roundedRect ?? false + roundedCorners = multiProgressModel.roundedCorners ?? false thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight progressList = multiProgressModel.progressList diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift index 4033fd28..fb70ffd0 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgressModel.swift @@ -9,12 +9,12 @@ import Foundation @objcMembers public class SingleProgressBarModel: Codable { - @Percent var progress: CGFloat - var progressColor: Color + @Percent var percent: CGFloat + var color: Color - init(_ progress: CGFloat, color: Color) { - self.progress = progress - self.progressColor = color + init(_ percent: CGFloat, color: Color) { + self.percent = percent + self.color = color } } @@ -23,13 +23,13 @@ import Foundation public var progressList: [SingleProgressBarModel] public var backgroundColor: Color? public var thickness: CGFloat? - public var roundedRect: Bool? + public var roundedCorners: Bool? private enum CodingKeys: String, CodingKey { case moleculeName case progressList case thickness - case roundedRect + case roundedCorners case backgroundColor } @@ -42,7 +42,7 @@ import Foundation progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) - roundedRect = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedRect) + roundedCorners = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedCorners) } public func encode(to encoder: Encoder) throws { @@ -50,7 +50,7 @@ import Foundation try container.encode(moleculeName, forKey: .moleculeName) try container.encode(progressList, forKey: .progressList) try container.encodeIfPresent(thickness, forKey: .thickness) - try container.encodeIfPresent(roundedRect, forKey: .roundedRect) + try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift index 1b9f1e74..edb8c1de 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift @@ -14,7 +14,7 @@ import Foundation var thickness: CGFloat = 8.0 { willSet(newValue) { heightAnchor.constraint(equalToConstant: newValue).isActive = true - if progressBarModel?.isRounded ?? false { + if progressBarModel?.roundedCorners ?? false { layer.cornerRadius = newValue/2.0 } else { progressViewStyle = .bar @@ -52,12 +52,11 @@ import Foundation //MARK: - MoleculeViewProtocol public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let progressBarModel = model as? ProgressBarModel else { - return - } + guard let progressBarModel = model as? ProgressBarModel else { return } + self.progressBarModel = progressBarModel thickness = progressBarModel.thickness ?? 8 progress = Float((progressBarModel.percent)/100.0) - progressTintColor = progressBarModel.progressColor.uiColor + progressTintColor = progressBarModel.color.uiColor if let backgroundColor = progressBarModel.backgroundColor { trackTintColor = backgroundColor.uiColor } diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift index dd53afac..7cef8936 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift @@ -11,17 +11,17 @@ import Foundation @objcMembers public class ProgressBarModel: MoleculeModelProtocol { public static var identifier: String = "progressBar" @Percent public var percent: CGFloat - public var progressColor: Color = Color(uiColor: .mfCerulean()) + public var color: Color = Color(uiColor: .mfCerulean()) public var backgroundColor: Color? = Color(uiColor: .mfLightSilver()) - public var isRounded: Bool? + public var roundedCorners: Bool? public var thickness: CGFloat? private enum CodingKeys: String, CodingKey { case moleculeName - case isRounded = "roundRect" + case roundedCorners case thickness case percent - case progressColor + case color case backgroundColor } @@ -32,13 +32,13 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) percent = try typeContainer.decode(CGFloat.self, forKey: .percent) - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .progressColor) { - progressColor = color + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) { + self.color = color } if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) { backgroundColor = color } - isRounded = try typeContainer.decodeIfPresent(Bool.self, forKey: .isRounded) + roundedCorners = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedCorners) thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) } @@ -46,9 +46,9 @@ import Foundation var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(percent, forKey: .percent) - try container.encode(progressColor, forKey: .progressColor) + try container.encode(color, forKey: .color) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(isRounded, forKey: .isRounded) + try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners) try container.encodeIfPresent(thickness, forKey: .thickness) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/GraphView.swift b/MVMCoreUI/Atomic/Atoms/Views/Wheel.swift similarity index 87% rename from MVMCoreUI/Atomic/Atoms/Views/GraphView.swift rename to MVMCoreUI/Atomic/Atoms/Views/Wheel.swift index 3cf22d79..da71ea0f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/GraphView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Wheel.swift @@ -1,5 +1,5 @@ // -// GraphView.swift +// Wheel.swift // MobileFirstFramework // // Created by Ryan on 10/24/19. @@ -8,12 +8,12 @@ import UIKit -@objcMembers open class GraphView: View, MVMCoreUIViewConstrainingProtocol { +@objcMembers open class Wheel: View, MVMCoreUIViewConstrainingProtocol { var heightConstraint: NSLayoutConstraint? var gradientLayer: CALayer? - var graphModel: CircleProgressModel? { - return model as? CircleProgressModel + var graphModel: WheelModel? { + return model as? WheelModel } // MARK: setup @@ -28,7 +28,7 @@ import UIKit override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let model = model as? CircleProgressModel else { return } + guard let model = model as? WheelModel else { return } createGraphCircle(model) rotationAnimation(model) } @@ -42,7 +42,7 @@ import UIKit } // MARK: circle - open func createGraphCircle(_ graphObject: CircleProgressModel) { + open func createGraphCircle(_ graphObject: WheelModel) { if let sublayers = layer.sublayers { for sublayer in sublayers { sublayer.removeAllAnimations() @@ -56,7 +56,7 @@ import UIKit //begin point will be at the bottom, clockwise direction let path = UIBezierPath(arcCenter: CGPoint(x: radius - , y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(GraphView.getPiValue(90.0)), endAngle: CGFloat(GraphView.getPiValue(90.0 + 360.0)), clockwise: true) + , y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(Wheel.getPiValue(90.0)), endAngle: CGFloat(Wheel.getPiValue(90.0 + 360.0)), clockwise: true) path.lineWidth = graphObject.lineWidth let circleLayer = CAShapeLayer() @@ -83,7 +83,7 @@ import UIKit | | | ------------- */ - func createGradientLayer(_ graphObject: CircleProgressModel) -> CALayer { + func createGradientLayer(_ graphObject: WheelModel) -> CALayer { let containLayer = CALayer() containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter) let radius = graphObject.diameter / 2.0 @@ -151,18 +151,18 @@ import UIKit } //MARK: Animation - func rotationAnimation(_ object: CircleProgressModel) { + func rotationAnimation(_ object: WheelModel) { MVMCoreDispatchUtility.performBlock(onMainThread:{ let rotation = CABasicAnimation(keyPath: "transform.rotation") - let animationHandler = GraphViewAnimationHandler.shared + let animationHandler = WheelAnimationHandler.shared let startAngle = animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime()) if startAngle == 0.0 { animationHandler.storeAnimation(object.duration, CACurrentMediaTime()) } - var fromValue = GraphView.getPiValue(0.0 + startAngle), toValue = GraphView.getPiValue(360.0 + startAngle) + var fromValue = Wheel.getPiValue(0.0 + startAngle), toValue = Wheel.getPiValue(360.0 + startAngle) if !object.clockwise { - fromValue = GraphView.getPiValue(360.0 - startAngle) - toValue = GraphView.getPiValue(0.0 - startAngle) + fromValue = Wheel.getPiValue(360.0 - startAngle) + toValue = Wheel.getPiValue(0.0 - startAngle) } rotation.fromValue = fromValue rotation.toValue = toValue @@ -180,7 +180,7 @@ import UIKit } -extension GraphView: CAAnimationDelegate { +extension Wheel: CAAnimationDelegate { public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if let object = graphModel { rotationAnimation(object) diff --git a/MVMCoreUI/Atomic/Atoms/Views/GraphViewAnimationHandler.swift b/MVMCoreUI/Atomic/Atoms/Views/WheelAnimationHandler.swift similarity index 82% rename from MVMCoreUI/Atomic/Atoms/Views/GraphViewAnimationHandler.swift rename to MVMCoreUI/Atomic/Atoms/Views/WheelAnimationHandler.swift index 2d7489dc..9a862cec 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/GraphViewAnimationHandler.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WheelAnimationHandler.swift @@ -1,5 +1,5 @@ // -// GraphViewAnimationHandler.swift +// WheelAnimationHandler.swift // MobileFirstFramework // // Created by Ryan on 10/29/19. @@ -8,12 +8,12 @@ import UIKit -@objcMembers open class GraphViewAnimationHandler: NSObject { +@objcMembers open class WheelAnimationHandler: NSObject { /// duration : CACurrentMediaTime() private var animations = [Double: Double]() - static let shared = GraphViewAnimationHandler() + static let shared = WheelAnimationHandler() open func storeAnimation(_ duration: Double, _ currentTime: CFTimeInterval) { guard animations[duration] == nil else { diff --git a/MVMCoreUI/Atomic/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift similarity index 96% rename from MVMCoreUI/Atomic/Atoms/Views/CircleProgressModel.swift rename to MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift index 2fc67b44..85e4fffb 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WheelModel.swift @@ -1,5 +1,5 @@ // -// CircleProgressModel.swift +// WheelModel.swift // MVMCoreUI // // Created by Scott Pfeil on 1/13/20. @@ -16,9 +16,9 @@ public enum GraphStyle: String, Codable { case unlimited, safetyMode } -public class CircleProgressModel: MoleculeModelProtocol { +public class WheelModel: MoleculeModelProtocol { - public static var identifier: String = "circleProgress" + public static var identifier: String = "wheel" public var style: GraphStyle = .unlimited { didSet { updateStyle() diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 7d35dbce..354bb082 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -72,7 +72,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: DashLine.self, viewModelClass: DashLineModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MFLoadImageView.self, viewModelClass: ImageViewModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: GraphView.self, viewModelClass: CircleProgressModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: Wheel.self, viewModelClass: WheelModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) MoleculeObjectMapping.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index 8ca28609..f7c65dbe 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -8,7 +8,7 @@ import Foundation @objcMembers open class ListRVWheel: TableViewCell { - let wheel = GraphView(frame: .zero) + let wheel = Wheel(frame: .zero) let leftLabel = Label.commonLabelB1(true) let rightLabel = Label.commonLabelB2(true) var stack: Stack diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift index 89b70b0f..a5df2cfe 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift @@ -11,9 +11,9 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listRVWheel" public var leftLabel: LabelModel public var rightLabel: LabelModel - public var wheel : CircleProgressModel + public var wheel: WheelModel - public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) { + public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: WheelModel) { self.leftLabel = leftLabel self.rightLabel = rightLabel self.wheel = wheel @@ -37,7 +37,7 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) - wheel = try typeContainer.decodeIfPresent(CircleProgressModel.self, forKey: .wheel) ?? CircleProgressModel() + wheel = try typeContainer.decodeIfPresent(WheelModel.self, forKey: .wheel) ?? WheelModel() try super.init(from: decoder) } From 10ed8bcb6658b0d0a757da5fcfe9d455bfca62b7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 11:45:06 -0400 Subject: [PATCH 006/136] link color update MOBFIRST-20060 --- MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift | 2 +- MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift | 2 +- MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift index 9fe48936..5b4e5671 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/ExternalLink.swift @@ -25,7 +25,7 @@ open class ExternalLink: Link { guard let model = model as? ExternalLinkModel else { return } - exportImageView?.tintColor = model.textColor.uiColor + exportImageView?.tintColor = model.enabledColor.uiColor } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index d65ce3ce..5f5e6e12 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -52,7 +52,7 @@ import UIKit guard let model = model as? LinkModel else { return } setTitle(model.title, for: .normal) - setTitleColor(model.textColor.uiColor, for: .normal) + setTitleColor(model.enabledColor.uiColor, for: .normal) setTitleColor(model.disabledColor.uiColor, for: .disabled) isEnabled = model.enabled set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift index 7a4661bd..a54f23e9 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift @@ -21,7 +21,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public var title: String public var action: ActionModelProtocol public var enabled = true - public var textColor = Color(uiColor: .mvmBlack) + public var enabledColor = Color(uiColor: .mvmBlack) public var disabledColor = Color(uiColor: .mvmCoolGray6) //-------------------------------------------------- @@ -43,7 +43,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { case title case action case enabled - case textColor + case enabledColor case disabledColor } @@ -60,8 +60,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) { - textColor = color + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) { + enabledColor = color } if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) { @@ -76,7 +76,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabled) - try container.encode(textColor, forKey: .textColor) + try container.encode(enabledColor, forKey: .enabledColor) try container.encode(disabledColor, forKey: .disabledColor) } } From 1e67404748af16ef0283ccd651356693b444cf78 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Fri, 3 Apr 2020 12:03:13 -0400 Subject: [PATCH 007/136] add new tabs --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../HorizontalCombinationViews/Tabs.swift | 343 ++++++++++++++++++ .../TabsModel.swift | 36 +- .../Molecules/Items/TabsTableViewCell.swift | 38 +- 5 files changed, 395 insertions(+), 27 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 49ac139e..914b4afc 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -173,6 +173,7 @@ 94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */; }; 94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; + 94F6516D2437954100631BF9 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94F6516C2437954100631BF9 /* Tabs.swift */; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; }; AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; @@ -566,6 +567,7 @@ 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = ""; }; 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimaryButtonView.h; sourceTree = ""; }; 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = ""; }; + 94F6516C2437954100631BF9 /* Tabs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = ""; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = ""; }; 94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = ""; }; AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = ""; }; @@ -1169,6 +1171,7 @@ D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */, D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */, D28A837E23CCA96400DFE4FC /* TabsModel.swift */, + 94F6516C2437954100631BF9 /* Tabs.swift */, 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, ); @@ -2042,6 +2045,7 @@ 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, + 94F6516D2437954100631BF9 /* Tabs.swift in Sources */, 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 438f652b..08cbd301 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -85,6 +85,7 @@ import Foundation // Horizontal Combination Molecules MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self) // Vertical Combination Molecules MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift new file mode 100644 index 00000000..d49cd414 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -0,0 +1,343 @@ +// +// Tabs.swift +// MVMCoreUI +// +// Created by Ryan on 2/7/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objc public protocol TabsDelegate { + func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool + func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) +} + +@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol { + + public var tabsModel: TabsModel? { + get { return model as? TabsModel } + } + + var delegateObject: MVMCoreUIDelegateObject? + var additionalData: [AnyHashable: Any]? + + let layout = UICollectionViewFlowLayout() + public var collectionView: UICollectionView? + + let bottomScrollView = UIScrollView(frame: .zero) + let bottomContentView = View() + let bottomLine = View() + var bottomLineLeftConstraint: NSLayoutConstraint? + var bottomLineWidthConstraint: NSLayoutConstraint? + + //delegate + public var delegate: TabsDelegate? + + //control var + public var heightConstraint: NSLayoutConstraint? + public var selectedIndex: Int = 0 + public var paddingBeforeFirstTab: Bool = true + + //constant + let TabCellId = "TabCell" + public let sectionPadding: CGFloat = 20.0 + public let cellSpacing: CGFloat = 34.0 + public let cellHeight: CGFloat = 34.0 + public let bottomLineHeight: CGFloat = 4.0 + public let bottomLineWidth: CGFloat = 32.0 + public let tabsHeight: CGFloat = 38.0 + public let bottomLineMovingTime: TimeInterval = 0.2 + + //------------------------------------------------- + // MARK:- Layout Views + //------------------------------------------------- + + open override func reset() { + super.reset() + heightConstraint?.constant = tabsHeight + selectedIndex = 0 + paddingBeforeFirstTab = true + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + } + + open override func setupView() { + super.setupView() + backgroundColor = .white + setupCollectionView() + setupBottomLine() + setupConstraints() + } + + func setupCollectionView () { + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = cellSpacing + + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.translatesAutoresizingMaskIntoConstraints = false + collectionView.register(TabItemCell.self, forCellWithReuseIdentifier: TabCellId) + collectionView.backgroundColor = .clear + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false + collectionView.dataSource = self + collectionView.delegate = self + addSubview(collectionView) + self.collectionView = collectionView + } + + func setupBottomLine() { + bottomScrollView.translatesAutoresizingMaskIntoConstraints = false + bottomScrollView.delegate = self + addSubview(bottomScrollView) + bottomScrollView.addSubview(bottomContentView) + bottomLine.backgroundColor = .mfTomatoRed() + bottomContentView.addSubview(bottomLine) + bringSubviewToFront(bottomScrollView) + } + + func setupConstraints() { + //collection view + NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) + + //bottom lines + NSLayoutConstraint.constraintPinSubview(bottomScrollView, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) + bottomScrollView.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true + NSLayoutConstraint.constraintPinSubview(bottomLine, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) + bottomLine.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true + bottomLineLeftConstraint = bottomLine.leftAnchor.constraint(equalTo: bottomContentView.leftAnchor) + bottomLineLeftConstraint?.isActive = true + bottomLineWidthConstraint = bottomLine.widthAnchor.constraint(equalToConstant: bottomLineWidth) + bottomLineWidthConstraint?.isActive = true + NSLayoutConstraint.constraintPinSubview(toSuperview: bottomContentView) + + //height + heightConstraint = heightAnchor.constraint(equalToConstant: tabsHeight) + heightConstraint?.isActive = true + } + + //------------------------------------------------- + // MARK:- Control Methods + //------------------------------------------------- + + public func pinHeight(_ height: CGFloat) { + heightConstraint?.constant = height + setNeedsLayout() + layoutIfNeeded() + } + + public func selectIndex(_ index: Int, animated: Bool) { + guard let _ = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { + selectedIndex = index + return + } + MVMCoreDispatchUtility.performBlock(onMainThread: { + let currentIndex = self.selectedIndex + self.selectedIndex = index + self.deselect(indexPath: IndexPath(row: currentIndex, section: 0)) + self.selectItem(atIndexPath: IndexPath(row: index, section: 0), animated: animated) + }) + } + + public func reloadData() { + collectionView?.reloadData() + } + + //------------------------------------------------- + // MARK:- Molecule Setup + //------------------------------------------------- + + override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + self.delegateObject = delegateObject + self.additionalData = additionalData + self.selectedIndex = tabsModel?.selectedIndex ?? 0 + self.bottomLine.backgroundColor = tabsModel?.selectedColor.uiColor + reloadData() + } +} + +//------------------------------------------------- +// MARK:- Collection View Methods +//------------------------------------------------- + +extension Tabs: UICollectionViewDataSource { + public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return tabsModel?.tabs.count ?? 0 + } + + public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let labelModel = tabsModel?.tabs[indexPath.row].label, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else { + return UICollectionViewCell() + } + cell.updateCell(labelModel: labelModel, indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel) + return cell + } +} + +extension Tabs: UICollectionViewDelegateFlowLayout { + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + guard let labelModel = tabsModel?.tabs[indexPath.row].label else { + return .zero + } + return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight) + } + + func getLabelWidth(_ labelModel: LabelModel?) -> CGSize { + guard let labelModel = labelModel else { return .zero} + let label = Label() + label.set(with: labelModel, nil, nil) + return label.intrinsicContentSize + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + if !paddingBeforeFirstTab && section == 0 { + return .zero + } else { + return UIEdgeInsets(top: 0, left: sectionPadding, bottom: 0, right: 0) + } + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + return sectionPadding + } + + public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + return delegate?.shouldSelectItem(indexPath, tabs: self) ?? true + } + + public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + selectIndex(indexPath.row, animated: true) + } + + public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + guard let tabCell = cell as? TabItemCell else { return } + if indexPath.row == selectedIndex { + moveBottomLine(toIndex: indexPath, animated: false, cell: tabCell) + } + } + + func deselect(indexPath:IndexPath) { + collectionView?.deselectItem(at: indexPath, animated: false) + collectionView?.reloadItems(at: [indexPath]) + } + + func selectItem(atIndexPath indexPath: IndexPath, animated: Bool) { + + guard let collect = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { return } + + collect.selectItem(at: indexPath, animated: animated, scrollPosition: .centeredHorizontally) + guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = self.tabsModel else { return } + self.moveBottomLine(toIndex: indexPath, animated: animated, cell: tabCell) + tabCell.label.textColor = tabsModel.selectedColor.uiColor + tabCell.updateAccessibility(indexPath: indexPath, selected: true, tabsModel: tabsModel) + tabCell.setNeedsDisplay() + tabCell.setNeedsLayout() + tabCell.layoutIfNeeded() + self.delegate?.didSelectItem(indexPath, tabs: self) + } +} + + +extension Tabs: UIScrollViewDelegate { + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard let offsetX = collectionView?.contentOffset.x else { return } + bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false) + } +} + + +//------------------------------------------------- +// MARK:- Bottom Line Methods +//------------------------------------------------- +extension Tabs { + func moveBottomLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) { + guard let collect = self.collectionView else {return} + + let size = collectionView(collect, layout: layout, sizeForItemAt: indexPath) + let barWidth = max(size.width, bottomLineWidth) + let animationBlock = { + [weak self] in + let x = cell.frame.origin.x + self?.bottomLineWidthConstraint?.constant = barWidth + self?.bottomLineLeftConstraint?.constant = x + (size.width - barWidth) / 2.0 + self?.bottomContentView.layoutIfNeeded() + } + if animated { + UIView.animate(withDuration: bottomLineMovingTime, animations: animationBlock) + } else { + animationBlock() + } + } + + public func progress(fromIndex: Int, toIndex: Int, progressPercentage percent: CGFloat) { + guard let _ = collectionView else { return } + MVMCoreDispatchUtility.performBlock(onMainThread: { + self.setBottomLine(fromIndex: IndexPath(row: fromIndex, section: 0), toIndex: IndexPath(row: toIndex, section: 0), percent: percent) + }) + } + + func setBottomLine(fromIndex: IndexPath, toIndex: IndexPath, percent: CGFloat) { + guard let fromCell = collectionView?.cellForItem(at: fromIndex) as? TabItemCell, let toCell = collectionView?.cellForItem(at: toIndex) as? TabItemCell else { + return + } + let fromWidth = getLabelWidth(fromCell.labelModel).width + let toWidth = getLabelWidth(toCell.labelModel).width + let finalWidth = (toWidth - fromWidth) * percent + fromWidth + bottomLineWidthConstraint?.constant = finalWidth + let xDifference = toCell.frame.origin.x - fromCell.frame.origin.x + let finalX = xDifference * percent + fromCell.frame.origin.x + bottomLineLeftConstraint?.constant = finalX + bottomContentView.layoutIfNeeded() + } +} + + + +@objcMembers public class TabItemCell: UICollectionViewCell { + public let label = Label() + public var labelModel: LabelModel? + + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } + + func setupView() { + contentView.addSubview(label) + NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true) + label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true + label.baselineAdjustment = .alignCenters + } + + public func updateCell(labelModel: LabelModel, indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) { + label.reset() + label.set(with: labelModel, delegateObject, additionalData) + self.labelModel = labelModel + if selected, let selectedColor = tabsModel?.selectedColor { + label.textColor = selectedColor.uiColor + } + updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel) + } + + public func updateAccessibility(indexPath: IndexPath, selected: Bool, tabsModel: TabsModel?) { + //Accessibility + isAccessibilityElement = false + contentView.isAccessibilityElement = true + let accKey = selected ? "toptabbar_tab_selected" : "AccTab" + let accLabel = "\(label.text ?? "") \(MVMCoreUIUtility.hardcodedString(withKey: accKey) ?? "")" + let accOrder = String(format: MVMCoreUIUtility.hardcodedString(withKey: "AccTabIndex") ?? "", indexPath.row + 1, tabsModel?.tabs.count ?? 0) + contentView.accessibilityLabel = "\(accLabel) \(accOrder)" + contentView.accessibilityHint = selected ? nil : MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint") + } +} + + diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 8b69c590..d663a703 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -11,7 +11,7 @@ import UIKit public class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" public var backgroundColor: Color? - public var tabs: [LabelModel] + public var tabs: [TabItemModel] public var selectedColor = Color(uiColor: .mfTomatoRed()) // Must be capped to 0...(tabs.count - 1) @@ -25,13 +25,13 @@ public class TabsModel: MoleculeModelProtocol { case moleculeName } - public init(with tabs: [LabelModel]) { + public init(with tabs: [TabItemModel]) { self.tabs = tabs } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - tabs = try typeContainer.decode([LabelModel].self, forKey: .tabs) + tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) { selectedColor = color @@ -50,3 +50,33 @@ public class TabsModel: MoleculeModelProtocol { try container.encode(selectedIndex, forKey: .selectedIndex) } } + + + +public class TabItemModel: Codable { + var label: LabelModel + var action: ActionModelProtocol? + + init(label: LabelModel) { + self.label = label + } + + private enum CodingKeys: String, CodingKey { + case label + case action + } + + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + label = try typeContainer.decode(LabelModel.self, forKey: .label) + action = try typeContainer.decodeModelIfPresent(codingKey: .action) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModel(label, forKey: .label) + try container.encodeModelIfPresent(action, forKey: .action) + } + +} diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift index 16794eb1..f9ed4243 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift @@ -12,7 +12,7 @@ import UIKit var tabsListItemModel: TabsListItemModel? { return listItemModel as? TabsListItemModel } - let tabs = TopTabbar(frame: .zero) + let tabs = Tabs(frame: .zero) var delegateObject: MVMCoreUIDelegateObject? var previousTabIndex = 0 @@ -22,7 +22,6 @@ import UIKit tabs.paddingBeforeFirstTab = false tabs.translatesAutoresizingMaskIntoConstraints = false tabs.delegate = self - tabs.datasource = self contentView.addSubview(tabs) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values)) @@ -39,7 +38,9 @@ import UIKit public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject - tabs.reloadData() + if let tabsModel = tabsListItemModel?.tabs { + tabs.set(with: tabsModel, delegateObject, additionalData) + } } public override func reset() { @@ -53,33 +54,22 @@ import UIKit } } -extension TabsTableViewCell: TopTabbarDelegate { - public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { +extension TabsTableViewCell: TabsDelegate { + public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool { if let model = tabsListItemModel { - let molecules = model.molecules[topTabbar.selectedIndex] - delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left) + let molecules = model.molecules[tabs.selectedIndex] + delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left) } previousTabIndex = tabs.selectedIndex return true } - public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { - guard let model = tabsListItemModel, - let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return } - let molecules = model.molecules[index] - delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) - } -} - -extension TabsTableViewCell: TopTabbarDataSource { - public func number(ofTopTabbarItems topTabbar: TopTabbar) -> Int { - return tabsListItemModel?.tabs.tabs.count ?? 0 - } - - public func topTabbar(_ topTabbar: TopTabbar, titleForItemAt index: Int) -> String? { - guard let title = tabsListItemModel?.tabs.tabs[index].text else { - return "Select" + public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) { + let index = indexPath.row + if let model = tabsListItemModel, index < model.molecules.count { + let molecules = model.molecules[index] + delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) } - return title } } + From 7382d9acf55674367a22d7ab1eef02c6042ece0b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 13:44:20 -0400 Subject: [PATCH 008/136] Textfield key updates: MOBFIRST-20088 --- .../Atomic/Atoms/TextFields/EntryField.swift | 6 ++-- .../Atoms/TextFields/EntryFieldModel.swift | 36 +++++++++---------- .../Atoms/TextFields/TextEntryField.swift | 9 +---- .../TextFields/TextEntryFieldModel.swift | 4 --- 4 files changed, 20 insertions(+), 35 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index a02f87ee..88aa1559 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -256,12 +256,12 @@ import UIKit title = model.title feedback = model.feedback errorMessage = model.errorMessage - isEnabled = model.isEnabled + isEnabled = model.enabled - if let isLocked = model.isLocked { + if let isLocked = model.locked { self.isLocked = isLocked - } else if let isSelected = model.isSelected{ + } else if let isSelected = model.selected { self.isSelected = isSelected } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 729b3516..79de359b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -9,7 +9,7 @@ import Foundation -@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol { +@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -23,9 +23,9 @@ import Foundation public var title: String? public var feedback: String? public var errorMessage: String = "" - public var isEnabled: Bool = true - public var isLocked: Bool? - public var isSelected: Bool? + public var enabled: Bool = true + public var locked: Bool? + public var selected: Bool? public var text: String? public var fieldKey: String? @@ -52,14 +52,12 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor - case title = "label" - case isEnabled + case title + case enabled case feedback - case errorMessage = "errorMsg" - case isLocked - case isSelected - case isValid - case isRequired = "required" + case errorMessage + case locked + case selected case text case fieldKey case groupName @@ -84,10 +82,9 @@ import Foundation title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? "" - isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true - isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked) - isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) - isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid) + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked) + selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) text = try typeContainer.decodeIfPresent(String.self, forKey: .text) baseValue = text @@ -104,12 +101,11 @@ import Foundation try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) try container.encode(errorMessage, forKey: .errorMessage) - try container.encode(isEnabled, forKey: .isEnabled) - try container.encode(isLocked, forKey: .isLocked) - try container.encode(isSelected, forKey: .isSelected) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(isValid, forKey: .isValid) + 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(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 2e7df5ee..a421cb46 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -308,14 +308,7 @@ import UIKit break } - if let regex = model.regex, !regex.isEmpty { - validationBlock = { enteredValue in - guard let value = enteredValue else { return false } - return MVMCoreUIUtility.validate(value, withRegularExpression: regex) - } - } else { - defaultValidationBlock() - } + defaultValidationBlock() uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index c35d812e..0057b46a 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -27,7 +27,6 @@ public var enabledTextColor: Color? public var disabledTextColor: Color? public var type: EntryType? - public var regex: String? //-------------------------------------------------- // MARK: - Keys @@ -40,7 +39,6 @@ case enabledTextColor case disabledTextColor case type - case regex } //-------------------------------------------------- @@ -55,7 +53,6 @@ enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type) - regex = try typeContainer.decodeIfPresent(String.self, forKey: .regex) } public override func encode(to encoder: Encoder) throws { @@ -67,6 +64,5 @@ try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(type, forKey: .type) - try container.encodeIfPresent(regex, forKey: .regex) } } From 817e4cb7bab3c4cc09b1ebc4049097325f122a23 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 15:22:21 -0400 Subject: [PATCH 009/136] multi progress changes --- .../Atomic/Atoms/Views/MultiProgress.swift | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift index adf480c2..67a5f840 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift @@ -9,31 +9,38 @@ import UIKit @objcMembers open class MultiProgress: View { + private let stack = Stack() var multiProgressModel: MultiProgressBarModel? { get { return model as? MultiProgressBarModel } } - + + public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.init(frame: .zero) + set(with: model, delegateObject, additionalData) + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + ///passing value to progressList creates corresponding progress bars var progressList: Array? { didSet { - for subview in subviews { - subview.removeFromSuperview() - } - guard (progressList?.count ?? 0) > 0 else { - return - } - var previous: UIView? + stack.removeAllItemViews() + guard (progressList?.count ?? 0) > 0 else { return } + var viewModels: [(view: UIView, model: StackItemModel)] = [] for progressObject in progressList! { guard progressObject.percent > 0.0 else { continue } - let view = UIView(frame: .zero) - view.translatesAutoresizingMaskIntoConstraints = false - addSubview(view) - view.backgroundColor = progressObject.color.uiColor - view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.percent/100.0).isActive = true - view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true - previous = view - NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) + let model = StackItemModel(spacing: 0, percent: Int(progressObject.percent), horizontalAlignment: .fill, verticalAlignment: .fill) + model.backgroundColor = progressObject.color + viewModels.append((view: StackItem(frame: .zero), model: model)) } + stack.set(with: viewModels) + stack.restack() } } @@ -55,6 +62,8 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false backgroundColor = .mfLightSilver() clipsToBounds = true + addSubview(stack) + NSLayoutConstraint.constraintPinSubview(toSuperview: stack) if thicknessConstraint == nil { thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight) thicknessConstraint?.isActive = true From cbf0f85ea796fef35af2e8d10c8cb66aebea5f5d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 17:00:16 -0400 Subject: [PATCH 010/136] Fix to progress bar spacing MOBFIRST-20303 Brought back molecule stack --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ .../Atomic/Atoms/Views/MultiProgress.swift | 50 ++++++++------- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 2 +- .../Doughnut/DoughnutChartView.swift | 2 +- .../StringAndMoleculeStack.swift | 2 +- .../Atomic/Organisms/MoleculeStackView.swift | 61 +++++++++++++++++++ MVMCoreUI/Atomic/Organisms/Stack.swift | 25 +------- 7 files changed, 98 insertions(+), 48 deletions(-) create mode 100644 MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 33daa259..ffbc8621 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -202,6 +202,7 @@ D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; + D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelToggle.swift */; }; D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224798B231450C8003FCCF9 /* HeadlineBodyToggle.swift */; }; @@ -589,6 +590,7 @@ D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; + D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; D22479892314445E003FCCF9 /* LabelToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggle.swift; sourceTree = ""; }; D224798B231450C8003FCCF9 /* HeadlineBodyToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggle.swift; sourceTree = ""; }; @@ -1181,6 +1183,7 @@ D260105A23D0BB7100764D80 /* StackModelProtocol.swift */, D260106423D0CEA700764D80 /* StackModel.swift */, D260105C23D0BCD400764D80 /* Stack.swift */, + D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */, 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */, D2A6390022CBB1820052ED1F /* Carousel.swift */, ); @@ -1924,6 +1927,7 @@ D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, + D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */, 0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift index 67a5f840..6339d002 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift @@ -27,23 +27,6 @@ import UIKit super.init(frame: frame) } - ///passing value to progressList creates corresponding progress bars - var progressList: Array? { - didSet { - stack.removeAllItemViews() - guard (progressList?.count ?? 0) > 0 else { return } - var viewModels: [(view: UIView, model: StackItemModel)] = [] - for progressObject in progressList! { - guard progressObject.percent > 0.0 else { continue } - let model = StackItemModel(spacing: 0, percent: Int(progressObject.percent), horizontalAlignment: .fill, verticalAlignment: .fill) - model.backgroundColor = progressObject.color - viewModels.append((view: StackItem(frame: .zero), model: model)) - } - stack.set(with: viewModels) - stack.restack() - } - } - var roundedCorners: Bool = false { didSet { if roundedCorners { @@ -62,30 +45,51 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false backgroundColor = .mfLightSilver() clipsToBounds = true + addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) + stack.backgroundColor = backgroundColor + stack.contentView.backgroundColor = .white + stack.model = StackModel(molecules: [], axis: .horizontal, spacing: 2) + stack.stackModel?.horizontalAlignment = .leading + if thicknessConstraint == nil { thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight) thicknessConstraint?.isActive = true } } + /// Creates the bars + open func set(with progressList: Array, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let stackModel = stack.stackModel else { return } + var views: [StackItem] = [] + var models: [StackItemModel] = [] + for progressObject in progressList { + guard progressObject.percent > 0.0 else { continue } + let model = StackItemModel(percent: Int(progressObject.percent), horizontalAlignment: .fill, verticalAlignment: .fill) + model.backgroundColor = progressObject.color + models.append(model) + views.append(StackItem()) + } + stack.stackItems = views + stackModel.molecules = models + stack.set(with: stackModel, delegateObject, additionalData) + } + //MARK: - MoleculeViewProtocol public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let multiProgressModel = multiProgressModel else { - return - } + guard let multiProgressModel = multiProgressModel else { return } roundedCorners = multiProgressModel.roundedCorners ?? false thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight - progressList = multiProgressModel.progressList - + stack.model?.backgroundColor = model.backgroundColor + set(with: multiProgressModel.progressList, delegateObject, additionalData) } open override func reset() { super.reset() backgroundColor = .mfLightSilver() - progressList = nil + set(with: [], nil, nil) } public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 354bb082..ee26efaa 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -37,7 +37,7 @@ import Foundation /// Call to register all of the CoreUI molecules. public static func registerObjects() { // Stacks - MoleculeObjectMapping.shared()?.register(viewClass: Stack.self, viewModelClass: StackModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: StackModel.self) MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self) MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift index bffea398..36bec9a5 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift @@ -88,7 +88,7 @@ extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { } } -class ColorViewLabelsStack: Stack { +class ColorViewLabelsStack: MoleculeStackView { override func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift index 8bd6d005..c887e838 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -9,7 +9,7 @@ import UIKit // This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need. -open class StringAndMoleculeStack: Stack { +open class StringAndMoleculeStack: MoleculeStackView { override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let model = model as? StackModelProtocol, let molcules = model.molecules as? [MoleculeStackItemModel] else { return } diff --git a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift new file mode 100644 index 00000000..c5c993f2 --- /dev/null +++ b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift @@ -0,0 +1,61 @@ +// +// MoleculeStackView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// +// This is a dynamic stack view that creates molecules if needed on set. + +import UIKit + +open class MoleculeStackView: Stack { + var previousModel: MoleculeModelProtocol? + + /// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack + func setup(with views: [View], lastItem: Bool) { + var models: [MoleculeStackItemModel] = [] + for view in views { + guard let model = view.model else { return } + let stackItemModel = MoleculeStackItemModel(with: model) + let stackItem = MoleculeStackItem(andContain: view) + stackItems.append(stackItem) + models.append(stackItemModel) + } + if let stackModel = stackModel { + stackModel.molecules = models + } else { + model = StackModel(molecules: models) + } + restack() + } + + + + // MARK: - Adding to stack + /// Can be subclassed to create views when we get stack item models and have no views yet + open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + guard let stackItemModels = stackModel?.molecules else { return } + for model in stackItemModels { + if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem { + stackItems.append(stackItem) + } + } + } + + open override func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + // If the items in the stack are different, clear them, create new ones. + if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) { + stackItems = [] + createStackItemsFromModel(model, delegateObject, additionalData) + } else { + super.setStackItemsFromModel(model, delegateObject, additionalData) + } + } + + /// + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + previousModel = self.model + super.set(with: model, delegateObject, additionalData) + } +} diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index ab17be3b..d43719a9 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -147,18 +147,9 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - let previousModel = self.model super.set(with: model, delegateObject, additionalData) removeAllItemViews() - - // If the items in the stack are different, clear them, create new ones. - if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) { - stackItems = [] - createStackItemsFromModel(model, delegateObject, additionalData) - } else { - setStackItemsFromModel(model, delegateObject, additionalData) - } - + setStackItemsFromModel(model, delegateObject, additionalData) restack() } @@ -216,16 +207,6 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto // MARK: - Subclassables //-------------------------------------------------- - /// Can be subclassed to create views when we get stack item models and have no views yet - open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let stackItemModels = (model as? StackModelProtocol)?.molecules else { return } - for model in stackItemModels { - if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) { - stackItems.append(stackItem) - } - } - } - /// Can be subclassed to set stack items with model when we already have views open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let models = stackModel?.molecules else { return } @@ -314,7 +295,7 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto if let percent = model.percent { let multiplier = CGFloat(percent) / 100.0 let constant = multiplier * totalSpacing - view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true + view.heightAnchor.constraint(equalTo: heightAnchor, multiplier: multiplier, constant: -constant).isActive = true } if lastItem { pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) @@ -333,7 +314,7 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto if let percent = model.percent { let multiplier = CGFloat(percent) / 100.0 let constant = multiplier * totalSpacing - view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true + view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: multiplier, constant: -constant).isActive = true } if lastItem { pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0) From 2e7dc614c50dff9919e8f9bdc2aa6cc09e0ee48c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 3 Apr 2020 18:49:02 -0400 Subject: [PATCH 011/136] Key changes --- MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift index b095f19e..b26bbc8a 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift @@ -49,7 +49,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { return nil } - let stack = Stack(frame: .zero) + let stack = MoleculeStackView(frame: .zero) moleculeStackModel.useStackSpacingBeforeFirstItem = true moleculeStackModel.useHorizontalMargins = true stack.set(with: moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil) From dc2dfe42bb86b04c975a54bcefed934df9d94185 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 6 Apr 2020 11:37:14 -0400 Subject: [PATCH 012/136] MoleculeStack --- MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift index b095f19e..b26bbc8a 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift @@ -49,7 +49,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { return nil } - let stack = Stack(frame: .zero) + let stack = MoleculeStackView(frame: .zero) moleculeStackModel.useStackSpacingBeforeFirstItem = true moleculeStackModel.useHorizontalMargins = true stack.set(with: moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil) From 63f225398bdb11dde1e6bede8f2a3a91219304b4 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 7 Apr 2020 17:59:28 +0530 Subject: [PATCH 013/136] Added Radioswatches and radioswatchitem class files. --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ .../Atoms/Buttons/RadioSwatchItem.swift | 106 ++++++++++++++++++ .../Atomic/Atoms/Buttons/RadioSwatches.swift | 91 +++++++++++++++ .../Atoms/Buttons/RadioSwatchesModel.swift | 76 +++++++++++-- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 3 + 5 files changed, 277 insertions(+), 7 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchItem.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatches.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 7bd74df8..36a87994 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -173,6 +173,8 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; + AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; + AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatchItem.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; }; @@ -557,6 +559,8 @@ AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; + AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; + AAB9C109243496DD00151545 /* RadioSwatchItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItem.swift; sourceTree = ""; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = ""; }; BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = ""; }; @@ -1495,6 +1499,8 @@ 011D95AE2407266E000E3791 /* RadioButtonModel.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, + AAB9C10724346F4B00151545 /* RadioSwatches.swift */, + AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, ); path = Buttons; sourceTree = ""; @@ -1897,6 +1903,7 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */, + AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */, 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, @@ -1938,6 +1945,7 @@ D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, + AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* ValidProtocol.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchItem.swift new file mode 100644 index 00000000..9693fe62 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchItem.swift @@ -0,0 +1,106 @@ +// +// RadioSwatchItem.swift +// MVMCoreUI +// +// Created by Lekshmi S on 01/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { + public var bottomText = Label.commonLabelB2(true) + let circleLayer = CAShapeLayer() + let outerCircleLayer = CAShapeLayer() + var cellView = MVMCoreUICommonViewsUtility.commonView() + var fillColor: Color = Color(uiColor: .mvmBlue) + + open override var isSelected: Bool { + didSet { + drawCircle() + isSelected ? drawOuterCircle() : removeOuterCircle() + isSelected ? (bottomText.isHidden = false) : (bottomText.isHidden = true) + } + } + + var isStrikeThrough: Bool = false { + didSet { + if isStrikeThrough { + drawStrikeThrough() + } + } + } + + public override init(frame: CGRect) { + super.init(frame: .zero) + setupView() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + public func drawCircle() { + circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath + circleLayer.fillColor = fillColor.cgColor + circleLayer.strokeColor = UIColor.mvmCoolGray6.cgColor + cellView.layer.addSublayer(circleLayer) + } + + public func drawStrikeThrough() { + let startPoint = CGPoint(x: 12, y: 30) + let endPoint = CGPoint(x: 42, y: 0) + let bezierPath = UIBezierPath() + bezierPath.move(to: startPoint) + bezierPath.addLine(to: endPoint) + let strikeThroughLayer = CAShapeLayer() + strikeThroughLayer.path = bezierPath.cgPath + strikeThroughLayer.strokeColor = UIColor.mvmBlack.cgColor + strikeThroughLayer.lineWidth = 1 + cellView.layer.addSublayer(strikeThroughLayer) + isUserInteractionEnabled = false + } + + public func drawOuterCircle() { + circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath + outerCircleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath + outerCircleLayer.name = "OuterCircle" + outerCircleLayer.strokeColor = UIColor.mvmCoolGray6.cgColor + outerCircleLayer.fillColor = UIColor.clear.cgColor + cellView.layer.addSublayer(outerCircleLayer) + } + + public func removeOuterCircle() { + circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath + self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()}) + } + + public func setupView() { + guard cellView.superview == nil else { + return + } + isAccessibilityElement = false + contentView.isAccessibilityElement = false + insetsLayoutMarginsFromSafeArea = false + contentView.insetsLayoutMarginsFromSafeArea = false + contentView.preservesSuperviewLayoutMargins = false + contentView.addSubview(cellView) + NSLayoutConstraint.constraintPinSubview(toSuperview: cellView) + cellView.addSubview(bottomText) + bottomText.textAlignment = .center + bottomText.topAnchor.constraint(equalTo: cellView.topAnchor, constant: 38).isActive = true + bottomText.leadingAnchor.constraint(equalTo: cellView.leadingAnchor).isActive = true + bottomText.trailingAnchor.constraint(equalTo: cellView.trailingAnchor).isActive = true + cellView.bottomAnchor.constraint(equalTo: bottomText.bottomAnchor).isActive = true + } + + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let collectionModel = model as? RadioSwatchItemModel else { return } + fillColor = collectionModel.color + isSelected = collectionModel.selected ?? false + isUserInteractionEnabled = collectionModel.enabled ?? true + isStrikeThrough = collectionModel.strikethrough ?? false + bottomText.text = collectionModel.text + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatches.swift new file mode 100644 index 00000000..5c0c24be --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatches.swift @@ -0,0 +1,91 @@ +// +// RadioSwatches.swift +// MVMCoreUI +// +// Created by Lekshmi S on 01/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class RadioSwatches: View { + public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) + var swatches: [MoleculeModelProtocol]? + public var collectionViewHeight: NSLayoutConstraint? + + public let cellSize: Double = 54.0 + public let spacing: Double = 10 + + open override func setupView() { + super.setupView() + guard collectionView.superview == nil else { + return + } + collectionView.translatesAutoresizingMaskIntoConstraints = false + collectionView.dataSource = self + collectionView.delegate = self + collectionView.showsHorizontalScrollIndicator = false + collectionView.backgroundColor = .clear + collectionView.isAccessibilityElement = false + addSubview(collectionView) + NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) + collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100) + collectionViewHeight?.isActive = true + } + + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let radioSwatchesModel = model as? RadioSwatchesModel else { return } + collectionView.layer.borderColor = backgroundColor?.cgColor + registerCells() + setupLayout(with: radioSwatchesModel) + prepareMolecules(with: radioSwatchesModel) + collectionView.reloadData() + } + + func registerCells() { + collectionView.register(RadioSwatchItem.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") + } + + func setupLayout(with radioSwatchesModel: RadioSwatchesModel?) { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .vertical + layout.minimumLineSpacing = CGFloat(spacing) + layout.minimumInteritemSpacing = CGFloat(spacing) + collectionView.collectionViewLayout = layout + } + + func prepareMolecules(with radioSwatchesModel: RadioSwatchesModel?) { + guard let newSwatches = radioSwatchesModel?.swatches else { + swatches = nil + return + } + swatches = newSwatches + let collectionViewWidth = UIScreen.main.bounds.width - (2 * MFStyler.defaultHorizontalPaddingForApplicationWidth()) + let swatchesInRow = Double(floor(Double(collectionViewWidth/60.0))) + let numberOfRows = floor(Double(swatches?.count ?? 1)/swatchesInRow) + 1.0 + let height = (numberOfRows * cellSize) + (spacing * (numberOfRows-1)) + collectionViewHeight?.constant = CGFloat(height) + collectionViewHeight?.isActive = true + } +} + +extension RadioSwatches: UICollectionViewDelegateFlowLayout { + open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + return CGSize(width: cellSize, height: cellSize) + } +} + +extension RadioSwatches: UICollectionViewDataSource { + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return swatches?.count ?? 0 + } + + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItem else { + return UICollectionViewCell() + } + cell.set(with: molecule, nil, nil) + return cell + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift index 734ecbfd..ba6cddef 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift @@ -11,25 +11,87 @@ import Foundation @objcMembers public class RadioSwatchesModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "radioSwatches" - public var moleculeName: String = RadioSwatchesModel.identifier public var swatches: [RadioSwatchItemModel] public init(swatches: [RadioSwatchItemModel]) { self.swatches = swatches } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case swatches + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches) + self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(swatches, forKey: .swatches) + } } @objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "radioSwatchItem" - public var moleculeName: String = RadioSwatchItemModel.identifier - public var text: String - public var enabled: Bool - public var color: Color + public var color: Color = Color(uiColor: .mvmBlue) + public var text: String? + public var selected: Bool? = false + public var enabled: Bool? = true + public var strikethrough: Bool? = false - public init(enabled: Bool, color: Color, text: String) { - self.enabled = enabled + public init(color: Color, text:String, selected: Bool, enabled: Bool, strikethrough: Bool) { self.color = color self.text = text + self.selected = selected + self.enabled = enabled + self.strikethrough = strikethrough + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case color + case text + case selected + case enabled + case strikethrough + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + color = try typeContainer.decode(Color.self, forKey: .color) + if let text = try typeContainer.decodeIfPresent(String.self, forKey: .text) { + self.text = text + } + if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { + self.selected = selected + } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { + self.strikethrough = strikethrough + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(color, forKey: .color) + try container.encode(text, forKey: .text) + try container.encode(selected, forKey: .selected) + try container.encode(enabled, forKey: .enabled) + try container.encode(strikethrough, forKey: .strikethrough) } } + + diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index bfa6db01..67a5cfed 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -111,6 +111,9 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackItem.self, viewModelClass: MoleculeStackItemModel.self) MoleculeObjectMapping.shared()?.register(viewClass: StackItem.self, viewModelClass: StackItemModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: CarouselItemModel.self) + + MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatchItem.self, viewModelClass: RadioSwatchItemModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self) // Other Container Molecules MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self) From 237ddb82251e2daefdaee2c591d9b427a2b0f6dc Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 7 Apr 2020 18:07:40 +0530 Subject: [PATCH 014/136] Added folder structure --- MVMCoreUI.xcodeproj/project.pbxproj | 22 +++++++++++++------ .../RadioSwatchItem.swift | 0 .../RadioSwatches.swift | 0 .../RadioSwatchesModel.swift | 0 4 files changed, 15 insertions(+), 7 deletions(-) rename MVMCoreUI/Atomic/Atoms/{Buttons => Selectors}/RadioSwatchItem.swift (100%) rename MVMCoreUI/Atomic/Atoms/{Buttons => Selectors}/RadioSwatches.swift (100%) rename MVMCoreUI/Atomic/Atoms/{Buttons => Selectors}/RadioSwatchesModel.swift (100%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index fad7e2e3..17ec4e42 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -182,11 +182,11 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; - BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; }; - BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatchItem.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; + BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; }; + BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; }; BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */; }; @@ -583,11 +583,11 @@ AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; - BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = ""; }; - BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = ""; }; AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; AAB9C109243496DD00151545 /* RadioSwatchItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItem.swift; sourceTree = ""; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; + BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = ""; }; + BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = ""; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = ""; }; BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = ""; }; BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinks.swift; sourceTree = ""; }; @@ -1055,6 +1055,16 @@ path = RightVariable; sourceTree = ""; }; + AA56A26D243CAB0800303286 /* Selectors */ = { + isa = PBXGroup; + children = ( + AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, + AAB9C10724346F4B00151545 /* RadioSwatches.swift */, + AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, + ); + path = Selectors; + sourceTree = ""; + }; D202AFE2242A5F1400E5BEDF /* Extensions */ = { isa = PBXGroup; children = ( @@ -1425,6 +1435,7 @@ D29DF10D21E67A70003B2FB9 /* Atoms */ = { isa = PBXGroup; children = ( + AA56A26D243CAB0800303286 /* Selectors */, D29DF22B21E6A0FA003B2FB9 /* TextFields */, D29DF17D21E69E26003B2FB9 /* Views */, D29DF16821E69E1F003B2FB9 /* Buttons */, @@ -1565,9 +1576,6 @@ 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */, 011D95AE2407266E000E3791 /* RadioButtonModel.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, - AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, - AAB9C10724346F4B00151545 /* RadioSwatches.swift */, - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, ); path = Buttons; sourceTree = ""; diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchItem.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatches.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Buttons/RadioSwatchesModel.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift From d351d6cd7c0a46bad043bcb6e9cdbb4f6049f4f3 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 7 Apr 2020 19:02:50 +0530 Subject: [PATCH 015/136] Code changes after review --- MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index ba6cddef..d926ad5c 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -87,10 +87,10 @@ import Foundation try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(color, forKey: .color) - try container.encode(text, forKey: .text) - try container.encode(selected, forKey: .selected) - try container.encode(enabled, forKey: .enabled) - try container.encode(strikethrough, forKey: .strikethrough) + try container.encodeIfPresent(text, forKey: .text) + try container.encodeIfPresent(selected, forKey: .selected) + try container.encodeIfPresent(enabled, forKey: .enabled) + try container.encodeIfPresent(strikethrough, forKey: .strikethrough) } } From f46b9cb339502b7110bf8b7f093e9dff97480bcc Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Wed, 8 Apr 2020 19:57:27 +0530 Subject: [PATCH 016/136] Radio swatch elements - modify story commit --- .../Atomic/Atoms/Selectors/RadioSwatchItem.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift index 9693fe62..3404f7f7 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift @@ -25,6 +25,7 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { var isStrikeThrough: Bool = false { didSet { + cellView.layer.sublayers?.filter({$0.name == "OutOfStock"}).forEach({$0.removeFromSuperlayer()}) if isStrikeThrough { drawStrikeThrough() } @@ -44,7 +45,8 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { public func drawCircle() { circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath circleLayer.fillColor = fillColor.cgColor - circleLayer.strokeColor = UIColor.mvmCoolGray6.cgColor + circleLayer.strokeColor = UIColor.mvmBlack.cgColor + circleLayer.lineWidth = 1 cellView.layer.addSublayer(circleLayer) } @@ -56,18 +58,19 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { bezierPath.addLine(to: endPoint) let strikeThroughLayer = CAShapeLayer() strikeThroughLayer.path = bezierPath.cgPath - strikeThroughLayer.strokeColor = UIColor.mvmBlack.cgColor + strikeThroughLayer.name = "OutOfStock" + strikeThroughLayer.strokeColor = UIColor.mvmCoolGray6.cgColor strikeThroughLayer.lineWidth = 1 cellView.layer.addSublayer(strikeThroughLayer) - isUserInteractionEnabled = false } public func drawOuterCircle() { circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath outerCircleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath outerCircleLayer.name = "OuterCircle" - outerCircleLayer.strokeColor = UIColor.mvmCoolGray6.cgColor + outerCircleLayer.strokeColor = UIColor.mvmBlack.cgColor outerCircleLayer.fillColor = UIColor.clear.cgColor + outerCircleLayer.lineWidth = 1 cellView.layer.addSublayer(outerCircleLayer) } From 45901f31101876a9f456866a372fe43244b02161 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Thu, 9 Apr 2020 19:37:32 +0530 Subject: [PATCH 017/136] Added new keys and code changes. --- .../Atoms/Selectors/RadioSwatchItem.swift | 28 +++++++++-- .../Atoms/Selectors/RadioSwatches.swift | 48 ++++++++++++++++++- .../Atoms/Selectors/RadioSwatchesModel.swift | 28 ++++++++++- 3 files changed, 95 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift index 3404f7f7..17352ed7 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift @@ -9,12 +9,17 @@ import UIKit open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { - public var bottomText = Label.commonLabelB2(true) + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var bottomText = Label(frame: .zero) let circleLayer = CAShapeLayer() - let outerCircleLayer = CAShapeLayer() var cellView = MVMCoreUICommonViewsUtility.commonView() var fillColor: Color = Color(uiColor: .mvmBlue) - + + //------------------------------------------------------ + // MARK: - Property Observer + //------------------------------------------------------ open override var isSelected: Bool { didSet { drawCircle() @@ -32,6 +37,9 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { } } + //------------------------------------------------------ + // MARK: - Initialization + //------------------------------------------------------ public override init(frame: CGRect) { super.init(frame: .zero) setupView() @@ -42,10 +50,15 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { setupView() } + //------------------------------------------------------ + // MARK: - Drawing + //------------------------------------------------------ public func drawCircle() { + cellView.layer.sublayers?.filter({$0.name == "InnerCircle"}).forEach({$0.removeFromSuperlayer()}) circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath circleLayer.fillColor = fillColor.cgColor - circleLayer.strokeColor = UIColor.mvmBlack.cgColor + circleLayer.strokeColor = isUserInteractionEnabled ? UIColor.mvmBlack.cgColor : UIColor.mvmCoolGray6.cgColor + circleLayer.name = "InnerCircle" circleLayer.lineWidth = 1 cellView.layer.addSublayer(circleLayer) } @@ -65,7 +78,9 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { } public func drawOuterCircle() { + self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()}) circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath + let outerCircleLayer = CAShapeLayer() outerCircleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath outerCircleLayer.name = "OuterCircle" outerCircleLayer.strokeColor = UIColor.mvmBlack.cgColor @@ -79,6 +94,9 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()}) } + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- public func setupView() { guard cellView.superview == nil else { return @@ -92,6 +110,7 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { NSLayoutConstraint.constraintPinSubview(toSuperview: cellView) cellView.addSubview(bottomText) bottomText.textAlignment = .center + bottomText.font = MFFonts.mfFontTXRegular(11.0) bottomText.topAnchor.constraint(equalTo: cellView.topAnchor, constant: 38).isActive = true bottomText.leadingAnchor.constraint(equalTo: cellView.leadingAnchor).isActive = true bottomText.trailingAnchor.constraint(equalTo: cellView.trailingAnchor).isActive = true @@ -101,7 +120,6 @@ open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let collectionModel = model as? RadioSwatchItemModel else { return } fillColor = collectionModel.color - isSelected = collectionModel.selected ?? false isUserInteractionEnabled = collectionModel.enabled ?? true isStrikeThrough = collectionModel.strikethrough ?? false bottomText.text = collectionModel.text diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index 5c0c24be..a27af6c8 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -9,13 +9,29 @@ import UIKit open class RadioSwatches: View { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) - var swatches: [MoleculeModelProtocol]? - public var collectionViewHeight: NSLayoutConstraint? + var swatches: [RadioSwatchItemModel]? + public var selectedSwatchItem: RadioSwatchItemModel? { + get{ + guard let selectedItem = collectionView.indexPathsForSelectedItems?.first else {return nil} + return swatches?[selectedItem.item] + } + } + + //------------------------------------------------------ + // MARK: - Constraints + //------------------------------------------------------ + public var collectionViewHeight: NSLayoutConstraint? public let cellSize: Double = 54.0 public let spacing: Double = 10 + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- open override func setupView() { super.setupView() guard collectionView.superview == nil else { @@ -33,6 +49,17 @@ open class RadioSwatches: View { collectionViewHeight?.isActive = true } + public override func updateView(_ size: CGFloat) { + DispatchQueue.main.async { + self.collectionView.collectionViewLayout.invalidateLayout() + self.collectionView.reloadData() + guard let selectedCell = self.swatches?.firstIndex(where: {$0.selected == true}) else { + return + } + self.collectionView.selectItem(at: IndexPath(item: selectedCell, section: 0), animated: true, scrollPosition: .centeredHorizontally) + } + } + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let radioSwatchesModel = model as? RadioSwatchesModel else { return } @@ -43,6 +70,9 @@ open class RadioSwatches: View { collectionView.reloadData() } + //------------------------------------------------------ + // MARK: - Methods + //------------------------------------------------------ func registerCells() { collectionView.register(RadioSwatchItem.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") } @@ -70,6 +100,9 @@ open class RadioSwatches: View { } } +//------------------------------------------------------ +// MARK: - Delegate methods +//------------------------------------------------------ extension RadioSwatches: UICollectionViewDelegateFlowLayout { open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: cellSize, height: cellSize) @@ -89,3 +122,14 @@ extension RadioSwatches: UICollectionViewDataSource { return cell } } + +extension RadioSwatches: UICollectionViewDelegate { + public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let swatchItem = swatches?[indexPath.row] else { return } + swatchItem.selected = true + } + public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { + guard let swatchItem = swatches?[indexPath.row] else { return } + swatchItem.selected = false + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index d926ad5c..e5e0ce11 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -37,7 +37,7 @@ import Foundation } } -@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol { +@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol, FormFieldProtocol { public var backgroundColor: Color? public static var identifier: String = "radioSwatchItem" public var color: Color = Color(uiColor: .mvmBlue) @@ -45,13 +45,25 @@ import Foundation public var selected: Bool? = false public var enabled: Bool? = true public var strikethrough: Bool? = false + public var fieldKey: String? + public var fieldValue: String? + public var baseValue: AnyHashable? + public var groupName: String = FormValidator.defaultGroupName - public init(color: Color, text:String, selected: Bool, enabled: Bool, strikethrough: Bool) { + public init(color: Color, text:String, selected: Bool, enabled: Bool, strikethrough: Bool, fieldKey: String, fieldValue: String, groupName:String) { self.color = color self.text = text self.selected = selected + self.fieldValue = fieldValue self.enabled = enabled self.strikethrough = strikethrough + self.fieldKey = fieldKey + self.groupName = groupName + baseValue = selected + } + + public func formFieldValue() -> AnyHashable? { + return selected } private enum CodingKeys: String, CodingKey { @@ -62,6 +74,9 @@ import Foundation case selected case enabled case strikethrough + case fieldKey + case fieldValue + case groupName } required public init(from decoder: Decoder) throws { @@ -80,6 +95,12 @@ import Foundation if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { self.strikethrough = strikethrough } + baseValue = self.selected + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } } public func encode(to encoder: Encoder) throws { @@ -91,6 +112,9 @@ import Foundation try container.encodeIfPresent(selected, forKey: .selected) try container.encodeIfPresent(enabled, forKey: .enabled) try container.encodeIfPresent(strikethrough, forKey: .strikethrough) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(fieldValue, forKey: .fieldValue) + try container.encodeIfPresent(groupName, forKey: .groupName) } } From 8572b1c71840a059f666d9569b399266bbe669b7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 10 Apr 2020 16:03:01 -0400 Subject: [PATCH 018/136] current state --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ .../TextFields/BaseDropdownEntryField.swift | 8 +-- .../Atomic/Atoms/TextFields/EntryField.swift | 10 ++-- .../Atoms/TextFields/TextEntryField.swift | 57 ++++++++++++++----- .../Extensions/UIToolbar+Extension.swift | 36 ++++++++++++ 5 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index b96efb29..7ac8ba76 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -95,6 +95,7 @@ 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.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 */; }; 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; }; 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; }; @@ -504,6 +505,7 @@ 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = ""; }; 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = ""; }; 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = ""; }; + 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = ""; }; 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = ""; }; 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = ""; }; 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = ""; }; @@ -1083,6 +1085,7 @@ D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */, D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */, 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */, + 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */, ); path = Extensions; sourceTree = ""; @@ -2125,6 +2128,7 @@ BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */, D2B18B812360945C00A9AEDC /* View.swift in Sources */, C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, + 0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift index f7083df5..bf1dbfab 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift @@ -64,13 +64,7 @@ import UIKit super.setupFieldContainerContent(container) container.addSubview(dropDownCaretView) - - textFieldTrailingConstraint?.isActive = false - textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6) - textFieldTrailingConstraint?.isActive = true - - container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true - dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true + accessoryView = dropDownCaretView } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 658af357..2487d619 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -36,7 +36,7 @@ import UIKit label.setContentCompressionResistancePriority(.required, for: .vertical) return label }() - + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -193,7 +193,7 @@ import UIKit entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical) setupFieldContainerContent(entryFieldContainer) - titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4) + titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One) titleContainerDistance?.isActive = true entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) entryFieldContainerLeading?.isActive = true @@ -202,7 +202,7 @@ import UIKit addSubview(feedbackLabel) - feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: PaddingOne) + feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two) feedbackContainerDistance?.isActive = true feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) feedbackLabelLeading?.isActive = true @@ -240,9 +240,9 @@ import UIKit backgroundColor = .clear isAccessibilityElement = false - titleLabel.font = MFStyler.fontRegularMicro() + titleLabel.font = Styler.Font.RegularMicro.getFont() titleLabel.textColor = .mvmBlack - feedbackLabel.font = MFStyler.fontRegularMicro() + feedbackLabel.font = Styler.Font.RegularMicro.getFont() feedbackLabel.textColor = .mvmBlack entryFieldContainer.reset() } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index de0d1789..1b3ed015 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -28,7 +28,7 @@ import UIKit let textField = TextField() textField.isAccessibilityElement = true textField.setContentCompressionResistancePriority(.required, for: .vertical) - textField.font = MFStyler.fontRegularBodyLarge() + textField.font = Styler.Font.RegularBodyLarge.getFont() textField.textColor = .mvmBlack textField.smartQuotesType = .no textField.smartDashesType = .no @@ -36,6 +36,12 @@ import UIKit return textField }() + public var accessoryView: View? { + didSet { + accessoryView == nil ? removeAccessoryView() : constrainAccessoryView() + } + } + //-------------------------------------------------- // MARK: - Stored Properties //-------------------------------------------------- @@ -54,7 +60,7 @@ import UIKit public var textEntryFieldModel: TextEntryFieldModel? { return model as? TextEntryFieldModel } - + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- @@ -141,6 +147,26 @@ import UIKit //-------------------------------------------------- public var textFieldTrailingConstraint: NSLayoutConstraint? + public var accessoryViewTrailingConstraint: NSLayoutConstraint? + + public func constrainAccessoryView() { + + textFieldTrailingConstraint?.isActive = false + textFieldTrailingConstraint = accessoryView?.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) + textFieldTrailingConstraint?.isActive = true + + accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView!.trailingAnchor, constant: Padding.Four) + accessoryViewTrailingConstraint?.isActive = true + accessoryView?.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + } + + public func removeAccessoryView() { + + accessoryView?.removeFromSuperview() + + textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint?.isActive = true + } //-------------------------------------------------- // MARK: - Initializers @@ -169,17 +195,17 @@ import UIKit @objc open override func setupFieldContainerContent(_ container: UIView) { - textField.font = MFStyler.fontRegularBodyLarge() + textField.font = Styler.Font.RegularBodyLarge.getFont() container.addSubview(textField) NSLayoutConstraint.activate([ - textField.heightAnchor.constraint(equalToConstant: 24), - textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12), - textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16), - container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12) + textField.heightAnchor.constraint(equalToConstant: Padding.Five), + textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three), + textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Four), + 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.Four) textFieldTrailingConstraint?.isActive = true textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin) @@ -194,20 +220,20 @@ import UIKit @objc open override func updateView(_ size: CGFloat) { super.updateView(size) - textField.font = MFStyler.fontRegularBodyLarge() + textField.font = Styler.Font.RegularBodyLarge.getFont() layoutIfNeeded() } open override func 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)?) { observingTextFieldDelegate = delegate uiTextFieldDelegate = delegate @@ -240,11 +266,11 @@ import UIKit text = textField.text _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } - + @objc public func updateValidation(_ isValid: Bool) { let previousValidity = self.isValid self.isValid = isValid - + if previousValidity && !isValid { showError = true observingTextFieldDelegate?.isInvalid?(textfield: self) @@ -288,7 +314,7 @@ import UIKit super.set(with: model, delegateObject, additionalData) guard let model = model as? TextEntryFieldModel else { return } - + model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { if self?.isSelected ?? false { @@ -306,10 +332,13 @@ import UIKit switch model.type { case .password: textField.isSecureTextEntry = true + case .number: textField.keyboardType = .numberPad + case .email: textField.keyboardType = .emailAddress + default: break } diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift new file mode 100644 index 00000000..6686f164 --- /dev/null +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -0,0 +1,36 @@ +// +// UIToolbar+Extension.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 4/10/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +/* +public extension UIToolbar { + + class func makeEmptyToolbar() -> UIToolbar { + + let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44.0)) + toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth] + toolbar.barStyle = .default + toolbar.barTintColor = .mvmCoolGray3 + toolbar.isTranslucent = true + + return toolbar + } + + class func getToolbarWithDoneButton(delegate: ObservingTextFieldDelegate) -> UIToolbar { + + let toolbar = makeEmptyToolbar() + let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput)) + button.tintColor = .mvmBlack + toolbar.setItems([space, button], animated: false) + + return toolbar + } +} +*/ From 5a30f99d62f260f83237d2b5e9d48648e82c04e8 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Mon, 13 Apr 2020 10:22:30 +0530 Subject: [PATCH 019/136] Re-arranged folder structure. --- MVMCoreUI.xcodeproj/project.pbxproj | 14 +++----------- .../Atoms/{Selectors => }/RadioSwatchItem.swift | 0 .../Atoms/{Selectors => }/RadioSwatches.swift | 0 .../Atoms/{Selectors => }/RadioSwatchesModel.swift | 0 4 files changed, 3 insertions(+), 11 deletions(-) rename MVMCoreUI/Atomic/Atoms/{Selectors => }/RadioSwatchItem.swift (100%) rename MVMCoreUI/Atomic/Atoms/{Selectors => }/RadioSwatches.swift (100%) rename MVMCoreUI/Atomic/Atoms/{Selectors => }/RadioSwatchesModel.swift (100%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5bcd1a74..08fbd249 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -1069,16 +1069,6 @@ path = TwoColumn; sourceTree = ""; }; - AA56A26D243CAB0800303286 /* Selectors */ = { - isa = PBXGroup; - children = ( - AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, - AAB9C10724346F4B00151545 /* RadioSwatches.swift */, - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, - ); - path = Selectors; - sourceTree = ""; - }; D202AFE2242A5F1400E5BEDF /* Extensions */ = { isa = PBXGroup; children = ( @@ -1453,7 +1443,9 @@ D29DF10D21E67A70003B2FB9 /* Atoms */ = { isa = PBXGroup; children = ( - AA56A26D243CAB0800303286 /* Selectors */, + AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, + AAB9C10724346F4B00151545 /* RadioSwatches.swift */, + AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, D29DF22B21E6A0FA003B2FB9 /* TextFields */, D29DF17D21E69E26003B2FB9 /* Views */, D29DF16821E69E1F003B2FB9 /* Buttons */, diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift rename to MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/RadioSwatches.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift rename to MVMCoreUI/Atomic/Atoms/RadioSwatches.swift diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/RadioSwatchesModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift rename to MVMCoreUI/Atomic/Atoms/RadioSwatchesModel.swift From 163535398925b20ec54f2ccf7306ef64f9d1bf1e Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Mon, 13 Apr 2020 18:07:54 +0530 Subject: [PATCH 020/136] Code refactoring by using collection base classes. --- MVMCoreUI.xcodeproj/project.pbxproj | 10 +- MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift | 127 ------------- .../Atoms/Selectors/RadioSwatchItem.swift | 167 ++++++++++++++++++ .../RadioSwatchItemCollectionViewCell.swift | 24 +++ .../Atoms/{ => Selectors}/RadioSwatches.swift | 113 ++++++------ .../{ => Selectors}/RadioSwatchesModel.swift | 53 +++--- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + 7 files changed, 280 insertions(+), 215 deletions(-) delete mode 100644 MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift rename MVMCoreUI/Atomic/Atoms/{ => Selectors}/RadioSwatches.swift (54%) rename MVMCoreUI/Atomic/Atoms/{ => Selectors}/RadioSwatchesModel.swift (86%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 3e55a236..077b0ca2 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -190,6 +190,7 @@ AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; + AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; @@ -619,6 +620,7 @@ AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; + AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItemCollectionViewCell.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; @@ -1435,6 +1437,10 @@ 01004F2F22721C3800991ECC /* RadioButton.swift */, 31BE15CA23D8924C00452370 /* CheckboxModel.swift */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, + AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, + AAB9C10724346F4B00151545 /* RadioSwatches.swift */, + AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, + AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */, ); path = Selectors; sourceTree = ""; @@ -1515,9 +1521,6 @@ isa = PBXGroup; children = ( D264FAA8243FE17A00D98315 /* Selectors */, - AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, - AAB9C10724346F4B00151545 /* RadioSwatches.swift */, - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, D29DF22B21E6A0FA003B2FB9 /* TextFields */, D29DF17D21E69E26003B2FB9 /* Views */, D29DF16821E69E1F003B2FB9 /* Buttons */, @@ -2330,6 +2333,7 @@ 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */, D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */, + AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */, 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift deleted file mode 100644 index 17352ed7..00000000 --- a/MVMCoreUI/Atomic/Atoms/RadioSwatchItem.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// RadioSwatchItem.swift -// MVMCoreUI -// -// Created by Lekshmi S on 01/04/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import UIKit - -open class RadioSwatchItem: UICollectionViewCell, MoleculeViewProtocol { - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - public var bottomText = Label(frame: .zero) - let circleLayer = CAShapeLayer() - var cellView = MVMCoreUICommonViewsUtility.commonView() - var fillColor: Color = Color(uiColor: .mvmBlue) - - //------------------------------------------------------ - // MARK: - Property Observer - //------------------------------------------------------ - open override var isSelected: Bool { - didSet { - drawCircle() - isSelected ? drawOuterCircle() : removeOuterCircle() - isSelected ? (bottomText.isHidden = false) : (bottomText.isHidden = true) - } - } - - var isStrikeThrough: Bool = false { - didSet { - cellView.layer.sublayers?.filter({$0.name == "OutOfStock"}).forEach({$0.removeFromSuperlayer()}) - if isStrikeThrough { - drawStrikeThrough() - } - } - } - - //------------------------------------------------------ - // MARK: - Initialization - //------------------------------------------------------ - public override init(frame: CGRect) { - super.init(frame: .zero) - setupView() - } - - public required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setupView() - } - - //------------------------------------------------------ - // MARK: - Drawing - //------------------------------------------------------ - public func drawCircle() { - cellView.layer.sublayers?.filter({$0.name == "InnerCircle"}).forEach({$0.removeFromSuperlayer()}) - circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath - circleLayer.fillColor = fillColor.cgColor - circleLayer.strokeColor = isUserInteractionEnabled ? UIColor.mvmBlack.cgColor : UIColor.mvmCoolGray6.cgColor - circleLayer.name = "InnerCircle" - circleLayer.lineWidth = 1 - cellView.layer.addSublayer(circleLayer) - } - - public func drawStrikeThrough() { - let startPoint = CGPoint(x: 12, y: 30) - let endPoint = CGPoint(x: 42, y: 0) - let bezierPath = UIBezierPath() - bezierPath.move(to: startPoint) - bezierPath.addLine(to: endPoint) - let strikeThroughLayer = CAShapeLayer() - strikeThroughLayer.path = bezierPath.cgPath - strikeThroughLayer.name = "OutOfStock" - strikeThroughLayer.strokeColor = UIColor.mvmCoolGray6.cgColor - strikeThroughLayer.lineWidth = 1 - cellView.layer.addSublayer(strikeThroughLayer) - } - - public func drawOuterCircle() { - self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()}) - circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath - let outerCircleLayer = CAShapeLayer() - outerCircleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath - outerCircleLayer.name = "OuterCircle" - outerCircleLayer.strokeColor = UIColor.mvmBlack.cgColor - outerCircleLayer.fillColor = UIColor.clear.cgColor - outerCircleLayer.lineWidth = 1 - cellView.layer.addSublayer(outerCircleLayer) - } - - public func removeOuterCircle() { - circleLayer.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath - self.cellView.layer.sublayers?.filter({$0.name == "OuterCircle"}).forEach({$0.removeFromSuperlayer()}) - } - - //-------------------------------------------------- - // MARK: - Lifecycle - //-------------------------------------------------- - public func setupView() { - guard cellView.superview == nil else { - return - } - isAccessibilityElement = false - contentView.isAccessibilityElement = false - insetsLayoutMarginsFromSafeArea = false - contentView.insetsLayoutMarginsFromSafeArea = false - contentView.preservesSuperviewLayoutMargins = false - contentView.addSubview(cellView) - NSLayoutConstraint.constraintPinSubview(toSuperview: cellView) - cellView.addSubview(bottomText) - bottomText.textAlignment = .center - bottomText.font = MFFonts.mfFontTXRegular(11.0) - bottomText.topAnchor.constraint(equalTo: cellView.topAnchor, constant: 38).isActive = true - bottomText.leadingAnchor.constraint(equalTo: cellView.leadingAnchor).isActive = true - bottomText.trailingAnchor.constraint(equalTo: cellView.trailingAnchor).isActive = true - cellView.bottomAnchor.constraint(equalTo: bottomText.bottomAnchor).isActive = true - } - - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let collectionModel = model as? RadioSwatchItemModel else { return } - fillColor = collectionModel.color - isUserInteractionEnabled = collectionModel.enabled ?? true - isStrikeThrough = collectionModel.strikethrough ?? false - bottomText.text = collectionModel.text - } -} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift new file mode 100644 index 00000000..f6054ebb --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift @@ -0,0 +1,167 @@ +// +// RadioSwatchItem.swift +// MVMCoreUI +// +// Created by Lekshmi S on 01/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +import UIKit + +open class RadioSwatchItem: Control { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var bottomText = Label.createLabelRegularMicro(true) + public var isOutOfStock = false + public var fillColor: Color = Color(uiColor: .mvmBlue) + + private var circleLayer: CAShapeLayer? + private var selectedLayer: CALayer? + private var strikeLayer: CALayer? + private var maskLayer: CALayer? + + public var radioSwatchModel: RadioSwatchItemModel? { + return model as? RadioSwatchItemModel + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + open override func updateView(_ size: CGFloat) { + super.updateView(size) + bottomText.updateView(size) + layer.setNeedsDisplay() + } + + public override func setupView() { + super.setupView() + + addSubview(bottomText) + bottomText.textAlignment = .center + bottomText.topAnchor.constraint(equalTo: topAnchor, constant: 38).isActive = true + bottomText.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + bottomText.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true + bottomAnchor.constraint(equalTo: bottomText.bottomAnchor).isActive = true + addTarget(self, action: #selector(selectSwatch), for: .touchUpInside) + } + + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? RadioSwatchItemModel else { return } + fillColor = model.color + isSelected = model.selected ?? false + isEnabled = model.enabled ?? true + bottomText.text = model.text + isOutOfStock = model.strikethrough ?? false + } + + //------------------------------------------------------ + // MARK: - State Handling + //------------------------------------------------------ + + open override func draw(_ layer: CALayer, in ctx: CGContext) { + //Draw the swatch + circleLayer?.removeFromSuperlayer() + let circle = getCircle(color: UIColor.mvmBlack, thickness: 1) + layer.addSublayer(circle) + circleLayer = circle + + //Draw the strikethrough + strikeLayer?.removeFromSuperlayer() + if isOutOfStock { + let line = getStrikeThrough(color: UIColor.mvmCoolGray6, thickness: 1) + layer.addSublayer(line) + strikeLayer = line + } + + //Draw the selected layer + selectedLayer?.removeFromSuperlayer() + if isSelected { + let outerCircle = getSelectedLayer(color: UIColor.black, thickness: 1) + layer.addSublayer(outerCircle) + selectedLayer = outerCircle + bottomText.isHidden = false + } else { + circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath + bottomText.isHidden = true + } + + //Handle Mask + maskLayer?.removeFromSuperlayer() + if !isEnabled { + let mask = getMaskLayer() + layer.mask = mask + maskLayer = mask + } + } + + open override func layoutSubviews() { + super.layoutSubviews() + // Accounts for any size changes + layer.setNeedsDisplay() + } + + @objc open func selectSwatch() { + isSelected = true + radioSwatchModel?.selected = isSelected + layer.setNeedsDisplay() + } + + @objc open func deselectSwatch() { + isSelected = false + radioSwatchModel?.selected = isSelected + layer.setNeedsDisplay() + } + + func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer { + let circle = CAShapeLayer() + circle.name = "innercircle" + circle.fillColor = fillColor.cgColor + circle.opacity = 1.0 + circle.lineWidth = thickness + circle.strokeColor = isEnabled ? color.cgColor : UIColor.mvmCoolGray6.cgColor + + let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)) + circle.path = circlePath.cgPath + return circle + } + + func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer { + let strikeThrough = CAShapeLayer() + strikeThrough.name = "strikethrough" + strikeThrough.fillColor = nil + strikeThrough.opacity = 1.0 + strikeThrough.lineWidth = thickness + strikeThrough.strokeColor = color.cgColor + + let linePath = UIBezierPath() + linePath.move(to: CGPoint(x: 12, y: 30)) + linePath.addLine(to: CGPoint(x: 42, y: 0)) + strikeThrough.path = linePath.cgPath + return strikeThrough + } + + func getSelectedLayer(color: UIColor, thickness: CGFloat) -> CAShapeLayer { + circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath + let circle = CAShapeLayer() + circle.name = "outercircle" + circle.fillColor = UIColor.clear.cgColor + circle.opacity = 1.0 + circle.lineWidth = thickness + circle.strokeColor = color.cgColor + + let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)) + circle.path = circlePath.cgPath + return circle + } + + func getMaskLayer() -> CALayer { + let mask = CALayer() + mask.backgroundColor = UIColor.white.cgColor + mask.opacity = 0.3 + mask.frame = bounds + return mask + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift new file mode 100644 index 00000000..b274d28d --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift @@ -0,0 +1,24 @@ +// +// RadioSwatchItemCollectionViewCell.swift +// MVMCoreUI +// +// Created by Lekshmi S on 13/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +open class RadioSwatchItemCollectionViewCell: CollectionViewCell { + let radioSwatch = RadioSwatchItem() + + open override func setupView() { + super.setupView() + addMolecule(radioSwatch) + MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let model = model as? RadioSwatchItemModel else { return } + radioSwatch.set(with: model, delegateObject, additionalData) + self.isUserInteractionEnabled = model.enabled ?? true + } +} diff --git a/MVMCoreUI/Atomic/Atoms/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift similarity index 54% rename from MVMCoreUI/Atomic/Atoms/RadioSwatches.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index a27af6c8..d73c749a 100644 --- a/MVMCoreUI/Atomic/Atoms/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -6,97 +6,97 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -import UIKit +import Foundation open class RadioSwatches: View { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) + public var collectionView: CollectionView! var swatches: [RadioSwatchItemModel]? - - public var selectedSwatchItem: RadioSwatchItemModel? { - get{ - guard let selectedItem = collectionView.indexPathsForSelectedItems?.first else {return nil} - return swatches?[selectedItem.item] - } - } + private var size: CGFloat? + private var delegateObject: MVMCoreUIDelegateObject? //------------------------------------------------------ // MARK: - Constraints //------------------------------------------------------ public var collectionViewHeight: NSLayoutConstraint? - public let cellSize: Double = 54.0 - public let spacing: Double = 10 + private let cellSize: CGFloat = 54.0 + private let itemSpacing: CGFloat = 8.0 //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- + open override func layoutSubviews() { + super.layoutSubviews() + // Accounts for any collection size changes + DispatchQueue.main.async { + self.collectionView.collectionViewLayout.invalidateLayout() + } + } + open override func setupView() { super.setupView() - guard collectionView.superview == nil else { - return - } - collectionView.translatesAutoresizingMaskIntoConstraints = false - collectionView.dataSource = self - collectionView.delegate = self - collectionView.showsHorizontalScrollIndicator = false - collectionView.backgroundColor = .clear - collectionView.isAccessibilityElement = false + collectionView = createCollectionView() addSubview(collectionView) NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100) collectionViewHeight?.isActive = true } - public override func updateView(_ size: CGFloat) { - DispatchQueue.main.async { - self.collectionView.collectionViewLayout.invalidateLayout() - self.collectionView.reloadData() - guard let selectedCell = self.swatches?.firstIndex(where: {$0.selected == true}) else { - return - } - self.collectionView.selectItem(at: IndexPath(item: selectedCell, section: 0), animated: true, scrollPosition: .centeredHorizontally) - } + @objc override open func updateView(_ size: CGFloat) { + super.updateView(size) + self.size = size + collectionView.updateView(size) } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) + self.delegateObject = delegateObject + guard let radioSwatchesModel = model as? RadioSwatchesModel else { return } - collectionView.layer.borderColor = backgroundColor?.cgColor + swatches = radioSwatchesModel.swatches + FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate) registerCells() - setupLayout(with: radioSwatchesModel) - prepareMolecules(with: radioSwatchesModel) + setHeight() collectionView.reloadData() } //------------------------------------------------------ // MARK: - Methods //------------------------------------------------------ - func registerCells() { - collectionView.register(RadioSwatchItem.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") + open func registerCells() { + collectionView.register(RadioSwatchItemCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") } - func setupLayout(with radioSwatchesModel: RadioSwatchesModel?) { + /// Creates the collection view. + open func createCollectionView() -> CollectionView { + let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) + collection.dataSource = self + collection.delegate = self + return collection + } + + /// Creates the layout for the collection. + open func createCollectionViewLayout() -> UICollectionViewLayout { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical - layout.minimumLineSpacing = CGFloat(spacing) - layout.minimumInteritemSpacing = CGFloat(spacing) - collectionView.collectionViewLayout = layout + layout.minimumLineSpacing = itemSpacing + layout.minimumInteritemSpacing = itemSpacing + return layout } - func prepareMolecules(with radioSwatchesModel: RadioSwatchesModel?) { - guard let newSwatches = radioSwatchesModel?.swatches else { - swatches = nil + open func setHeight() { + guard let swatches = swatches, swatches.count > 0 else { + collectionViewHeight?.constant = 0 return } - swatches = newSwatches + // Calculate the height let collectionViewWidth = UIScreen.main.bounds.width - (2 * MFStyler.defaultHorizontalPaddingForApplicationWidth()) - let swatchesInRow = Double(floor(Double(collectionViewWidth/60.0))) - let numberOfRows = floor(Double(swatches?.count ?? 1)/swatchesInRow) + 1.0 - let height = (numberOfRows * cellSize) + (spacing * (numberOfRows-1)) + let swatchesInRow = floor(CGFloat(collectionViewWidth/(cellSize + itemSpacing))) + let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow) + let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1)) collectionViewHeight?.constant = CGFloat(height) - collectionViewHeight?.isActive = true } } @@ -115,21 +115,28 @@ extension RadioSwatches: UICollectionViewDataSource { } open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItem else { - return UICollectionViewCell() + guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItemCollectionViewCell else { + fatalError() } - cell.set(with: molecule, nil, nil) + cell.radioSwatch.isUserInteractionEnabled = false + cell.set(with: molecule, delegateObject, nil) + cell.updateView(size ?? collectionView.bounds.width) + if molecule.selected ?? false { + collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically) + } + cell.layoutIfNeeded() return cell } } extension RadioSwatches: UICollectionViewDelegate { public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let swatchItem = swatches?[indexPath.row] else { return } - swatchItem.selected = true + guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } + cell.radioSwatch.selectSwatch() + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { - guard let swatchItem = swatches?[indexPath.row] else { return } - swatchItem.selected = false + guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } + cell.radioSwatch.deselectSwatch() } } diff --git a/MVMCoreUI/Atomic/Atoms/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift similarity index 86% rename from MVMCoreUI/Atomic/Atoms/RadioSwatchesModel.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index e5e0ce11..965b72f6 100644 --- a/MVMCoreUI/Atomic/Atoms/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -8,25 +8,39 @@ import Foundation -@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol { +@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol { public var backgroundColor: Color? public static var identifier: String = "radioSwatches" public var swatches: [RadioSwatchItemModel] + public var fieldKey: String? + public var groupName: String = FormValidator.defaultGroupName + public var baseValue: AnyHashable? - public init(swatches: [RadioSwatchItemModel]) { - self.swatches = swatches + /// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch. + public func formFieldValue() -> AnyHashable? { + let selectedSwatch = swatches.first { (swatch) -> Bool in + return (swatch.selected ?? false) + } + return selectedSwatch?.fieldValue ?? selectedSwatch?.text } private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor case swatches + case fieldKey + case groupName } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches) self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches) + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } + baseValue = formFieldValue() } public func encode(to encoder: Encoder) throws { @@ -34,10 +48,12 @@ import Foundation try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(swatches, forKey: .swatches) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(groupName, forKey: .groupName) } } -@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol, FormFieldProtocol { +@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "radioSwatchItem" public var color: Color = Color(uiColor: .mvmBlue) @@ -47,24 +63,6 @@ import Foundation public var strikethrough: Bool? = false public var fieldKey: String? public var fieldValue: String? - public var baseValue: AnyHashable? - public var groupName: String = FormValidator.defaultGroupName - - public init(color: Color, text:String, selected: Bool, enabled: Bool, strikethrough: Bool, fieldKey: String, fieldValue: String, groupName:String) { - self.color = color - self.text = text - self.selected = selected - self.fieldValue = fieldValue - self.enabled = enabled - self.strikethrough = strikethrough - self.fieldKey = fieldKey - self.groupName = groupName - baseValue = selected - } - - public func formFieldValue() -> AnyHashable? { - return selected - } private enum CodingKeys: String, CodingKey { case moleculeName @@ -74,9 +72,7 @@ import Foundation case selected case enabled case strikethrough - case fieldKey case fieldValue - case groupName } required public init(from decoder: Decoder) throws { @@ -95,12 +91,7 @@ import Foundation if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { self.strikethrough = strikethrough } - baseValue = self.selected - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) - if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName - } } public func encode(to encoder: Encoder) throws { @@ -112,9 +103,7 @@ import Foundation try container.encodeIfPresent(selected, forKey: .selected) try container.encodeIfPresent(enabled, forKey: .enabled) try container.encodeIfPresent(strikethrough, forKey: .strikethrough) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) - try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index ab0d5b43..1b050aca 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -70,6 +70,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self) MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self) // Other Atoms MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self) From 98e4f3d6211d372a9602a2ceb34c7954bd6b8f2a Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 13 Apr 2020 14:25:52 -0400 Subject: [PATCH 021/136] latest state of updates --- .../TextFields/DateDropdownEntryField.swift | 4 +- .../DateDropdownEntryFieldModel.swift | 5 +- .../Atoms/TextFields/DigitEntryField.swift | 9 -- .../TextFields/DigitEntryFieldModel.swift | 10 ++- .../Atomic/Atoms/TextFields/EntryField.swift | 14 ++- .../Atoms/TextFields/EntryFieldModel.swift | 85 ++++++++++--------- .../ItemDropdownEntryFieldModel.swift | 10 ++- .../Atoms/TextFields/MdnEntryField.swift | 10 +-- .../Atoms/TextFields/TextEntryField.swift | 44 +++------- .../TextFields/TextEntryFieldModel.swift | 7 +- .../Views/EntryFieldContainer.swift | 4 +- 11 files changed, 92 insertions(+), 110 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift index a7a483fc..50cca777 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift @@ -32,9 +32,7 @@ import UIKit }() public var dateFormat: String = "MMM d, y" { - didSet { - dateFormatter.dateFormat = dateFormat - } + didSet { dateFormatter.dateFormat = dateFormat } } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift index cdafc9e9..726eab1f 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -33,7 +33,10 @@ required public init(from decoder: Decoder) throws { try super.init(from: decoder) 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 { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 38adee03..9d2c02cb 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -246,15 +246,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) { var selectPreviousField = false diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift index 0291066c..423c1d7d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift @@ -36,8 +36,14 @@ required public init(from decoder: Decoder) throws { try super.init(from: decoder) 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 + } + + if let secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) { + self.secureEntry = secureEntry + } } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 2487d619..8eb94f4e 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -20,7 +20,7 @@ import UIKit public private(set) var titleLabel: Label = { let label = Label() - label.font = MFStyler.fontRegularMicro() + label.font = Styler.Font.RegularMicro.getFont() label.textColor = .mvmBlack label.setContentCompressionResistancePriority(.required, for: .vertical) return label @@ -31,7 +31,7 @@ import UIKit /// Provides contextual information on the TextField. public private(set) var feedbackLabel: Label = { let label = Label() - label.font = MFStyler.fontRegularMicro() + label.font = Styler.Font.RegularMicro.getFont() label.textColor = .mvmBlack label.setContentCompressionResistancePriority(.required, for: .vertical) return label @@ -174,8 +174,6 @@ import UIKit @objc final public override func setupView() { super.setupView() - guard subviews.isEmpty else { return } - isAccessibilityElement = false setContentCompressionResistancePriority(.required, for: .vertical) accessibilityElements = [titleLabel, feedbackLabel] @@ -258,13 +256,13 @@ import UIKit title = model.title feedback = model.feedback errorMessage = model.errorMessage - isEnabled = model.isEnabled + isEnabled = model.enabled - if let isLocked = model.isLocked { + if let isLocked = model.locked { self.isLocked = isLocked - } else if let isSelected = model.isSelected{ - self.isSelected = isSelected + } else if let selected = model.selected { + self.isSelected = selected } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 729b3516..efd47e1d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -9,8 +9,8 @@ import Foundation -@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol { - +@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -20,31 +20,24 @@ import Foundation } public var backgroundColor: Color? - public var title: String? + public var title: String = "" public var feedback: String? public var errorMessage: String = "" - public var isEnabled: Bool = true - public var isLocked: Bool? - public var isSelected: Bool? + public var enabled: Bool = true + public var locked: Bool? + public var selected: Bool? public var text: String? - public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? - + public var isValid: Bool? { - didSet { - updateUI?() - } + didSet { updateUI?() } } /// 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 //-------------------------------------------------- @@ -52,23 +45,29 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor - case title = "label" - case isEnabled + case title + case enabled case feedback - case errorMessage = "errorMsg" - case isLocked - case isSelected - case isValid - case isRequired = "required" + case errorMessage + case locked + case selected case text case fieldKey case groupName } - + + //-------------------------------------------------- + // MARK: - Validation Methods + //-------------------------------------------------- + public func formFieldValue() -> AnyHashable? { return text } + public func setValidity(_ valid: Bool, rule: RulesProtocol) { + self.isValid = valid + } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -81,20 +80,26 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - title = try typeContainer.decodeIfPresent(String.self, forKey: .title) - feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) - errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? "" - isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true - isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked) - isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) - isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid) - text = try typeContainer.decodeIfPresent(String.self, forKey: .text) + if let title = try typeContainer.decodeIfPresent(String.self, forKey: .title) { + self.title = title + } + + feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) + + if let errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) { + self.errorMessage = errorMessage + } + + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + + locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked) + selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) + text = try typeContainer.decodeIfPresent(String.self, forKey: .text) baseValue = text fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName - } } public func encode(to encoder: Encoder) throws { @@ -103,13 +108,11 @@ import Foundation try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) - try container.encode(errorMessage, forKey: .errorMessage) - try container.encode(isEnabled, forKey: .isEnabled) - try container.encode(isLocked, forKey: .isLocked) - try container.encode(isSelected, forKey: .isSelected) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(isValid, forKey: .isValid) try container.encodeIfPresent(text, forKey: .text) try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encodeIfPresent(locked, forKey: .locked) + try container.encodeIfPresent(selected, forKey: .selected) + try container.encode(errorMessage, forKey: .errorMessage) + try container.encode(enabled, forKey: .enabled) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index 56612b7b..2f2003c0 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -35,8 +35,14 @@ required public init(from decoder: Decoder) throws { try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - options = try typeContainer.decode([String].self, forKey: .options) - selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0 + + if let options = try typeContainer.decodeIfPresent([String].self, forKey: .options) { + self.options = options + } + + if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { + self.selectedIndex = selectedIndex + } } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index 77b5a4a4..4f9f5d8c 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -107,18 +107,18 @@ import MVMCore isValid = true return true } - + let isValid = hasValidMDN() - + if isValid { showError = false - + } else { errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") showError = true UIAccessibility.post(notification: .layoutChanged, argument: textField) } - + return isValid } @@ -196,7 +196,7 @@ import MVMCore } @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - + return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 1b3ed015..9d78416d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -37,9 +37,7 @@ import UIKit }() public var accessoryView: View? { - didSet { - accessoryView == nil ? removeAccessoryView() : constrainAccessoryView() - } + didSet { accessoryView == nil ? removeAccessoryView() : constrainAccessoryView() } } //-------------------------------------------------- @@ -108,12 +106,6 @@ import UIKit set { textField.placeholder = newValue } } - //-------------------------------------------------- - // MARK: - Property Observers - //-------------------------------------------------- - - public var validationBlock: ((_ value: String?) -> Bool)? - //-------------------------------------------------- // MARK: - Delegate Properties //-------------------------------------------------- @@ -155,9 +147,11 @@ import UIKit textFieldTrailingConstraint = accessoryView?.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) textFieldTrailingConstraint?.isActive = true - accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView!.trailingAnchor, constant: Padding.Four) - accessoryViewTrailingConstraint?.isActive = true - accessoryView?.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + if let accessoryView = accessoryView { + accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four) + accessoryViewTrailingConstraint?.isActive = true + accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + } } public func removeAccessoryView() { @@ -242,15 +236,7 @@ import UIKit //-------------------------------------------------- // MARK: - Observing for Change (TextFieldDelegate) //-------------------------------------------------- - - public func defaultValidationBlock() { - - validationBlock = { enteredValue in - guard let enteredValue = enteredValue else { return false } - return enteredValue.count > 0 - } - } - + @discardableResult @objc override open func resignFirstResponder() -> Bool { if validateWhenDoneEditing { @@ -317,11 +303,14 @@ import UIKit model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - if self?.isSelected ?? false { - self?.updateValidation(model.isValid ?? true) + guard let self = self else { return } + + if self.isSelected { + self.updateValidation(model.isValid ?? true) } }) } + self.delegateObject = delegateObject FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) textColor.enabled = model.enabledTextColor?.uiColor @@ -343,15 +332,6 @@ import UIKit break } - if let regex = model.regex, !regex.isEmpty { - validationBlock = { enteredValue in - guard let value = enteredValue else { return false } - return MVMCoreUIUtility.validate(value, withRegularExpression: regex) - } - } else { - defaultValidationBlock() - } - uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index c35d812e..99a5dba4 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -8,6 +8,9 @@ @objcMembers public class TextEntryFieldModel: EntryFieldModel { + //-------------------------------------------------- + // MARK: - Types + //-------------------------------------------------- public enum EntryType: String, Codable { case password @@ -27,7 +30,6 @@ public var enabledTextColor: Color? public var disabledTextColor: Color? public var type: EntryType? - public var regex: String? //-------------------------------------------------- // MARK: - Keys @@ -40,7 +42,6 @@ case enabledTextColor case disabledTextColor case type - case regex } //-------------------------------------------------- @@ -55,7 +56,6 @@ enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type) - regex = try typeContainer.decodeIfPresent(String.self, forKey: .regex) } public override func encode(to encoder: Encoder) throws { @@ -67,6 +67,5 @@ try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(type, forKey: .type) - try container.encodeIfPresent(regex, forKey: .regex) } } diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift index 3a8fac64..9ccd1d25 100644 --- a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -25,9 +25,7 @@ import UIKit /// Total control over the drawn top, bottom, left and right borders. public var disableAllBorders = false { - didSet { - bottomBar?.isHidden = disableAllBorders - } + didSet { bottomBar?.isHidden = disableAllBorders } } private(set) var fieldState: FieldState = .original { From 1f8cf7c4d03fa439f48e4dfac496bcd162849bbf Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 13 Apr 2020 16:28:02 -0400 Subject: [PATCH 022/136] EntryField updates --- .../TextFields/BaseDropdownEntryField.swift | 8 ++++- .../Atoms/TextFields/DigitEntryField.swift | 10 ++++++ .../Atomic/Atoms/TextFields/EntryField.swift | 16 ++++----- .../Atoms/TextFields/EntryFieldModel.swift | 4 ++- .../Atoms/TextFields/MdnEntryField.swift | 24 +++++++++++++- .../Atoms/TextFields/TextEntryField.swift | 31 +++--------------- .../alert_standard.imageset/Contents.json | 23 +++++++++++++ .../alert_standard @1x.png | Bin 0 -> 279 bytes .../alert_standard @2x.png | Bin 0 -> 525 bytes .../alert_standard @3x.png | Bin 0 -> 771 bytes 10 files changed, 76 insertions(+), 40 deletions(-) create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/Contents.json create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @1x.png create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @2x.png create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @3x.png diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift index bf1dbfab..f7083df5 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift @@ -64,7 +64,13 @@ import UIKit super.setupFieldContainerContent(container) container.addSubview(dropDownCaretView) - accessoryView = dropDownCaretView + + textFieldTrailingConstraint?.isActive = false + textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6) + textFieldTrailingConstraint?.isActive = true + + container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true + dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 9d2c02cb..25900f27 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -76,6 +76,15 @@ import UIKit public var digitBoxes: [DigitBox] = [] private var selectedDigitBox: DigitBox? + 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: - Computed Properties //-------------------------------------------------- @@ -205,6 +214,7 @@ import UIKit isAccessibilityElement = false entryFieldContainer.disableAllBorders = true + usesAccessoryView = false } @objc private func createDigitField() -> DigitBox { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 8eb94f4e..23225a57 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -48,14 +48,6 @@ import UIKit //-------------------------------------------------- public var isValid: Bool = false - public var errorMessage: String? - public var standardMessage: String? { - didSet { - if !showError { - feedback = standardMessage - } - } - } //-------------------------------------------------- // MARK: - Computed Properties @@ -75,7 +67,7 @@ import UIKit public var showError: Bool { get { return entryFieldContainer.showError } set (error) { - self.feedback = error ? self.errorMessage : self.standardMessage + self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.informativeMessage self.entryFieldContainer.showError = error } } @@ -121,6 +113,10 @@ import UIKit } } + public var entryFieldModel: EntryFieldModel? { + return model as? EntryFieldModel + } + //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- @@ -242,6 +238,7 @@ import UIKit titleLabel.textColor = .mvmBlack feedbackLabel.font = Styler.Font.RegularMicro.getFont() feedbackLabel.textColor = .mvmBlack + feedbackLabel.text = nil entryFieldContainer.reset() } @@ -255,7 +252,6 @@ import UIKit title = model.title feedback = model.feedback - errorMessage = model.errorMessage isEnabled = model.enabled if let isLocked = model.locked { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index efd47e1d..1f0e3d78 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -22,7 +22,8 @@ import Foundation public var backgroundColor: Color? public var title: String = "" public var feedback: String? - public var errorMessage: String = "" + public var errorMessage: String? + public var informativeMessage: String? public var enabled: Bool = true public var locked: Bool? public var selected: Bool? @@ -86,6 +87,7 @@ import Foundation } feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) + informativeMessage = feedback if let errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) { self.errorMessage = errorMessage diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index 4f9f5d8c..dfca1b76 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -86,6 +86,28 @@ import MVMCore textField.inputAccessoryView = toolbar } + public func constrainAccessoryView() { + + guard let accessoryView = accessoryView else { return } + + entryFieldContainer.addSubview(accessoryView) + + textFieldTrailingConstraint?.isActive = false + textFieldTrailingConstraint = accessoryView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) + textFieldTrailingConstraint?.isActive = true + + accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four) + accessoryViewTrailingConstraint?.isActive = true + accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + } + + public func unconstrainAccessoryView() { + + textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint?.isActive = true + } + + //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- @@ -114,7 +136,7 @@ import MVMCore showError = false } 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 UIAccessibility.post(notification: .layoutChanged, argument: textField) } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 9d78416d..c013a246 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -35,11 +35,7 @@ import UIKit textField.smartInsertDeleteType = .no return textField }() - - public var accessoryView: View? { - didSet { accessoryView == nil ? removeAccessoryView() : constrainAccessoryView() } - } - + //-------------------------------------------------- // MARK: - Stored Properties //-------------------------------------------------- @@ -52,6 +48,8 @@ import UIKit /// Validate on each entry in the textField. Default: true public var validateEachCharacter: Bool = true + var usesAccessoryView: Bool = true + /// Validate when user resigns editing. Default: true public var validateWhenDoneEditing: Bool = true @@ -82,7 +80,7 @@ import UIKit set (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 { textField.accessibilityValue = nil } @@ -141,27 +139,6 @@ import UIKit public var textFieldTrailingConstraint: NSLayoutConstraint? public var accessoryViewTrailingConstraint: NSLayoutConstraint? - public func constrainAccessoryView() { - - textFieldTrailingConstraint?.isActive = false - textFieldTrailingConstraint = accessoryView?.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) - textFieldTrailingConstraint?.isActive = true - - if let accessoryView = accessoryView { - accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four) - accessoryViewTrailingConstraint?.isActive = true - accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true - } - } - - public func removeAccessoryView() { - - accessoryView?.removeFromSuperview() - - textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) - textFieldTrailingConstraint?.isActive = true - } - //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/Contents.json b/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/Contents.json new file mode 100644 index 00000000..af2434ac --- /dev/null +++ b/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/Contents.json @@ -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" + } +} \ No newline at end of file diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @1x.png b/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @1x.png new file mode 100644 index 0000000000000000000000000000000000000000..f5fbe367cf64f711290e7b32a70ec1a601d97264 GIT binary patch literal 279 zcmV+y0qFjTP)Px#(Md!>R5%f(mB9_dFbqX2!InL6<;Da|!I>?X09Igy9=Zbu{Hj<=Lu@DEOJB9( zpQlE#+G&b4OJqr={!3@s{SjZ2saYG6!cN(4>LF+irrd6*2kVAfu$PcPsTTt!uY=-G3584g$pu?~d%FyDWZ=u5U d$(%O-0>1XbOgi*8)%^ef002ovPDHLkV1iTmbsPWy literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @2x.png b/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d40e714930cf2c5fd9e0c850db453c7bac83e141 GIT binary patch literal 525 zcmV+o0`mQdP)Px$$4Nv%R9Fek+09MFKn#ZA2<~*jl^*zOfHOxrfEJ((&Tya^ieNe;+B(eNXdYS#wm^oZIWwMv9xU{teq>cs#%_p%nZ zvYCk!+gL#AOkknc?jX~pv+aBFx~z-Ev9i`FKD6C`w@Dq1Kc~3XMFNN;mpOX97YU7P z+-B(W+9tI(N?h;nm>S3KIwZdz%O*z0Az3{~KZt5rsAh*WAT; P00000NkvXXu0mjfMds}x literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @3x.png b/MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @3x.png new file mode 100644 index 0000000000000000000000000000000000000000..00589541efe77d734e8d84564871b848afbed248 GIT binary patch literal 771 zcmV+e1N{7nP)Px%y-7qtRA>d=+c8fRK@K*a}^5-I1zeRH2 zTE#9jpONE4avzUbi`awW7jg<~<2;7Pb{z!#MjDFSYviXzviAGBMiZMpv)?iH3~9ld zW8I^tu#ZjZwjApkJqK&$@=Fl~;&7f;ySB@^l zzJOp%l4CcC>Tga;u|$=C`Tf<<3akQL1+BuWz@ca*RtXM4tFdaZ6di$$087wO*eGxj zIugr;Jx7j7a!e7kPg&7eqIQrem}9EAG5QHQrdJnvorx1D;{hg1!5mY@6q?4raR*;N zBK<-luxxfW>BF8JQ%4R>Bdx<5WDP8PF@7MeAM2>dp=lkCk+uL{828tWxnCVun9%yM zjtpA-#r_jE`+~Fu@Qy%qoTGvDV;vndS--Ehqq}A1|K`Sg?S|t@f-l|l4^c<|N_(WQ z-7;h)Esxx6mjs`=fm^7Lkm}QsYcY7Ful+HKng&{Yobo}<(-Ql=LfYRH>xjs`LjOB0 zu^~^&xjTIk&-6?5GB9g(tqWCi&i)&D_ed)?bNMfy1zBv;rKC zRiaD5)vzjb3Aj2|g|>O-Y*&W0MJiv&Y|g3e%CWYv8t7)QHPFprBhk%bBhbxbmFRA; z3Uqha5_GrNWzgMY4ZV*dca6+n_h#Mof5RKrw)-ej^fkuT@AD Date: Mon, 13 Apr 2020 16:42:39 -0400 Subject: [PATCH 023/136] revising error view to only MDN --- .../TextFields/BaseDropdownEntryField.swift | 2 +- .../Atoms/TextFields/MdnEntryField.swift | 29 ++++++++++++++----- .../Atoms/TextFields/TextEntryField.swift | 1 - 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift index f7083df5..ee697a3e 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/BaseDropdownEntryField.swift @@ -69,7 +69,7 @@ import UIKit textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6) 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 } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index dfca1b76..c973071d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -22,6 +22,8 @@ import MVMCore public var isNationalMDN = true public var shouldValidateMDN = false + public var accessoryViewTrailingConstraint: NSLayoutConstraint? + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -38,6 +40,15 @@ import MVMCore } } + 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: - Computed Properties //-------------------------------------------------- @@ -84,21 +95,26 @@ import MVMCore let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:))) toolbar.items = [contacts, space, dismissButton] textField.inputAccessoryView = toolbar + +// textFieldTrailingConstraint?.isActive = false +// textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) +// textFieldTrailingConstraint?.isActive = true +// +// container.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four).isActive = true +// errorImage.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true } public func constrainAccessoryView() { - guard let accessoryView = accessoryView else { return } - - entryFieldContainer.addSubview(accessoryView) + entryFieldContainer.addSubview(errorImage) textFieldTrailingConstraint?.isActive = false - textFieldTrailingConstraint = accessoryView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) + textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) textFieldTrailingConstraint?.isActive = true - accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four) + accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four) accessoryViewTrailingConstraint?.isActive = true - accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true } public func unconstrainAccessoryView() { @@ -107,7 +123,6 @@ import MVMCore textFieldTrailingConstraint?.isActive = true } - //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index c013a246..1c5563aa 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -137,7 +137,6 @@ import UIKit //-------------------------------------------------- public var textFieldTrailingConstraint: NSLayoutConstraint? - public var accessoryViewTrailingConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Initializers From cc5eb5c58e79d1a2a911026bb455c7a859bd0139 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 13 Apr 2020 16:44:39 -0400 Subject: [PATCH 024/136] puling over code to be worked on later --- .../Atoms/TextFields/MdnEntryField.swift | 37 ---------------- .../Atoms/TextFields/TextEntryField.swift | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index c973071d..71bc0539 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -22,8 +22,6 @@ import MVMCore public var isNationalMDN = true public var shouldValidateMDN = false - public var accessoryViewTrailingConstraint: NSLayoutConstraint? - //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -40,15 +38,6 @@ import MVMCore } } - 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: - Computed Properties //-------------------------------------------------- @@ -95,32 +84,6 @@ import MVMCore let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:))) toolbar.items = [contacts, space, dismissButton] textField.inputAccessoryView = toolbar - -// textFieldTrailingConstraint?.isActive = false -// textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) -// textFieldTrailingConstraint?.isActive = true -// -// container.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four).isActive = true -// errorImage.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true - } - - public func constrainAccessoryView() { - - entryFieldContainer.addSubview(errorImage) - - textFieldTrailingConstraint?.isActive = false - textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) - textFieldTrailingConstraint?.isActive = true - - accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four) - accessoryViewTrailingConstraint?.isActive = true - errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true - } - - public func unconstrainAccessoryView() { - - textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) - textFieldTrailingConstraint?.isActive = true } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 1c5563aa..98c03238 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -337,3 +337,46 @@ extension TextEntryField { textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")" } } + +// FOR isSecureEntry state +/* + + public var accessoryViewTrailingConstraint: NSLayoutConstraint? + + + // textFieldTrailingConstraint?.isActive = false + // textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) + // textFieldTrailingConstraint?.isActive = true + // + // container.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four).isActive = true + // errorImage.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true + + + 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 + }() + + public func constrainAccessoryView() { + + entryFieldContainer.addSubview(errorImage) + + textFieldTrailingConstraint?.isActive = false + textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) + textFieldTrailingConstraint?.isActive = true + + accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four) + accessoryViewTrailingConstraint?.isActive = true + errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + } + + public func unconstrainAccessoryView() { + + textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint?.isActive = true + } + */ From 949cd3292fb61f3d5421b94b72302ad519d6120c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 13 Apr 2020 17:07:28 -0400 Subject: [PATCH 025/136] resolving state of error image --- .../Atoms/TextFields/DigitEntryField.swift | 10 -- .../Atoms/TextFields/TextEntryField.swift | 102 ++++++++++-------- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 25900f27..9d2c02cb 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -76,15 +76,6 @@ import UIKit public var digitBoxes: [DigitBox] = [] private var selectedDigitBox: DigitBox? - 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: - Computed Properties //-------------------------------------------------- @@ -214,7 +205,6 @@ import UIKit isAccessibilityElement = false entryFieldContainer.disableAllBorders = true - usesAccessoryView = false } @objc private func createDigitField() -> DigitBox { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 98c03238..b267cd32 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -35,7 +35,22 @@ import UIKit textField.smartInsertDeleteType = .no return textField }() - + + private var standardAccessoryView: UIView? + + public var accessoryView: UIView? { + didSet { accessoryView == nil ? unconstrainAccessoryView() : constrainAccessoryView() } + } + + 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 //-------------------------------------------------- @@ -85,6 +100,17 @@ import UIKit textField.accessibilityValue = nil } + if textField.isSecureTextEntry { + if !error { + accessoryView?.removeFromSuperview() + accessoryView = nil + accessoryView = standardAccessoryView + } else { + standardAccessoryView = accessoryView + accessoryView = errorImage + } + } + super.showError = error } } @@ -137,6 +163,28 @@ import UIKit //-------------------------------------------------- public var textFieldTrailingConstraint: NSLayoutConstraint? + public var accessoryViewTrailingConstraint: NSLayoutConstraint? + + public func constrainAccessoryView() { + + guard let accessoryView = accessoryView else { return } + + entryFieldContainer.addSubview(accessoryView) + + textFieldTrailingConstraint?.isActive = false + textFieldTrailingConstraint = accessoryView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) + textFieldTrailingConstraint?.isActive = true + + accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four) + accessoryViewTrailingConstraint?.isActive = true + accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + } + + public func unconstrainAccessoryView() { + + textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint?.isActive = true + } //-------------------------------------------------- // MARK: - Initializers @@ -185,6 +233,15 @@ import UIKit entryFieldContainer.addGestureRecognizer(tap) accessibilityElements = [titleLabel, textField, feedbackLabel] + + // TODO: Remove these two lines. + let tapErr = UITapGestureRecognizer(target: self, action: #selector(tapForError)) + titleLabel.addGestureRecognizer(tapErr) + } + + // TODO: Remove this func + @objc func tapForError() { + showError.toggle() } @objc open override func updateView(_ size: CGFloat) { @@ -337,46 +394,3 @@ extension TextEntryField { textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")" } } - -// FOR isSecureEntry state -/* - - public var accessoryViewTrailingConstraint: NSLayoutConstraint? - - - // textFieldTrailingConstraint?.isActive = false - // textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) - // textFieldTrailingConstraint?.isActive = true - // - // container.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four).isActive = true - // errorImage.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true - - - 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 - }() - - public func constrainAccessoryView() { - - entryFieldContainer.addSubview(errorImage) - - textFieldTrailingConstraint?.isActive = false - textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) - textFieldTrailingConstraint?.isActive = true - - accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four) - accessoryViewTrailingConstraint?.isActive = true - errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true - } - - public func unconstrainAccessoryView() { - - textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) - textFieldTrailingConstraint?.isActive = true - } - */ From 5f125524be93872fb4bdd543a7093230547b40dd Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Tue, 14 Apr 2020 08:47:47 +0530 Subject: [PATCH 026/136] Initial commit --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ .../Atomic/Atoms/Selectors/RadioBox.swift | 2 + MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 2 + ...ListRightVariablePriceChangeBodyText.swift | 55 +++++++++++++++++++ ...ightVariablePriceChangeBodyTextModel.swift | 52 ++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 294f6188..778d8ab8 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -198,6 +198,8 @@ BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; }; BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */; }; BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */; }; + BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */; }; + BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */; }; BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; }; BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; }; BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; }; @@ -624,6 +626,8 @@ BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = ""; }; BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinks.swift; sourceTree = ""; }; BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinksModel.swift; sourceTree = ""; }; + BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyText.swift; sourceTree = ""; }; + BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyTextModel.swift; sourceTree = ""; }; BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = ""; }; BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = ""; }; BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = ""; }; @@ -1085,6 +1089,8 @@ AA4FC2A323F4F69600E251DB /* RightVariable */ = { isa = PBXGroup; children = ( + BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */, + BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */, BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */, BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */, BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */, @@ -2159,6 +2165,7 @@ 525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */, D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, + BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */, D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, @@ -2217,6 +2224,7 @@ D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, 0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */, + BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */, 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift index da762dbb..1c8527e8 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBox.swift @@ -98,6 +98,7 @@ open class RadioBox: Control { if !isEnabled { let mask = getMaskLayer() layer.mask = mask + maskLayer = mask } } @@ -108,6 +109,7 @@ open class RadioBox: Control { } @objc open func selectBox() { + isSelected = true radioBoxModel?.selected = isSelected layer.setNeedsDisplay() diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index ab0d5b43..c59bf1c7 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -138,6 +138,8 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift new file mode 100644 index 00000000..7b4be31f --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -0,0 +1,55 @@ +// +// ListRightVariablePriceChangeBodyText.swift +// MVMCoreUI +// +// Created by Dhamodaram Nandi on 13/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers open class ListRightVariablePriceChangeBodyText: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + public var stack: Stack + public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) + public let rightLabel = Label.commonLabelB2(true) + public let arrow = Arrow(frame: .zero) + + + + // MARK: - Initializers + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading)), + (view: rightLabel, model: StackItemModel(horizontalAlignment:.fill)), + (view: arrow, model: StackItemModel(horizontalAlignment:.fill))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //----------------------------------------------------- + override open func setupView() { + super.setupView() + addMolecule(stack) + stack.restack() + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListRightVariablePriceChangeBodyTextModel else { return } + eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + rightLabel.set(with: model.rightLabel, delegateObject, additionalData) + arrow.set(with: model.arrow, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 120 + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift new file mode 100644 index 00000000..3855ffb8 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift @@ -0,0 +1,52 @@ +// +// ListRightVariablePriceChangeBodyTextModel.swift +// MVMCoreUI +// +// Created by Dhamodaram Nandi on 13/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "listRVArwBdy" + public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + public var rightLabel: LabelModel + public var arrow: ArrowModel + + + + public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel,rightLabel: LabelModel,arrow: ArrowModel) { + self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + self.rightLabel = rightLabel + self.arrow = arrow + super.init() + } + + + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrowHeadlineBodyLink + case rightLabel + case arrow + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) + rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) + arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow) + + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + try container.encode(rightLabel, forKey: .rightLabel) + try container.encode(arrow, forKey: .arrow) + + } +} From c51dcfc5741706f6d5a4d28fd6f4c326fd18e30a Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Tue, 14 Apr 2020 14:13:04 +0530 Subject: [PATCH 027/136] arrow changes implemented --- .../ListRightVariablePriceChangeBodyText.swift | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index 7b4be31f..07e74886 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -16,14 +16,15 @@ import Foundation public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let rightLabel = Label.commonLabelB2(true) public let arrow = Arrow(frame: .zero) - - + let arrowAndrightLabelStack: Stack // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + arrowAndrightLabelStack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)), + (view: rightLabel, model: StackItemModel(horizontalAlignment: .leading))], + axis: .horizontal, spacing: 4) stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading)), - (view: rightLabel, model: StackItemModel(horizontalAlignment:.fill)), - (view: arrow, model: StackItemModel(horizontalAlignment:.fill))], + (view: arrowAndrightLabelStack, model: StackItemModel(verticalAlignment: .top))], axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -37,8 +38,11 @@ import Foundation //----------------------------------------------------- override open func setupView() { super.setupView() + arrow.pinHeightAndWidth() addMolecule(stack) stack.restack() + arrowAndrightLabelStack.restack() + } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { @@ -52,4 +56,8 @@ import Foundation open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 120 } + open override func reset() { + super.reset() + rightLabel.styleB2(true) + } } From 04a148aa72daec8bc425e5839d9f2c1114513ffe Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Tue, 14 Apr 2020 14:46:21 +0530 Subject: [PATCH 028/136] MFloadimageview changes reverted --- MVMCoreUI/Atomic/Atoms/Views/MFLoadImageView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atomic/Atoms/Views/MFLoadImageView.swift index b8b5321d..826759a7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MFLoadImageView.swift @@ -276,7 +276,7 @@ import UIKit let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback") if let format = format, format.lowercased().contains("gif") { // Gifs aren't supported by default and need special handling - MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, completionHandler: finishedLoadingBlock) + MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) } else { MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) } From 98ff848b33a0e73247f7c6e7e3c5093d6aac1861 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 14 Apr 2020 15:18:29 +0530 Subject: [PATCH 029/136] Added stroke color changes for selected and not selected. --- MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift | 8 ++++---- .../Selectors/RadioSwatchItemCollectionViewCell.swift | 1 - MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift | 5 +++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift index f6054ebb..2b5c05f3 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift @@ -71,7 +71,7 @@ open class RadioSwatchItem: Control { //Draw the strikethrough strikeLayer?.removeFromSuperlayer() if isOutOfStock { - let line = getStrikeThrough(color: UIColor.mvmCoolGray6, thickness: 1) + let line = getStrikeThrough(color: UIColor.mvmBlack, thickness: 1) layer.addSublayer(line) strikeLayer = line } @@ -79,7 +79,7 @@ open class RadioSwatchItem: Control { //Draw the selected layer selectedLayer?.removeFromSuperlayer() if isSelected { - let outerCircle = getSelectedLayer(color: UIColor.black, thickness: 1) + let outerCircle = getSelectedLayer(color: UIColor.mvmBlack, thickness: 1) layer.addSublayer(outerCircle) selectedLayer = outerCircle bottomText.isHidden = false @@ -121,7 +121,7 @@ open class RadioSwatchItem: Control { circle.fillColor = fillColor.cgColor circle.opacity = 1.0 circle.lineWidth = thickness - circle.strokeColor = isEnabled ? color.cgColor : UIColor.mvmCoolGray6.cgColor + circle.strokeColor = isSelected ? color.cgColor : UIColor.mvmCoolGray6.cgColor let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)) circle.path = circlePath.cgPath @@ -134,7 +134,7 @@ open class RadioSwatchItem: Control { strikeThrough.fillColor = nil strikeThrough.opacity = 1.0 strikeThrough.lineWidth = thickness - strikeThrough.strokeColor = color.cgColor + strikeThrough.strokeColor = isSelected ? color.cgColor : UIColor.mvmCoolGray6.cgColor let linePath = UIBezierPath() linePath.move(to: CGPoint(x: 12, y: 30)) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift index b274d28d..3d3100a8 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift @@ -19,6 +19,5 @@ open class RadioSwatchItemCollectionViewCell: CollectionViewCell { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? RadioSwatchItemModel else { return } radioSwatch.set(with: model, delegateObject, additionalData) - self.isUserInteractionEnabled = model.enabled ?? true } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index d73c749a..ed16fc39 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -114,6 +114,11 @@ extension RadioSwatches: UICollectionViewDataSource { return swatches?.count ?? 0 } + public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + guard let molecule = swatches?[indexPath.row] else {return true } + return molecule.enabled ?? true + } + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItemCollectionViewCell else { fatalError() From 0e2417b1a19db56b4c04ebc874088ccedddca312 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 14 Apr 2020 15:50:30 +0530 Subject: [PATCH 030/136] Code changes after merge from develop. --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++++++++-------- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../ListLeftVariableCheckboxBodyText.swift | 6 +++--- .../ListLeftVariableCheckboxBodyTextModel.swift | 10 +++++++--- 4 files changed, 19 insertions(+), 14 deletions(-) rename MVMCoreUI/Atomic/Molecules/DesignedComponents/{SectionDividers => List}/LeftVariable/ListLeftVariableCheckboxBodyText.swift (95%) rename MVMCoreUI/Atomic/Molecules/DesignedComponents/{SectionDividers => List}/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift (89%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c3dc2043..69dd61d0 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -190,8 +190,8 @@ AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; - AA4B6A67242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4B6A66242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift */; }; - AA4B6A69242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4B6A68242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift */; }; + AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; }; + AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; }; @@ -618,8 +618,8 @@ AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; - AA4B6A66242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; - AA4B6A68242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = ""; }; + AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; + AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = ""; }; @@ -1353,8 +1353,8 @@ 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, 0A6682A32434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift */, 0A6682A12434DB4F00AD3CA1 /* ListLeftVariableRadioButtonBodyText.swift */, - AA4B6A66242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift */, - AA4B6A68242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift */, + AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */, + AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */, ); path = LeftVariable; sourceTree = ""; @@ -2109,7 +2109,6 @@ D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, - AA4B6A67242A2E0300C124D3 /* ListLeftVariableCheckboxBodyText.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */, @@ -2173,7 +2172,6 @@ EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, - AA4B6A69242A2E1000C124D3 /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, 0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */, 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */, @@ -2194,6 +2192,7 @@ 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */, + AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */, D2B18B812360945C00A9AEDC /* View.swift in Sources */, C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, @@ -2248,6 +2247,7 @@ C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */, + AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index ab0d5b43..7ce9ff9f 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -136,6 +136,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxBodyText.self, viewModelClass: ListLeftVariableCheckboxBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/LeftVariable/ListLeftVariableCheckboxBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift similarity index 95% rename from MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/LeftVariable/ListLeftVariableCheckboxBodyText.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift index 6b05820f..ed9e84df 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/LeftVariable/ListLeftVariableCheckboxBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift @@ -2,7 +2,7 @@ // ListLeftVariableCheckboxBodyText.swift // MVMCoreUI // -// Created by Lekshmi S on 24/03/20. +// Created by Lekshmi S on 14/04/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // @@ -13,7 +13,7 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public let checkbox = Checkbox(frame: .zero) - public var headlineBody = HeadlineBody(frame: .zero) + public var headlineBody = HeadlineBody() public var stack: Stack //----------------------------------------------------- @@ -50,6 +50,6 @@ import Foundation } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 140 + return 90 } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift similarity index 89% rename from MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift index 1e149d98..5ee50501 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift @@ -2,12 +2,11 @@ // ListLeftVariableCheckboxBodyTextModel.swift // MVMCoreUI // -// Created by Lekshmi S on 24/03/20. +// Created by Lekshmi S on 14/04/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // import Foundation - open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -26,6 +25,11 @@ open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelPr super.init() } + open override func setDefaults() { + super.setDefaults() + headlineBody.style = .item + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -41,7 +45,7 @@ open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelPr required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) - checkbox = try typeContainer.decodeIfPresent(CheckboxModel.self, forKey: .checkbox) ?? CheckboxModel() + checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox) try super.init(from: decoder) } From f138c0a256f55798ffb1725efe8dec9f0ec04eb2 Mon Sep 17 00:00:00 2001 From: Kruthika KP <> Date: Tue, 14 Apr 2020 16:30:13 +0530 Subject: [PATCH 031/136] 18965 - List - Right Variable - Price Change - All Text & Links - Initial commit --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 3 +- ...htVariablePriceChangeAllTextAndLinks.swift | 69 +++++++++++++++++++ ...iablePriceChangeAllTextAndLinksModel.swift | 55 +++++++++++++++ 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 294f6188..07fe171e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -139,6 +139,8 @@ 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */; }; 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; }; + 8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */; }; + 8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; }; 8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; }; 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; }; 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; }; @@ -566,6 +568,8 @@ 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItemModel.swift; sourceTree = ""; }; 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = ""; }; + 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinksModel.swift; sourceTree = ""; }; + 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinks.swift; sourceTree = ""; }; 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalDataModel.swift; sourceTree = ""; }; 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = ""; }; 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = ""; }; @@ -1093,6 +1097,8 @@ AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */, 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */, + 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */, + 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */, C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, C7F8012023E8303200396FBD /* ListRVWheel.swift */, ); @@ -2085,6 +2091,7 @@ 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */, BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */, 012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */, + 8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */, 0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */, DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */, @@ -2210,6 +2217,7 @@ 0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */, AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */, 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */, + 8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */, 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index ab0d5b43..2886f49d 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -148,7 +148,8 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) - + MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self) + // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift new file mode 100644 index 00000000..6d179922 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -0,0 +1,69 @@ +// +// ListRightVariablePriceChangeAllTextAndLinks.swift +// MVMCoreUI +// +// Created by Kruthika KP on 13/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ListRightVariablePriceChangeAllTextAndLinks: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + open var stack: Stack + public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) + public let rightLabel = Label.commonLabelB2(true) + public let arrow = Arrow(frame: .zero) + public let arrowAndLabel2Stack: Stack + + //----------------------------------------------------- + // MARK: - Initializers + //----------------------------------------------------- + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + arrowAndLabel2Stack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .trailing)), + (view: rightLabel, model: StackItemModel(horizontalAlignment: .fill))], + axis: .horizontal, spacing: 6) + rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) + stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(percent: 70, horizontalAlignment: .leading)), + (view: arrowAndLabel2Stack, model: StackItemModel(percent: 30, horizontalAlignment: .fill, verticalAlignment: .top))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //----------------------------------------------------- + override open func setupView() { + super.setupView() + addMolecule(stack) + arrow.pinHeightAndWidth() + arrowAndLabel2Stack.restack() + stack.restack() + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListRightVariablePriceChangeAllTextAndLinksModel else { return } + eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + rightLabel.set(with: model.rightLabel, delegateObject, additionalData) + arrow.set(with: model.arrow, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 121 + } + + open override func reset() { + super.reset() + rightLabel.styleB2(true) + } +} + diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift new file mode 100644 index 00000000..c0f749e2 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift @@ -0,0 +1,55 @@ +// +// ListRightVariablePriceChangeAllTextAndLinksModel.swift +// MVMCoreUI +// +// Created by Kruthika KP on 13/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListRightVariablePriceChangeAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + + public static var identifier: String = "listRVArwAll" + public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + public var rightLabel: LabelModel + public var arrow: ArrowModel + + public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel, rightLabel: LabelModel, arrow: ArrowModel) { + self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + self.rightLabel = rightLabel + self.arrow = arrow + super.init() + } + + override public func setDefaults() { + super.setDefaults() + if let headline = eyebrowHeadlineBodyLink.headline { + headline.hero = 0 + } + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrowHeadlineBodyLink + case rightLabel + case arrow + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) + rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) + arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + try container.encode(rightLabel, forKey: .rightLabel) + try container.encode(arrow, forKey: .arrow) + } +} From a4ede5281034db760bdedf7c766a6d5fbdc8d090 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 09:54:27 -0400 Subject: [PATCH 032/136] improved error presentation --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 10 +++++----- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 9 --------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 23225a57..5e874936 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -211,11 +211,11 @@ import UIKit entryFieldContainer.refreshUI() } - /// Method to override. - /// Intended to add the interactive content (i.e. textField) to the entryFieldContainer. - @objc open func setupFieldContainerContent(_ container: UIView) { - // To be overridden by subclass. - } + /** + Method to override. + Intended to add the interactive content (i.e. textField) to the entryFieldContainer. + */ + @objc open func setupFieldContainerContent(_ container: UIView) { } @objc open override func updateView(_ size: CGFloat) { super.updateView(size) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index b267cd32..e9ba7d27 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -233,15 +233,6 @@ import UIKit entryFieldContainer.addGestureRecognizer(tap) accessibilityElements = [titleLabel, textField, feedbackLabel] - - // TODO: Remove these two lines. - let tapErr = UITapGestureRecognizer(target: self, action: #selector(tapForError)) - titleLabel.addGestureRecognizer(tapErr) - } - - // TODO: Remove this func - @objc func tapForError() { - showError.toggle() } @objc open override func updateView(_ size: CGFloat) { From cce4124bad8f71451246cdbdd6ada0f84c1a89e5 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 14 Apr 2020 10:18:58 -0400 Subject: [PATCH 033/136] Encode fix --- .../VerticalCombinationViews/Lists/UnOrderedListModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift index 32764641..3866e918 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift @@ -44,7 +44,7 @@ import Foundation var models: [MoleculeModelProtocol] = [] for molecule in molecules { - models.append((molecule as! MoleculeStackItemModel).molecule) + models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule) } try container.encodeModels(models, forKey: .list) } From bf1ca8b285a5bf5cf46a18e9141124dce09891a4 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 14 Apr 2020 10:20:33 -0400 Subject: [PATCH 034/136] remove unneeded comment --- MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift index c5c993f2..3965932d 100644 --- a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift @@ -53,7 +53,6 @@ open class MoleculeStackView: Stack { } } - /// open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { previousModel = self.model super.set(with: model, delegateObject, additionalData) From e03a4abbd5eb29a68a727361b3cae95a16c67eb2 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 10:29:49 -0400 Subject: [PATCH 035/136] broadening scope of toolbar func. improving MDN entryfield selection behavior. --- .../Atoms/TextFields/DateDropdownEntryField.swift | 2 +- .../Atomic/Atoms/TextFields/DigitEntryField.swift | 4 ++-- .../Atomic/Atoms/TextFields/MdnEntryField.swift | 14 +++++++++++++- .../Atomic/Atoms/TextFields/TextEntryField.swift | 9 +++++---- .../Atomic/Extensions/UIToolbar+Extension.swift | 8 ++++---- .../BaseControllers/ScrollingViewController.swift | 2 +- MVMCoreUI/BaseControllers/ViewController.swift | 2 +- .../MVMCoreUICommonViewsUtility+Extension.swift | 2 +- 8 files changed, 28 insertions(+), 15 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift index 50cca777..f16720f0 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift @@ -102,7 +102,7 @@ import UIKit } } - @objc override func dismissFieldInput(_ sender: Any?) { + @objc public override func dismissFieldInput(_ sender: Any?) { setTextWith(date: datePicker?.date) super.dismissFieldInput(sender) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 9d2c02cb..bc361abe 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -211,7 +211,7 @@ import UIKit let digitBox = DigitBox() digitBox.isAccessibilityElement = true - digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: self) + digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: self, action: #selector(dismissFieldInput)) digitBox.digitField.delegate = self digitBox.digitBoxDelegate = self return digitBox @@ -313,7 +313,7 @@ import UIKit return true } - @objc override func dismissFieldInput(_ sender: Any?) { + @objc public override func dismissFieldInput(_ sender: Any?) { digitBoxes.forEach { if $0.isSelected { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index 71bc0539..620ce26f 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -48,6 +48,18 @@ import MVMCore 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 //-------------------------------------------------- @@ -81,7 +93,7 @@ import MVMCore let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() 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 dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:))) + let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput)) toolbar.items = [contacts, space, dismissButton] textField.inputAccessoryView = toolbar } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index e9ba7d27..f138d860 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -15,7 +15,7 @@ import UIKit /// Called when the entered text becomes invalid based on the validation block @objc optional func isInvalid(textfield: TextEntryField?) /// Dismisses the keyboard. - @objc optional func dismissFieldInput(sender: Any?) + @objc optional func dismissFieldInput(_ sender: Any?) } @@ -227,7 +227,7 @@ import UIKit textFieldTrailingConstraint?.isActive = true 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)) entryFieldContainer.addGestureRecognizer(tap) @@ -312,7 +312,7 @@ import UIKit } } - @objc func dismissFieldInput(_ sender: Any?) { + @objc public func dismissFieldInput(_ sender: Any?) { resignFirstResponder() } @@ -358,7 +358,8 @@ import UIKit uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate - textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self) + textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self, + action: #selector(observingTextFieldDelegate?.dismissFieldInput)) } } diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift index 6686f164..4d31f708 100644 --- a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -8,7 +8,7 @@ import Foundation -/* + public extension UIToolbar { class func makeEmptyToolbar() -> UIToolbar { @@ -22,15 +22,15 @@ public extension UIToolbar { return toolbar } - class func getToolbarWithDoneButton(delegate: ObservingTextFieldDelegate) -> UIToolbar { + class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar { let toolbar = makeEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput)) + let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) button.tintColor = .mvmBlack toolbar.setItems([space, button], animated: false) return toolbar } } -*/ + diff --git a/MVMCoreUI/BaseControllers/ScrollingViewController.swift b/MVMCoreUI/BaseControllers/ScrollingViewController.swift index 2e4eceef..97e83f98 100644 --- a/MVMCoreUI/BaseControllers/ScrollingViewController.swift +++ b/MVMCoreUI/BaseControllers/ScrollingViewController.swift @@ -36,7 +36,7 @@ open class ScrollingViewController: ViewController { super.viewDidLoad() // 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!) dismissKeyboardTapGesture?.isEnabled = false scrollView.alwaysBounceVertical = false diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index eb4be908..c74b6a0c 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -399,7 +399,7 @@ import UIKit } } - @objc open func dismissFieldInput(sender: Any?) { + @objc open func dismissFieldInput(_ sender: Any?) { selectedField?.resignFirstResponder() } diff --git a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift index 3ee452b0..704cf801 100644 --- a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift +++ b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift @@ -14,7 +14,7 @@ public extension MVMCoreUICommonViewsUtility { let toolbar = self.makeEmptyToolbar() 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 toolbar.setItems([space, button], animated: false) From 3466be23c8ad2a0f2c549c9b5baffb655220ae7e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 10:49:36 -0400 Subject: [PATCH 036/136] little changes --- MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift | 3 +-- MVMCoreUI/Styles/Styler.swift | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift index 4d31f708..494aaf45 100644 --- a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -13,7 +13,7 @@ public extension UIToolbar { class func makeEmptyToolbar() -> UIToolbar { - let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44.0)) + 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 @@ -33,4 +33,3 @@ public extension UIToolbar { return toolbar } } - diff --git a/MVMCoreUI/Styles/Styler.swift b/MVMCoreUI/Styles/Styler.swift index b5d6627c..509ad107 100644 --- a/MVMCoreUI/Styles/Styler.swift +++ b/MVMCoreUI/Styles/Styler.swift @@ -10,10 +10,8 @@ import Foundation open class Styler { - //-------------------------------------------------- - // MARK: - Enums - //-------------------------------------------------- + // MARK:- Font Enum public enum Font: String, Codable { case Title2XLarge case TitleXLarge From 5f539aa6b724173c1d27ab96d9687c25172e06f0 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 11:57:51 -0400 Subject: [PATCH 037/136] extending picker classes for more logical separation and modernization --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++ .../TextFields/DateDropdownEntryField.swift | 4 +- .../Atoms/TextFields/DigitEntryField.swift | 3 +- .../TextFields/ItemDropdownEntryField.swift | 2 +- .../Atoms/TextFields/MdnEntryField.swift | 2 +- .../Extensions/UIDatePicker+Extension.swift | 37 ++++++++++++++++++ .../Extensions/UIPickerView+Extension.swift | 39 +++++++++++++++++++ .../Extensions/UIToolbar+Extension.swift | 28 ++++++++++++- 8 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift create mode 100644 MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index cdba6c77..3803e156 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -104,6 +104,8 @@ 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; }; 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.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 */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; @@ -532,6 +534,8 @@ 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = ""; }; 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = ""; }; + 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = ""; }; + 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIPickerView+Extension.swift"; sourceTree = ""; }; 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; @@ -1119,6 +1123,8 @@ D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */, 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */, 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */, + 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */, + 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */, ); path = Extensions; sourceTree = ""; @@ -2292,6 +2298,7 @@ 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, + 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, @@ -2372,6 +2379,7 @@ 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, + 0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */, 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift index f16720f0..1c2fef83 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift @@ -67,10 +67,10 @@ import UIKit public override func setupFieldContainerContent(_ container: UIView) { super.setupFieldContainerContent(container) - datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField) + datePicker = UIDatePicker.addDatePicker(to: textField) datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged) 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) { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index bc361abe..2bf80e9d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -331,7 +331,8 @@ import UIKit setAsSecureTextEntry(model.secureEntry) for digitBox in digitBoxes { - digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self) + digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self, + action: #selector(observingTextFieldDelegate?.dismissFieldInput)) } super.set(with: model, delegateObject, additionalData) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift index bd6d793c..4bddc5b9 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift @@ -62,7 +62,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField { @objc open override func setupFieldContainerContent(_ container: UIView) { super.setupFieldContainerContent(container) - pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self) + pickerView = UIPickerView.addPicker(to: textField, delegate: self, dismissAction: #selector(dismissFieldInput)) textField.hideBlinkingCaret = true textField.autocorrectionType = .no uiTextFieldDelegate = self diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index 620ce26f..28f7ba21 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -90,7 +90,7 @@ import MVMCore textField.keyboardType = .numberPad - let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() + let toolbar = UIToolbar.emptyToolbar() 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 dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput)) diff --git a/MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift new file mode 100644 index 00000000..4c1acfcb --- /dev/null +++ b/MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift @@ -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 + } +} diff --git a/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift new file mode 100644 index 00000000..795583bb --- /dev/null +++ b/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift @@ -0,0 +1,39 @@ +// +// 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: (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)?, 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 + } +} diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift index 494aaf45..1a677469 100644 --- a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -8,10 +8,15 @@ import Foundation +public protocol TextFieldOrView { } + +extension UITextView: TextFieldOrView { } +extension UITextField: TextFieldOrView { } + public extension UIToolbar { - class func makeEmptyToolbar() -> UIToolbar { + class func emptyToolbar() -> UIToolbar { let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44)) toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth] @@ -24,7 +29,7 @@ public extension UIToolbar { class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar { - let toolbar = makeEmptyToolbar() + let toolbar = emptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) button.tintColor = .mvmBlack @@ -32,4 +37,23 @@ public extension UIToolbar { return toolbar } + + class func addDismissToolbar(to object: TextFieldOrView?, delegate: Any?, action: Selector) { + + let toolbar = emptyToolbar() + let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) + dismissButton.tintColor = UIColor.black + toolbar.items = [space, dismissButton] + + switch object { + case is UITextField: + (object as? UITextField)?.inputAccessoryView = toolbar + + case is UITextView: + (object as? UITextView)?.inputAccessoryView = toolbar + default: + return + } + } } From ddc44a17edf4ad1e8018ba585662262951293c6f Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 14:01:23 -0400 Subject: [PATCH 038/136] error image for secure entry state --- .../TextFields/ItemDropdownEntryField.swift | 2 + .../Atoms/TextFields/MdnEntryField.swift | 4 +- .../Atoms/TextFields/TextEntryField.swift | 64 ++++++------------- .../Extensions/UIPickerView+Extension.swift | 3 +- .../Extensions/UIToolbar+Extension.swift | 11 ++-- 5 files changed, 32 insertions(+), 52 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift index 4bddc5b9..cc8a4c71 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryField.swift @@ -8,6 +8,8 @@ import UIKit +public typealias TextFieldAndPickerDelegate = (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource) + open class ItemDropdownEntryField: BaseDropdownEntryField { //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index 28f7ba21..55a903d0 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -90,9 +90,9 @@ import MVMCore textField.keyboardType = .numberPad - let toolbar = UIToolbar.emptyToolbar() + let toolbar = UIToolbar.createEmptyToolbar() 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)) toolbar.items = [contacts, space, dismissButton] textField.inputAccessoryView = toolbar diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index f138d860..a90ad63b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -36,12 +36,6 @@ import UIKit return textField }() - private var standardAccessoryView: UIView? - - public var accessoryView: UIView? { - didSet { accessoryView == nil ? unconstrainAccessoryView() : constrainAccessoryView() } - } - public lazy var errorImage: UIImageView = { let image = MVMCoreUIUtility.imageNamed("alert_standard") let imageView = UIImageView(image: image) @@ -63,8 +57,6 @@ import UIKit /// Validate on each entry in the textField. Default: true public var validateEachCharacter: Bool = true - var usesAccessoryView: Bool = true - /// Validate when user resigns editing. Default: true public var validateWhenDoneEditing: Bool = true @@ -101,14 +93,7 @@ import UIKit } if textField.isSecureTextEntry { - if !error { - accessoryView?.removeFromSuperview() - accessoryView = nil - accessoryView = standardAccessoryView - } else { - standardAccessoryView = accessoryView - accessoryView = errorImage - } + showErrorView(error) } super.showError = error @@ -163,28 +148,6 @@ import UIKit //-------------------------------------------------- public var textFieldTrailingConstraint: NSLayoutConstraint? - public var accessoryViewTrailingConstraint: NSLayoutConstraint? - - public func constrainAccessoryView() { - - guard let accessoryView = accessoryView else { return } - - entryFieldContainer.addSubview(accessoryView) - - textFieldTrailingConstraint?.isActive = false - textFieldTrailingConstraint = accessoryView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) - textFieldTrailingConstraint?.isActive = true - - accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four) - accessoryViewTrailingConstraint?.isActive = true - accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true - } - - public func unconstrainAccessoryView() { - - textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) - textFieldTrailingConstraint?.isActive = true - } //-------------------------------------------------- // MARK: - Initializers @@ -248,10 +211,6 @@ import UIKit textField.font = Styler.Font.RegularBodyLarge.getFont() } - @objc deinit { - setBothTextDelegates(to: nil) - } - @objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) { observingTextFieldDelegate = delegate uiTextFieldDelegate = delegate @@ -260,7 +219,7 @@ import UIKit //-------------------------------------------------- // MARK: - Observing for Change (TextFieldDelegate) //-------------------------------------------------- - + @discardableResult @objc override open func resignFirstResponder() -> Bool { if validateWhenDoneEditing { @@ -316,6 +275,25 @@ import UIKit 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.Four).isActive = true + errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true + + } else { + errorImage.removeFromSuperview() + textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint?.isActive = true + } + } + //-------------------------------------------------- // MARK: - MoleculeViewProtocol //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift index 795583bb..aa933e05 100644 --- a/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift @@ -9,7 +9,6 @@ import Foundation - public extension UIPickerView { class func createPickerView() -> UIPickerView { @@ -20,7 +19,7 @@ public extension UIPickerView { return picker } - class func addPicker(to textField: UITextField, delegate: (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)?, dismissAction: Selector?) -> UIPickerView { + class func addPicker(to textField: UITextField, delegate: TextFieldAndPickerDelegate?, dismissAction: Selector?) -> UIPickerView { // Sets up the picker (same tag as the textfield) let picker = createPickerView() diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift index 1a677469..a3e315c2 100644 --- a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -16,7 +16,7 @@ extension UITextField: TextFieldOrView { } public extension UIToolbar { - class func emptyToolbar() -> 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] @@ -29,7 +29,7 @@ public extension UIToolbar { class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar { - let toolbar = emptyToolbar() + let toolbar = createEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) button.tintColor = .mvmBlack @@ -38,12 +38,12 @@ public extension UIToolbar { return toolbar } - class func addDismissToolbar(to object: TextFieldOrView?, delegate: Any?, action: Selector) { + class func addDismissToolbar(to object: TextFieldOrView, delegate: Any?, action: Selector) { - let toolbar = emptyToolbar() + let toolbar = createEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) - dismissButton.tintColor = UIColor.black + dismissButton.tintColor = .mvmBlack toolbar.items = [space, dismissButton] switch object { @@ -52,6 +52,7 @@ public extension UIToolbar { case is UITextView: (object as? UITextView)?.inputAccessoryView = toolbar + default: return } From 1e86bfbc32d5dabc74f03361fd233b3356877460 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 14 Apr 2020 14:06:27 -0400 Subject: [PATCH 039/136] reuse issue fix --- MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift index 6339d002..ceecdd9b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift @@ -61,6 +61,7 @@ import UIKit /// Creates the bars open func set(with progressList: Array, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + stack.removeAllItemViews() guard let stackModel = stack.stackModel else { return } var views: [StackItem] = [] var models: [StackItemModel] = [] @@ -89,6 +90,7 @@ import UIKit open override func reset() { super.reset() backgroundColor = .mfLightSilver() + stack.reset() set(with: [], nil, nil) } From 7f7999774e79ff4c6bfe396520ef0298f13ee377 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 14:28:57 -0400 Subject: [PATCH 040/136] revised secure entry --- MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift | 5 ++++- .../Atomic/Atoms/TextFields/DigitEntryFieldModel.swift | 7 ------- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 2 +- .../Atomic/Atoms/TextFields/TextEntryFieldModel.swift | 1 + 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 2bf80e9d..d5648342 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -328,7 +328,10 @@ import UIKit guard let model = model as? DigitEntryFieldModel else { return } numberOfDigits = model.digits - setAsSecureTextEntry(model.secureEntry) + + if let entryType = model.type { + setAsSecureTextEntry(entryType == .secure || entryType == .password) + } for digitBox in digitBoxes { digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self, diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift index 423c1d7d..e91eca77 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift @@ -17,7 +17,6 @@ } public var digits: Int = 4 - public var secureEntry: Bool = false //-------------------------------------------------- // MARK: - Keys @@ -26,7 +25,6 @@ private enum CodingKeys: String, CodingKey { case moleculeName case digits - case secureEntry } //-------------------------------------------------- @@ -40,10 +38,6 @@ if let digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) { self.digits = digits } - - if let secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) { - self.secureEntry = secureEntry - } } public override func encode(to encoder: Encoder) throws { @@ -51,6 +45,5 @@ var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(digits, forKey: .digits) - try container.encode(secureEntry, forKey: .secureEntry) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index a90ad63b..0f4960be 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -321,7 +321,7 @@ import UIKit placeholder = model.placeholder switch model.type { - case .password: + case .password, .secure: textField.isSecureTextEntry = true case .number: diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index 99a5dba4..c12b92ac 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -14,6 +14,7 @@ public enum EntryType: String, Codable { case password + case secure case number case email } From 9e47ea8e1c374706f92b53bc951cdb1b048264ff Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 14 Apr 2020 15:30:15 -0400 Subject: [PATCH 041/136] remove bad remove items --- MVMCoreUI/Atomic/Organisms/Stack.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index d43719a9..f539cf8b 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -148,7 +148,6 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - removeAllItemViews() setStackItemsFromModel(model, delegateObject, additionalData) restack() } From 4f3b61944c1b49b9b986a0c22ceac19eed2cc545 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 14 Apr 2020 17:08:24 -0400 Subject: [PATCH 042/136] changing delegate --- MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index d5648342..aff5ec75 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -211,7 +211,8 @@ import UIKit let digitBox = DigitBox() digitBox.isAccessibilityElement = true - digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: self, action: #selector(dismissFieldInput)) + digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self, + action: #selector(observingTextFieldDelegate?.dismissFieldInput)) digitBox.digitField.delegate = self digitBox.digitBoxDelegate = self return digitBox From 73403b894875cdc7441bc68147e7849506e6923c Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Wed, 15 Apr 2020 08:53:28 +0530 Subject: [PATCH 043/136] alignment changes updated --- .../RightVariable/ListRightVariablePriceChangeBodyText.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index 07e74886..fd29f10c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -23,8 +23,8 @@ import Foundation arrowAndrightLabelStack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)), (view: rightLabel, model: StackItemModel(horizontalAlignment: .leading))], axis: .horizontal, spacing: 4) - stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading)), - (view: arrowAndrightLabelStack, model: StackItemModel(verticalAlignment: .top))], + stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(percent:70,horizontalAlignment: .leading)), + (view: arrowAndrightLabelStack, model: StackItemModel(percent:30,horizontalAlignment: .trailing,verticalAlignment: .top))], axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } From 594a45894e5899aec606206258fbcf14146c9b86 Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Wed, 15 Apr 2020 15:57:57 +0530 Subject: [PATCH 044/136] updated as per confluence --- ...ListRightVariablePriceChangeBodyText.swift | 26 +++++++++---------- ...ightVariablePriceChangeBodyTextModel.swift | 6 ----- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index fd29f10c..c62a7eaf 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -13,18 +13,18 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public var stack: Stack - public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) + public let headlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let rightLabel = Label.commonLabelB2(true) public let arrow = Arrow(frame: .zero) - let arrowAndrightLabelStack: Stack + let arrowAndRightLabelStack: Stack // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - arrowAndrightLabelStack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)), - (view: rightLabel, model: StackItemModel(horizontalAlignment: .leading))], - axis: .horizontal, spacing: 4) - stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(percent:70,horizontalAlignment: .leading)), - (view: arrowAndrightLabelStack, model: StackItemModel(percent:30,horizontalAlignment: .trailing,verticalAlignment: .top))], + arrowAndRightLabelStack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)), + (view: rightLabel, model: StackItemModel(horizontalAlignment: .leading))], + axis: .horizontal, spacing: 6) + stack = Stack.createStack(with: [(view: headlineBodyLink, model: StackItemModel(percent:70,horizontalAlignment: .leading)), + (view: arrowAndRightLabelStack, model: StackItemModel(percent:30,horizontalAlignment: .trailing,verticalAlignment: .top))], axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -41,14 +41,13 @@ import Foundation arrow.pinHeightAndWidth() addMolecule(stack) stack.restack() - arrowAndrightLabelStack.restack() - + arrowAndRightLabelStack.restack() } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? ListRightVariablePriceChangeBodyTextModel else { return } - eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + headlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) rightLabel.set(with: model.rightLabel, delegateObject, additionalData) arrow.set(with: model.arrow, delegateObject, additionalData) } @@ -56,8 +55,9 @@ import Foundation open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 120 } + open override func reset() { - super.reset() - rightLabel.styleB2(true) - } + super.reset() + rightLabel.styleB2(true) + } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift index 3855ffb8..e2d90eb7 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift @@ -13,8 +13,6 @@ public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeM public var rightLabel: LabelModel public var arrow: ArrowModel - - public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel,rightLabel: LabelModel,arrow: ArrowModel) { self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink self.rightLabel = rightLabel @@ -22,8 +20,6 @@ public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeM super.init() } - - private enum CodingKeys: String, CodingKey { case moleculeName case eyebrowHeadlineBodyLink @@ -36,7 +32,6 @@ public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeM eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow) - try super.init(from: decoder) } @@ -47,6 +42,5 @@ public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeM try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) try container.encode(rightLabel, forKey: .rightLabel) try container.encode(arrow, forKey: .arrow) - } } From dcd6257f95db113c08ada80290e1e7fd7697578f Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 15 Apr 2020 11:29:32 -0400 Subject: [PATCH 045/136] merge --- MVMCoreUI/BaseControllers/ViewController.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index a49dfad3..677d9e31 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -236,10 +236,13 @@ import UIKit } // MARK: - View lifecycle + + /// Called only once in viewDidLoad open func initialLoad() { observeForResponseJSONUpdates() } + /// Called on screen size update. open func updateViews() { _ = formValidator?.validate() } @@ -265,8 +268,7 @@ import UIKit initialLoad() } - // Handle data for first load. Dispatched to allow subclasses to finish their view did load implementations. - self.handleNewDataAndUpdateUI() + handleNewDataAndUpdateUI() } open override func viewDidLayoutSubviews() { From 7fd0df1b91de59879958a49b4bafc508d6055b5e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 12:07:49 -0400 Subject: [PATCH 046/136] revised how toolbar is configured --- .../Atomic/Atoms/TextFields/MdnEntryField.swift | 3 +++ .../Atomic/Atoms/TextFields/TextEntryField.swift | 13 +++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index 55a903d0..ce36a7cb 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -89,6 +89,9 @@ import MVMCore super.setupFieldContainerContent(container) textField.keyboardType = .numberPad + } + + open override func setupTextFieldToolbar() { let toolbar = UIToolbar.createEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 0f4960be..695694ac 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -182,11 +182,11 @@ import UIKit NSLayoutConstraint.activate([ textField.heightAnchor.constraint(equalToConstant: Padding.Five), textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three), - textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Four), + textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three), container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: Padding.Three) ]) - textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Three) textFieldTrailingConstraint?.isActive = true textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin) @@ -216,6 +216,12 @@ import UIKit uiTextFieldDelegate = delegate } + open func setupTextFieldToolbar() { + + textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self, + action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + } + //-------------------------------------------------- // MARK: - Observing for Change (TextFieldDelegate) //-------------------------------------------------- @@ -336,8 +342,7 @@ import UIKit uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate - textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self, - action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + setupTextFieldToolbar() } } From 1415b1bf5e2146e65a47f3ab3d0cb4bdb646a040 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 12:11:29 -0400 Subject: [PATCH 047/136] revised how toolbar is configured --- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 695694ac..2b68bb6b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -290,12 +290,12 @@ import UIKit textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) textFieldTrailingConstraint?.isActive = true - entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Four).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 = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Four) + textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) textFieldTrailingConstraint?.isActive = true } } From 217ec0333e93d3e6f0b89671002bb0ca45a6fbc1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 12:14:27 -0400 Subject: [PATCH 048/136] resolving all default button tint to black --- MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift index a3e315c2..49826504 100644 --- a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -22,6 +22,7 @@ public extension UIToolbar { toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth] toolbar.barStyle = .default toolbar.barTintColor = .mvmCoolGray3 + toolbar.tintColor = .mvmBlack toolbar.isTranslucent = true return toolbar @@ -32,7 +33,6 @@ public extension UIToolbar { let toolbar = createEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) - button.tintColor = .mvmBlack toolbar.setItems([space, button], animated: false) return toolbar @@ -43,7 +43,6 @@ public extension UIToolbar { let toolbar = createEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) - dismissButton.tintColor = .mvmBlack toolbar.items = [space, dismissButton] switch object { From d19b46d3e933d0ac50a726cca8eaecc98c7317fc Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 15 Apr 2020 12:37:05 -0400 Subject: [PATCH 049/136] corner labels defect fix --- .../Atomic/Molecules/LeftRightViews/CornerLabels.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift index c0018e9b..7eb3282b 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift @@ -164,10 +164,12 @@ import UIKit public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? CornerLabelsModel else { return } - if middleView != nil { - (middleView as? MoleculeViewProtocol)?.set(with: model, delegateObject, additionalData) - } else if let moleculeModel = model.molecule, let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { - addMiddleView(molecule) + if let moleculeModel = model.molecule { + if middleView != nil { + (middleView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData) + } else if let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { + addMiddleView(molecule) + } } topLeftLabel.setOptional(with: model.topLeftLabel, delegateObject, additionalData) From 904f8a35a262f931f0dd16dc0e718d2f02770258 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 13:00:04 -0400 Subject: [PATCH 050/136] reverting change --- MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift | 1 + MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 2 +- MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift index 1c2fef83..9860cd5b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryField.swift @@ -31,6 +31,7 @@ import UIKit return formatter }() + /// Update the property value to alter the format of how the date is presented. public var dateFormat: String = "MMM d, y" { didSet { dateFormatter.dateFormat = dateFormat } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 5e874936..d5abbe9f 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -67,7 +67,7 @@ import UIKit public var showError: Bool { get { return entryFieldContainer.showError } set (error) { - self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.informativeMessage + self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback self.entryFieldContainer.showError = error } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 1f0e3d78..0da17d96 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -87,7 +87,6 @@ import Foundation } feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) - informativeMessage = feedback if let errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) { self.errorMessage = errorMessage From 9181d3f6d1d30ed83145b53961b4d1b681d4ade6 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 13:05:38 -0400 Subject: [PATCH 051/136] removed unused variable --- MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 0da17d96..1cde6377 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -23,7 +23,6 @@ import Foundation public var title: String = "" public var feedback: String? public var errorMessage: String? - public var informativeMessage: String? public var enabled: Bool = true public var locked: Bool? public var selected: Bool? From e8aaad52876880f3ca5239dce0f00152b5eec20d Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 14:54:00 -0400 Subject: [PATCH 052/136] removing redundancy --- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index c12b92ac..b7d1cb7c 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -38,7 +38,6 @@ private enum CodingKeys: String, CodingKey { case moleculeName - case text case placeholder case enabledTextColor case disabledTextColor @@ -52,7 +51,6 @@ required public init(from decoder: Decoder) throws { try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - text = try typeContainer.decodeIfPresent(String.self, forKey: .text) placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder) enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) @@ -63,7 +61,6 @@ try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(text, forKey: .text) try container.encodeIfPresent(placeholder, forKey: .placeholder) try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) From a083a01dd812f01ee7401447afba453b9734aa96 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 15:14:55 -0400 Subject: [PATCH 053/136] resolving a race condition --- MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index ce36a7cb..ad7c8b49 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -125,7 +125,7 @@ import MVMCore let isValid = hasValidMDN() - if isValid { + if self.isValid { showError = false } else { From e5247ac13f976463f7460ac001c81e14925b4882 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 15 Apr 2020 15:26:44 -0400 Subject: [PATCH 054/136] resolving a race condition --- MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift index ad7c8b49..d80a008b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/MdnEntryField.swift @@ -123,7 +123,7 @@ import MVMCore return true } - let isValid = hasValidMDN() + isValid = hasValidMDN() if self.isValid { showError = false From a57f07c22b843ef1ec01e9ba35c22848a9709640 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 15 Apr 2020 17:42:57 -0400 Subject: [PATCH 055/136] remove previous items --- MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift index 3965932d..e0517d45 100644 --- a/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Atomic/Organisms/MoleculeStackView.swift @@ -46,6 +46,7 @@ open class MoleculeStackView: Stack { open override func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { // If the items in the stack are different, clear them, create new ones. if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) { + removeAllItemViews() stackItems = [] createStackItemsFromModel(model, delegateObject, additionalData) } else { From 8479ed605a4694bf43902d352a425904089c160a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 15 Apr 2020 18:09:10 -0400 Subject: [PATCH 056/136] small fix encoding numbered list --- .../VerticalCombinationViews/Lists/NumberedListModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift index f58a62ff..eeacb98d 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift @@ -38,9 +38,9 @@ import Foundation var models: [MoleculeModelProtocol] = [] for molecule in molecules { - models.append((molecule as! MoleculeStackItemModel).molecule) + models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule) } - try container.encodeModels(molecules, forKey: .list) + try container.encodeModels(models, forKey: .list) } } From e1894bd74b9fe2f7307fb5b0fc6ac48fb1f34323 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Thu, 16 Apr 2020 11:26:56 +0530 Subject: [PATCH 057/136] moved function, clean code --- MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift | 7 ++++--- MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift index 2b5c05f3..9117aee8 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift @@ -64,14 +64,14 @@ open class RadioSwatchItem: Control { open override func draw(_ layer: CALayer, in ctx: CGContext) { //Draw the swatch circleLayer?.removeFromSuperlayer() - let circle = getCircle(color: UIColor.mvmBlack, thickness: 1) + let circle = getCircle(color: .mvmBlack, thickness: 1) layer.addSublayer(circle) circleLayer = circle //Draw the strikethrough strikeLayer?.removeFromSuperlayer() if isOutOfStock { - let line = getStrikeThrough(color: UIColor.mvmBlack, thickness: 1) + let line = getStrikeThrough(color: .mvmBlack, thickness: 1) layer.addSublayer(line) strikeLayer = line } @@ -79,7 +79,7 @@ open class RadioSwatchItem: Control { //Draw the selected layer selectedLayer?.removeFromSuperlayer() if isSelected { - let outerCircle = getSelectedLayer(color: UIColor.mvmBlack, thickness: 1) + let outerCircle = getSelectedLayer(color: .mvmBlack, thickness: 1) layer.addSublayer(outerCircle) selectedLayer = outerCircle bottomText.isHidden = false @@ -104,6 +104,7 @@ open class RadioSwatchItem: Control { } @objc open func selectSwatch() { + guard isEnabled else { return } isSelected = true radioSwatchModel?.selected = isSelected layer.setNeedsDisplay() diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index ed16fc39..2811da69 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -114,11 +114,6 @@ extension RadioSwatches: UICollectionViewDataSource { return swatches?.count ?? 0 } - public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - guard let molecule = swatches?[indexPath.row] else {return true } - return molecule.enabled ?? true - } - open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItemCollectionViewCell else { fatalError() @@ -135,6 +130,11 @@ extension RadioSwatches: UICollectionViewDataSource { } extension RadioSwatches: UICollectionViewDelegate { + public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + guard let molecule = swatches?[indexPath.row] else {return true } + return molecule.enabled ?? true + } + public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } cell.radioSwatch.selectSwatch() From 932a79dea8dada272d190fadcb4d460eabc7041e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 16 Apr 2020 09:05:09 -0400 Subject: [PATCH 058/136] few more improvements to work closer with molecular --- .../ActionCollapseNotificationModel.swift | 2 ++ MVMCoreUI/Actions/ActionOpenPanelModel.swift | 2 ++ MVMCoreUI/Actions/ActionTopAlertModel.swift | 2 ++ .../DateDropdownEntryFieldModel.swift | 4 +--- .../TextFields/DigitEntryFieldModel.swift | 4 +--- .../Atomic/Atoms/TextFields/EntryField.swift | 1 - .../Atoms/TextFields/EntryFieldModel.swift | 18 ++++++++--------- .../ItemDropdownEntryFieldModel.swift | 2 -- .../Atoms/TextFields/TextEntryField.swift | 10 +++------- .../TextFields/TextEntryFieldModel.swift | 20 ++++++++++++------- 10 files changed, 33 insertions(+), 32 deletions(-) diff --git a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift index 1a665b80..a305436b 100644 --- a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift +++ b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift @@ -9,6 +9,8 @@ import UIKit @objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol { + public var title: String? + public static var identifier: String = "collapseNotification" public var actionType: String public var extraParameters: JSONValueDictionary? diff --git a/MVMCoreUI/Actions/ActionOpenPanelModel.swift b/MVMCoreUI/Actions/ActionOpenPanelModel.swift index 6ada6f04..4e2c26bf 100644 --- a/MVMCoreUI/Actions/ActionOpenPanelModel.swift +++ b/MVMCoreUI/Actions/ActionOpenPanelModel.swift @@ -9,6 +9,8 @@ import Foundation public class ActionOpenPanelModel: ActionModelProtocol { + public var title: String? + public enum Panel: String, Codable { case left diff --git a/MVMCoreUI/Actions/ActionTopAlertModel.swift b/MVMCoreUI/Actions/ActionTopAlertModel.swift index 29838c76..dbcf6371 100644 --- a/MVMCoreUI/Actions/ActionTopAlertModel.swift +++ b/MVMCoreUI/Actions/ActionTopAlertModel.swift @@ -9,6 +9,8 @@ import Foundation @objcMembers public class ActionTopAlertModel: ActionModelProtocol { + public var title: String? + public static var identifier: String = "topAlert" public var actionType: String = ActionTopAlertModel.identifier public var pageType: String diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift index 726eab1f..86c072dd 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -22,12 +22,11 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case moleculeName case dateFormat } //-------------------------------------------------- - // MARK: - Initializers + // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { @@ -42,7 +41,6 @@ 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(dateFormat, forKey: .dateFormat) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift index e91eca77..b906244d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryFieldModel.swift @@ -23,12 +23,11 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case moleculeName case digits } //-------------------------------------------------- - // MARK: - Initializers + // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { @@ -43,7 +42,6 @@ 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(digits, forKey: .digits) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index efa0b592..6bb82fe1 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -252,7 +252,6 @@ import UIKit title = model.title feedback = model.feedback - errorMessage = model.errorMessage isEnabled = model.enabled if let isLocked = model.locked { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index f91febf4..d6b7e279 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -20,9 +20,9 @@ import Foundation } public var backgroundColor: Color? - public var title: String = "" + public var title: String? public var feedback: String? - public var errorMessage: String = "" + public var errorMessage: String? public var enabled: Bool = true public var locked: Bool? public var selected: Bool? @@ -77,16 +77,16 @@ import Foundation baseValue = text } + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - - if let title = try typeContainer.decodeIfPresent(String.self, forKey: .title) { - self.title = title - } - + title = try typeContainer.decodeIfPresent(String.self, forKey: .title) 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 locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked) selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) @@ -106,7 +106,7 @@ import Foundation try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(locked, forKey: .locked) try container.encodeIfPresent(selected, forKey: .selected) - try container.encode(errorMessage, forKey: .errorMessage) + try container.encodeIfPresent(errorMessage, forKey: .errorMessage) try container.encode(enabled, forKey: .enabled) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index 2f2003c0..8554244b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -23,7 +23,6 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case moleculeName case options case selectedIndex } @@ -48,7 +47,6 @@ 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(options, forKey: .options) try container.encode(options, forKey: .selectedIndex) } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 2b68bb6b..0abf4b93 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -49,9 +49,6 @@ import UIKit // 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 /// Validate on each entry in the textField. Default: true @@ -77,7 +74,7 @@ import UIKit guard let self = self else { return } 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 } } } @@ -295,6 +292,7 @@ import UIKit } else { errorImage.removeFromSuperview() + textFieldTrailingConstraint?.isActive = false textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) textFieldTrailingConstraint?.isActive = true } @@ -320,9 +318,7 @@ import UIKit } self.delegateObject = delegateObject - FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - textColor.enabled = model.enabledTextColor?.uiColor - textColor.disabled = model.disabledTextColor?.uiColor + FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) text = model.text placeholder = model.placeholder diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index b7d1cb7c..491e9891 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -28,8 +28,8 @@ } public var placeholder: String? - public var enabledTextColor: Color? - public var disabledTextColor: Color? + public var enabledTextColor: Color = Color(uiColor: .mvmBlack) + public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3) public var type: EntryType? //-------------------------------------------------- @@ -45,16 +45,22 @@ } //-------------------------------------------------- - // MARK: - Initializers + // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) 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) + + 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 { @@ -62,8 +68,8 @@ var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(placeholder, forKey: .placeholder) - try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) - try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) + try container.encode(enabledTextColor, forKey: .enabledTextColor) + try container.encode(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(type, forKey: .type) } } From dfa49641d8f047900b366903b9d7a656c46f7525 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 16 Apr 2020 13:30:15 -0400 Subject: [PATCH 059/136] disable tap if radio is disabled --- MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift | 3 +++ .../ListLeftVariableRadioButtonAndPaymentMethod.swift | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index a5fedef0..1a968b7a 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -90,6 +90,9 @@ import UIKit /// The action performed when tapped. func tapAction() { + if !isEnabled { + return + } if let radioButtonModel = radioButtonSelectionHelper { radioButtonModel.selected(self) } else { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index 4597a0b9..7bf1ff6a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -71,9 +71,6 @@ import UIKit } public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - - if radioButton.isEnabled { - radioButton.tapAction() - } + radioButton.tapAction() } } From 7e2e974f15b68c88a531da72c6c05ff140834bb9 Mon Sep 17 00:00:00 2001 From: Kruthika KP <> Date: Fri, 17 Apr 2020 13:06:19 +0530 Subject: [PATCH 060/136] changed implementation --- ...htVariablePriceChangeAllTextAndLinks.swift | 32 ++++++++++++++----- ...iablePriceChangeAllTextAndLinksModel.swift | 7 ---- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index 6d179922..7355d17c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -13,24 +13,22 @@ import Foundation //----------------------------------------------------- // MARK: - Outlets //----------------------------------------------------- - open var stack: Stack public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let rightLabel = Label.commonLabelB2(true) public let arrow = Arrow(frame: .zero) public let arrowAndLabel2Stack: Stack + let view = MVMCoreUICommonViewsUtility.commonView() //----------------------------------------------------- // MARK: - Initializers //----------------------------------------------------- public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { arrowAndLabel2Stack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .trailing)), - (view: rightLabel, model: StackItemModel(horizontalAlignment: .fill))], - axis: .horizontal, spacing: 6) + (view: rightLabel, model: StackItemModel(horizontalAlignment: .trailing))], + axis: .horizontal, spacing: 8) rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) - stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(percent: 70, horizontalAlignment: .leading)), - (view: arrowAndLabel2Stack, model: StackItemModel(percent: 30, horizontalAlignment: .fill, verticalAlignment: .top))], - axis: .horizontal) + rightLabel.numberOfLines = 1 super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -41,12 +39,30 @@ import Foundation //----------------------------------------------------- // MARK: - View Lifecycle //----------------------------------------------------- + override open func setupView() { super.setupView() - addMolecule(stack) arrow.pinHeightAndWidth() arrowAndLabel2Stack.restack() - stack.restack() + + view.addSubview(eyebrowHeadlineBodyLink) + view.addSubview(arrowAndLabel2Stack) + contentView.addSubview(view) + containerHelper.constrainView(view) + + //constraints + arrowAndLabel2Stack.leadingAnchor.constraint(equalTo: eyebrowHeadlineBodyLink.trailingAnchor, constant: PaddingTen).isActive = true + arrowAndLabel2Stack.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + arrowAndLabel2Stack.topAnchor.constraint(equalTo: view.topAnchor, constant: PaddingTwo).isActive = true + + eyebrowHeadlineBodyLink.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + eyebrowHeadlineBodyLink.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + eyebrowHeadlineBodyLink.topAnchor.constraint(equalTo: view.topAnchor).isActive = true + } + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + eyebrowHeadlineBodyLink.updateView(size) } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift index c0f749e2..c048c973 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift @@ -22,13 +22,6 @@ public class ListRightVariablePriceChangeAllTextAndLinksModel: ListItemModel, Mo super.init() } - override public func setDefaults() { - super.setDefaults() - if let headline = eyebrowHeadlineBodyLink.headline { - headline.hero = 0 - } - } - private enum CodingKeys: String, CodingKey { case moleculeName case eyebrowHeadlineBodyLink From 135bf4c073df588a41751478f2b58451edc2a5a6 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 17 Apr 2020 16:30:49 +0530 Subject: [PATCH 061/136] Code cleanup --- .../Atomic/Atoms/Selectors/RadioSwatchItem.swift | 12 ++++-------- .../RadioSwatchItemCollectionViewCell.swift | 2 +- .../Atomic/Atoms/Selectors/RadioSwatches.swift | 13 +++++++------ .../Atomic/Atoms/Selectors/RadioSwatchesModel.swift | 1 - 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift index 9117aee8..a6e6b802 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift @@ -13,7 +13,7 @@ open class RadioSwatchItem: Control { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public var bottomText = Label.createLabelRegularMicro(true) + public let bottomText = Label.createLabelRegularMicro(true) public var isOutOfStock = false public var fillColor: Color = Color(uiColor: .mvmBlue) @@ -35,19 +35,16 @@ open class RadioSwatchItem: Control { layer.setNeedsDisplay() } - public override func setupView() { + open override func setupView() { super.setupView() addSubview(bottomText) bottomText.textAlignment = .center - bottomText.topAnchor.constraint(equalTo: topAnchor, constant: 38).isActive = true - bottomText.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - bottomText.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true - bottomAnchor.constraint(equalTo: bottomText.bottomAnchor).isActive = true + NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0) addTarget(self, action: #selector(selectSwatch), for: .touchUpInside) } - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? RadioSwatchItemModel else { return } fillColor = model.color @@ -60,7 +57,6 @@ open class RadioSwatchItem: Control { //------------------------------------------------------ // MARK: - State Handling //------------------------------------------------------ - open override func draw(_ layer: CALayer, in ctx: CGContext) { //Draw the swatch circleLayer?.removeFromSuperlayer() diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift index 3d3100a8..a820a680 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift @@ -8,7 +8,7 @@ import Foundation open class RadioSwatchItemCollectionViewCell: CollectionViewCell { - let radioSwatch = RadioSwatchItem() + public let radioSwatch = RadioSwatchItem() open override func setupView() { super.setupView() diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index 2811da69..f13dd331 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -13,9 +13,9 @@ open class RadioSwatches: View { // MARK: - Properties //-------------------------------------------------- public var collectionView: CollectionView! - var swatches: [RadioSwatchItemModel]? + public var swatches: [RadioSwatchItemModel]? private var size: CGFloat? - private var delegateObject: MVMCoreUIDelegateObject? + private var delegateObject: MVMCoreUIDelegateObject? //------------------------------------------------------ // MARK: - Constraints @@ -50,7 +50,7 @@ open class RadioSwatches: View { collectionView.updateView(size) } - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject @@ -65,6 +65,7 @@ open class RadioSwatches: View { //------------------------------------------------------ // MARK: - Methods //------------------------------------------------------ + /// Registers the cells with the collection view open func registerCells() { collectionView.register(RadioSwatchItemCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") } @@ -130,17 +131,17 @@ extension RadioSwatches: UICollectionViewDataSource { } extension RadioSwatches: UICollectionViewDelegate { - public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { guard let molecule = swatches?[indexPath.row] else {return true } return molecule.enabled ?? true } - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } cell.radioSwatch.selectSwatch() _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } - public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { + open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } cell.radioSwatch.deselectSwatch() } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index 965b72f6..d422d0db 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -61,7 +61,6 @@ import Foundation public var selected: Bool? = false public var enabled: Bool? = true public var strikethrough: Bool? = false - public var fieldKey: String? public var fieldValue: String? private enum CodingKeys: String, CodingKey { From 7471d2adf68375bf6a97cd948d5e20ff4f196342 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 17 Apr 2020 19:05:01 -0400 Subject: [PATCH 062/136] Separate radio swatch model file remove item from radio swatch name add in reset function to be consistent. Fix selected color issues with outer circle Center line Move height calculations to be dynamic minor encoding updates --- MVMCoreUI.xcodeproj/project.pbxproj | 20 +++--- ...adioSwatchItem.swift => RadioSwatch.swift} | 46 +++++++------ ...ft => RadioSwatchCollectionViewCell.swift} | 8 +-- .../Atoms/Selectors/RadioSwatchModel.swift | 64 ++++++++++++++++++ .../Atoms/Selectors/RadioSwatches.swift | 36 +++++----- .../Atoms/Selectors/RadioSwatchesModel.swift | 67 ++----------------- 6 files changed, 130 insertions(+), 111 deletions(-) rename MVMCoreUI/Atomic/Atoms/Selectors/{RadioSwatchItem.swift => RadioSwatch.swift} (77%) rename MVMCoreUI/Atomic/Atoms/Selectors/{RadioSwatchItemCollectionViewCell.swift => RadioSwatchCollectionViewCell.swift} (71%) create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 077b0ca2..befe232c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -190,11 +190,11 @@ AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; - AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */; }; + AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; - AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatchItem.swift */; }; + AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; }; BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; @@ -226,6 +226,7 @@ C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; }; D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; }; + D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092348244A51D40044AD09 /* RadioSwatchModel.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; @@ -620,11 +621,11 @@ AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; - AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItemCollectionViewCell.swift; sourceTree = ""; }; + AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchItem.swift; sourceTree = ""; }; + AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = ""; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = ""; }; BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = ""; }; @@ -656,6 +657,7 @@ C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = ""; }; D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = ""; }; D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = ""; }; + D2092348244A51D40044AD09 /* RadioSwatchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchModel.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; @@ -1439,8 +1441,9 @@ 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, AAB9C10724346F4B00151545 /* RadioSwatches.swift */, - AAB9C109243496DD00151545 /* RadioSwatchItem.swift */, - AA85236B244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift */, + D2092348244A51D40044AD09 /* RadioSwatchModel.swift */, + AAB9C109243496DD00151545 /* RadioSwatch.swift */, + AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */, ); path = Selectors; sourceTree = ""; @@ -2114,7 +2117,7 @@ 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */, - AAB9C10A243496DD00151545 /* RadioSwatchItem.swift in Sources */, + AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, @@ -2219,6 +2222,7 @@ D260105D23D0BCD400764D80 /* Stack.swift in Sources */, 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */, BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */, + D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */, 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */, @@ -2333,7 +2337,7 @@ 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */, D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */, - AA85236C244435A20059CC1E /* RadioSwatchItemCollectionViewCell.swift in Sources */, + AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */, 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift similarity index 77% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift index a6e6b802..35294457 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItem.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift @@ -1,5 +1,5 @@ // -// RadioSwatchItem.swift +// RadioSwatch.swift // MVMCoreUI // // Created by Lekshmi S on 01/04/20. @@ -9,21 +9,19 @@ import Foundation import UIKit -open class RadioSwatchItem: Control { +open class RadioSwatch: Control { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public let bottomText = Label.createLabelRegularMicro(true) - public var isOutOfStock = false - public var fillColor: Color = Color(uiColor: .mvmBlue) private var circleLayer: CAShapeLayer? private var selectedLayer: CALayer? private var strikeLayer: CALayer? private var maskLayer: CALayer? - public var radioSwatchModel: RadioSwatchItemModel? { - return model as? RadioSwatchItemModel + public var radioSwatchModel: RadioSwatchModel? { + return model as? RadioSwatchModel } //-------------------------------------------------- @@ -40,18 +38,23 @@ open class RadioSwatchItem: Control { addSubview(bottomText) bottomText.textAlignment = .center - NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0) + NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0) addTarget(self, action: #selector(selectSwatch), for: .touchUpInside) } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let model = model as? RadioSwatchItemModel else { return } - fillColor = model.color - isSelected = model.selected ?? false - isEnabled = model.enabled ?? true + guard let model = model as? RadioSwatchModel else { return } + isSelected = model.selected + isEnabled = model.enabled bottomText.text = model.text - isOutOfStock = model.strikethrough ?? false + } + + public override func reset() { + super.reset() + isSelected = false + isEnabled = true + bottomText.text = nil } //------------------------------------------------------ @@ -60,14 +63,14 @@ open class RadioSwatchItem: Control { open override func draw(_ layer: CALayer, in ctx: CGContext) { //Draw the swatch circleLayer?.removeFromSuperlayer() - let circle = getCircle(color: .mvmBlack, thickness: 1) + let circle = getCircle(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1) layer.addSublayer(circle) circleLayer = circle //Draw the strikethrough strikeLayer?.removeFromSuperlayer() - if isOutOfStock { - let line = getStrikeThrough(color: .mvmBlack, thickness: 1) + if radioSwatchModel?.strikethrough ?? false { + let line = getStrikeThrough(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1) layer.addSublayer(line) strikeLayer = line } @@ -75,12 +78,11 @@ open class RadioSwatchItem: Control { //Draw the selected layer selectedLayer?.removeFromSuperlayer() if isSelected { - let outerCircle = getSelectedLayer(color: .mvmBlack, thickness: 1) + let outerCircle = getSelectedLayer(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1) layer.addSublayer(outerCircle) selectedLayer = outerCircle bottomText.isHidden = false } else { - circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)).cgPath bottomText.isHidden = true } @@ -115,10 +117,10 @@ open class RadioSwatchItem: Control { func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer { let circle = CAShapeLayer() circle.name = "innercircle" - circle.fillColor = fillColor.cgColor + circle.fillColor = radioSwatchModel?.color.cgColor ?? UIColor.blue.cgColor circle.opacity = 1.0 circle.lineWidth = thickness - circle.strokeColor = isSelected ? color.cgColor : UIColor.mvmCoolGray6.cgColor + circle.strokeColor = color.cgColor let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30)) circle.path = circlePath.cgPath @@ -131,11 +133,11 @@ open class RadioSwatchItem: Control { strikeThrough.fillColor = nil strikeThrough.opacity = 1.0 strikeThrough.lineWidth = thickness - strikeThrough.strokeColor = isSelected ? color.cgColor : UIColor.mvmCoolGray6.cgColor + strikeThrough.strokeColor = color.cgColor let linePath = UIBezierPath() - linePath.move(to: CGPoint(x: 12, y: 30)) - linePath.addLine(to: CGPoint(x: 42, y: 0)) + linePath.move(to: CGPoint(x: 12, y: 31)) + linePath.addLine(to: CGPoint(x: 42, y: 1)) strikeThrough.path = linePath.cgPath return strikeThrough } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchCollectionViewCell.swift similarity index 71% rename from MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift rename to MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchCollectionViewCell.swift index a820a680..8412dab2 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchItemCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchCollectionViewCell.swift @@ -1,5 +1,5 @@ // -// RadioSwatchItemCollectionViewCell.swift +// RadioSwatchCollectionViewCell.swift // MVMCoreUI // // Created by Lekshmi S on 13/04/20. @@ -7,8 +7,8 @@ // import Foundation -open class RadioSwatchItemCollectionViewCell: CollectionViewCell { - public let radioSwatch = RadioSwatchItem() +open class RadioSwatchCollectionViewCell: CollectionViewCell { + public let radioSwatch = RadioSwatch() open override func setupView() { super.setupView() @@ -17,7 +17,7 @@ open class RadioSwatchItemCollectionViewCell: CollectionViewCell { } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? RadioSwatchItemModel else { return } + guard let model = model as? RadioSwatchModel else { return } radioSwatch.set(with: model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift new file mode 100644 index 00000000..3aadd467 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift @@ -0,0 +1,64 @@ +// +// RadioSwatchModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/17/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class RadioSwatchModel: MoleculeModelProtocol { + public static var identifier: String = "radioSwatch" + public var backgroundColor: Color? + public var color: Color = Color(uiColor: .mvmBlue) + public var text: String? + public var selected: Bool = false + public var enabled: Bool = true + public var strikethrough: Bool = false + public var fieldValue: String? + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case color + case text + case selected + case enabled + case strikethrough + case fieldValue + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) { + self.color = color + } + text = try typeContainer.decodeIfPresent(String.self, forKey: .text) + if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { + self.selected = selected + } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { + self.strikethrough = strikethrough + } + fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(color, forKey: .color) + try container.encodeIfPresent(text, forKey: .text) + try container.encode(selected, forKey: .selected) + try container.encode(enabled, forKey: .enabled) + try container.encode(strikethrough, forKey: .strikethrough) + try container.encodeIfPresent(fieldValue, forKey: .fieldValue) + } +} + + diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift index f13dd331..8a6b8faf 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift @@ -13,7 +13,7 @@ open class RadioSwatches: View { // MARK: - Properties //-------------------------------------------------- public var collectionView: CollectionView! - public var swatches: [RadioSwatchItemModel]? + public var swatches: [RadioSwatchModel]? private var size: CGFloat? private var delegateObject: MVMCoreUIDelegateObject? @@ -30,6 +30,7 @@ open class RadioSwatches: View { open override func layoutSubviews() { super.layoutSubviews() // Accounts for any collection size changes + setHeight() DispatchQueue.main.async { self.collectionView.collectionViewLayout.invalidateLayout() } @@ -57,24 +58,18 @@ open class RadioSwatches: View { guard let radioSwatchesModel = model as? RadioSwatchesModel else { return } swatches = radioSwatchesModel.swatches FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate) - registerCells() - setHeight() collectionView.reloadData() } //------------------------------------------------------ // MARK: - Methods //------------------------------------------------------ - /// Registers the cells with the collection view - open func registerCells() { - collectionView.register(RadioSwatchItemCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchItemCollectionViewCell") - } - /// Creates the collection view. open func createCollectionView() -> CollectionView { let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) collection.dataSource = self collection.delegate = self + collection.register(RadioSwatchCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchCollectionViewCell") return collection } @@ -93,10 +88,17 @@ open class RadioSwatches: View { return } // Calculate the height - let collectionViewWidth = UIScreen.main.bounds.width - (2 * MFStyler.defaultHorizontalPaddingForApplicationWidth()) - let swatchesInRow = floor(CGFloat(collectionViewWidth/(cellSize + itemSpacing))) + let swatchesInRow = floor(CGFloat(collectionView.bounds.width/(cellSize + itemSpacing))) let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow) let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1)) + + if let oldHeight = collectionViewHeight?.constant, + height != oldHeight { + // Notify delegate of height change, called async to avoid various race conditions caused while happening while laying out initially. + DispatchQueue.main.async { + self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + } + } collectionViewHeight?.constant = CGFloat(height) } } @@ -116,13 +118,14 @@ extension RadioSwatches: UICollectionViewDataSource { } open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchItemCollectionViewCell", for: indexPath) as? RadioSwatchItemCollectionViewCell else { + guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchCollectionViewCell", for: indexPath) as? RadioSwatchCollectionViewCell else { fatalError() } + cell.reset() cell.radioSwatch.isUserInteractionEnabled = false cell.set(with: molecule, delegateObject, nil) cell.updateView(size ?? collectionView.bounds.width) - if molecule.selected ?? false { + if molecule.selected { collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically) } cell.layoutIfNeeded() @@ -132,17 +135,18 @@ extension RadioSwatches: UICollectionViewDataSource { extension RadioSwatches: UICollectionViewDelegate { open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - guard let molecule = swatches?[indexPath.row] else {return true } - return molecule.enabled ?? true + guard let molecule = swatches?[indexPath.row] else { return false } + return molecule.enabled } open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } + guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return } cell.radioSwatch.selectSwatch() _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } + open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchItemCollectionViewCell else { return } + guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return } cell.radioSwatch.deselectSwatch() } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index d422d0db..db8e5d5d 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -9,9 +9,9 @@ import Foundation @objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol { - public var backgroundColor: Color? public static var identifier: String = "radioSwatches" - public var swatches: [RadioSwatchItemModel] + public var backgroundColor: Color? + public var swatches: [RadioSwatchModel] public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? @@ -19,7 +19,7 @@ import Foundation /// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch. public func formFieldValue() -> AnyHashable? { let selectedSwatch = swatches.first { (swatch) -> Bool in - return (swatch.selected ?? false) + return swatch.selected } return selectedSwatch?.fieldValue ?? selectedSwatch?.text } @@ -34,8 +34,8 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - self.swatches = try typeContainer.decode([RadioSwatchItemModel].self, forKey: .swatches) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName @@ -49,61 +49,6 @@ import Foundation try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(swatches, forKey: .swatches) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encode(groupName, forKey: .groupName) } } - -@objcMembers public class RadioSwatchItemModel: MoleculeModelProtocol { - public var backgroundColor: Color? - public static var identifier: String = "radioSwatchItem" - public var color: Color = Color(uiColor: .mvmBlue) - public var text: String? - public var selected: Bool? = false - public var enabled: Bool? = true - public var strikethrough: Bool? = false - public var fieldValue: String? - - private enum CodingKeys: String, CodingKey { - case moleculeName - case backgroundColor - case color - case text - case selected - case enabled - case strikethrough - case fieldValue - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - color = try typeContainer.decode(Color.self, forKey: .color) - if let text = try typeContainer.decodeIfPresent(String.self, forKey: .text) { - self.text = text - } - if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { - self.selected = selected - } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } - if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { - self.strikethrough = strikethrough - } - fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encode(color, forKey: .color) - try container.encodeIfPresent(text, forKey: .text) - try container.encodeIfPresent(selected, forKey: .selected) - try container.encodeIfPresent(enabled, forKey: .enabled) - try container.encodeIfPresent(strikethrough, forKey: .strikethrough) - try container.encodeIfPresent(fieldValue, forKey: .fieldValue) - } -} - - From c89929648fceea3dc4de7f233c5d39ffc9be5d94 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Sat, 18 Apr 2020 17:45:14 -0400 Subject: [PATCH 063/136] fix centering logic --- ...htVariablePriceChangeAllTextAndLinks.swift | 31 ++++++++++++------- MVMCoreUI/BaseClasses/TableViewCell.swift | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index 7355d17c..182e2cee 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -18,13 +18,14 @@ import Foundation public let arrow = Arrow(frame: .zero) public let arrowAndLabel2Stack: Stack let view = MVMCoreUICommonViewsUtility.commonView() + public var alignmentConstraint: NSLayoutConstraint? //----------------------------------------------------- // MARK: - Initializers //----------------------------------------------------- public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - arrowAndLabel2Stack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .trailing)), - (view: rightLabel, model: StackItemModel(horizontalAlignment: .trailing))], + arrowAndLabel2Stack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center)), + (view: rightLabel, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center))], axis: .horizontal, spacing: 8) rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) @@ -40,29 +41,35 @@ import Foundation // MARK: - View Lifecycle //----------------------------------------------------- + public override func alignAccessoryToHero() { + super.alignAccessoryToHero() + + // Aligns the center of the right side to the headline. + if let heroCenter = heroAccessoryCenter { + let convertedPoint = view.convert(heroCenter, from: self) + alignmentConstraint?.constant = convertedPoint.y - view.bounds.midY + } + } + override open func setupView() { super.setupView() arrow.pinHeightAndWidth() arrowAndLabel2Stack.restack() - view.addSubview(eyebrowHeadlineBodyLink) view.addSubview(arrowAndLabel2Stack) contentView.addSubview(view) containerHelper.constrainView(view) - //constraints - arrowAndLabel2Stack.leadingAnchor.constraint(equalTo: eyebrowHeadlineBodyLink.trailingAnchor, constant: PaddingTen).isActive = true - arrowAndLabel2Stack.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true - arrowAndLabel2Stack.topAnchor.constraint(equalTo: view.topAnchor, constant: PaddingTwo).isActive = true - - eyebrowHeadlineBodyLink.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true - eyebrowHeadlineBodyLink.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true - eyebrowHeadlineBodyLink.topAnchor.constraint(equalTo: view.topAnchor).isActive = true + NSLayoutConstraint.pinViews(leftView: eyebrowHeadlineBodyLink, rightView: arrowAndLabel2Stack, alignTop: false) + alignmentConstraint = view.constraintsAffectingLayout(for: .vertical).first { (layout) -> Bool in + return layout.firstAnchor == arrowAndLabel2Stack.centerYAnchor && layout.firstAttribute == .centerY + } } public override func updateView(_ size: CGFloat) { super.updateView(size) eyebrowHeadlineBodyLink.updateView(size) + arrowAndLabel2Stack.updateView(size) } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { @@ -79,6 +86,8 @@ import Foundation open override func reset() { super.reset() + eyebrowHeadlineBodyLink.reset() + arrowAndLabel2Stack.reset() rightLabel.styleB2(true) } } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index dc4d270a..8170e402 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -26,7 +26,7 @@ import UIKit /// For subclasses that want to use a custom accessory view. open var customAccessoryView = false - private var heroAccessoryCenter: CGPoint? + public var heroAccessoryCenter: CGPoint? private var initialSetupPerformed = false From 4d7740854daef8f8072f23df00dd5c6ba380d269 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Sat, 18 Apr 2020 18:08:13 -0400 Subject: [PATCH 064/136] Simpler stack logic --- ...htVariablePriceChangeAllTextAndLinks.swift | 59 ++++++++----------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index 182e2cee..f13d9f4c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -14,22 +14,24 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) - public let rightLabel = Label.commonLabelB2(true) public let arrow = Arrow(frame: .zero) - public let arrowAndLabel2Stack: Stack - let view = MVMCoreUICommonViewsUtility.commonView() - public var alignmentConstraint: NSLayoutConstraint? + public let rightLabel = Label.commonLabelB2(true) + private let stack: Stack + private let arrowStackItem: StackItem + private let rightLabelStackItem: StackItem //----------------------------------------------------- // MARK: - Initializers //----------------------------------------------------- public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - arrowAndLabel2Stack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center)), - (view: rightLabel, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center))], - axis: .horizontal, spacing: 8) - rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) - rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) - rightLabel.numberOfLines = 1 + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), + StackItemModel(horizontalAlignment: .fill), + StackItemModel(spacing: 8, horizontalAlignment: .fill)], + axis: .horizontal) + arrowStackItem = StackItem(andContain: arrow) + rightLabelStackItem = StackItem(andContain: rightLabel) + let stackItems = [StackItem(andContain: eyebrowHeadlineBodyLink), arrowStackItem, rightLabelStackItem] + stack = Stack(with: stackModel, stackItems: stackItems) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -44,32 +46,24 @@ import Foundation public override func alignAccessoryToHero() { super.alignAccessoryToHero() - // Aligns the center of the right side to the headline. + // Aligns the center of the right side items to the headline. if let heroCenter = heroAccessoryCenter { - let convertedPoint = view.convert(heroCenter, from: self) - alignmentConstraint?.constant = convertedPoint.y - view.bounds.midY + let convertedPoint = stack.convert(heroCenter, from: self) + arrowStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY + rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY } } override open func setupView() { super.setupView() - arrow.pinHeightAndWidth() - arrowAndLabel2Stack.restack() - view.addSubview(eyebrowHeadlineBodyLink) - view.addSubview(arrowAndLabel2Stack) - contentView.addSubview(view) - containerHelper.constrainView(view) + rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.numberOfLines = 1 - NSLayoutConstraint.pinViews(leftView: eyebrowHeadlineBodyLink, rightView: arrowAndLabel2Stack, alignTop: false) - alignmentConstraint = view.constraintsAffectingLayout(for: .vertical).first { (layout) -> Bool in - return layout.firstAnchor == arrowAndLabel2Stack.centerYAnchor && layout.firstAttribute == .centerY - } - } - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - eyebrowHeadlineBodyLink.updateView(size) - arrowAndLabel2Stack.updateView(size) + arrow.pinHeightAndWidth() + + addMolecule(stack) + stack.restack() } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { @@ -83,12 +77,5 @@ import Foundation open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } - - open override func reset() { - super.reset() - eyebrowHeadlineBodyLink.reset() - arrowAndLabel2Stack.reset() - rightLabel.styleB2(true) - } } From b061952e02a8a20a0a96fdd23327d4649c0df1be Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Sat, 18 Apr 2020 18:10:51 -0400 Subject: [PATCH 065/136] organize --- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 0457a23d..3fb78647 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -142,6 +142,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self) @@ -149,7 +150,6 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self) // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) From 9cff0f15f7bacca7951f0bee3d22f7336cde8b04 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Sat, 18 Apr 2020 19:09:19 -0400 Subject: [PATCH 066/136] hero fixes headlineBody update instead of eyebrowheadlinebody --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +-- ...htVariablePriceChangeAllTextAndLinks.swift | 13 ++++----- ...iablePriceChangeAllTextAndLinksModel.swift | 1 - ...ListRightVariablePriceChangeBodyText.swift | 27 ++++++++++++------- ...ightVariablePriceChangeBodyTextModel.swift | 20 +++++++++----- MVMCoreUI/BaseClasses/TableViewCell.swift | 12 +++++---- 6 files changed, 47 insertions(+), 30 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 227863dc..00550bbe 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -1103,8 +1103,6 @@ AA4FC2A323F4F69600E251DB /* RightVariable */ = { isa = PBXGroup; children = ( - BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */, - BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */, BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */, BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */, BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */, @@ -1113,6 +1111,8 @@ AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */, 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */, + BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */, + BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */, 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */, 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */, C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index f13d9f4c..7a74de6e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class ListRightVariablePriceChangeAllTextAndLinks: TableViewCell { +@objcMembers open class ListRightVariablePriceChangeAllTextAndLinks: TableViewCell { //----------------------------------------------------- // MARK: - Outlets @@ -26,7 +26,7 @@ import Foundation public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), StackItemModel(horizontalAlignment: .fill), - StackItemModel(spacing: 8, horizontalAlignment: .fill)], + StackItemModel(spacing: 6, horizontalAlignment: .fill)], axis: .horizontal) arrowStackItem = StackItem(andContain: arrow) rightLabelStackItem = StackItem(andContain: rightLabel) @@ -43,18 +43,19 @@ import Foundation // MARK: - View Lifecycle //----------------------------------------------------- - public override func alignAccessoryToHero() { - super.alignAccessoryToHero() + open override func alignAccessoryToHero() -> CGPoint? { + let heroCenter = super.alignAccessoryToHero() // Aligns the center of the right side items to the headline. - if let heroCenter = heroAccessoryCenter { + if let heroCenter = heroCenter { let convertedPoint = stack.convert(heroCenter, from: self) arrowStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY } + return heroCenter } - override open func setupView() { + open override func setupView() { super.setupView() rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift index c048c973..ae4be269 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinksModel.swift @@ -9,7 +9,6 @@ import Foundation public class ListRightVariablePriceChangeAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { - public static var identifier: String = "listRVArwAll" public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel public var rightLabel: LabelModel diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index c62a7eaf..2b87294a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -12,19 +12,20 @@ import Foundation //----------------------------------------------------- // MARK: - Outlets //----------------------------------------------------- - public var stack: Stack - public let headlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) - public let rightLabel = Label.commonLabelB2(true) + private let stack: Stack + public let headlineBody = HeadlineBody(frame: .zero) public let arrow = Arrow(frame: .zero) + public let rightLabel = Label.commonLabelB2(true) let arrowAndRightLabelStack: Stack + // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { arrowAndRightLabelStack = Stack.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)), - (view: rightLabel, model: StackItemModel(horizontalAlignment: .leading))], + (view: rightLabel, model: StackItemModel(horizontalAlignment: .fill))], axis: .horizontal, spacing: 6) - stack = Stack.createStack(with: [(view: headlineBodyLink, model: StackItemModel(percent:70,horizontalAlignment: .leading)), - (view: arrowAndRightLabelStack, model: StackItemModel(percent:30,horizontalAlignment: .trailing,verticalAlignment: .top))], + stack = Stack.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .leading)), + (view: arrowAndRightLabelStack, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading))], axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -36,8 +37,14 @@ import Foundation //----------------------------------------------------- // MARK: - View Lifecycle //----------------------------------------------------- - override open func setupView() { + open override func setupView() { super.setupView() + headlineBody.styleListItem() + + rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.numberOfLines = 1 + arrow.pinHeightAndWidth() addMolecule(stack) stack.restack() @@ -47,17 +54,17 @@ import Foundation open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? ListRightVariablePriceChangeBodyTextModel else { return } - headlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) rightLabel.set(with: model.rightLabel, delegateObject, additionalData) arrow.set(with: model.arrow, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 120 + return 80 } open override func reset() { super.reset() - rightLabel.styleB2(true) + headlineBody.styleListItem() } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift index e2d90eb7..7bf118df 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyTextModel.swift @@ -9,27 +9,35 @@ import Foundation public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listRVArwBdy" - public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + public var headlineBody: HeadlineBodyModel public var rightLabel: LabelModel public var arrow: ArrowModel - public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel,rightLabel: LabelModel,arrow: ArrowModel) { - self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + public init(headlineBody: HeadlineBodyModel,rightLabel: LabelModel,arrow: ArrowModel) { + self.headlineBody = headlineBody self.rightLabel = rightLabel self.arrow = arrow super.init() } + /// Defaults to set + public override func setDefaults() { + super.setDefaults() + if let headline = headlineBody.headline { + headline.hero = 0 + } + } + private enum CodingKeys: String, CodingKey { case moleculeName - case eyebrowHeadlineBodyLink + case headlineBody case rightLabel case arrow } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) + headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow) try super.init(from: decoder) @@ -39,7 +47,7 @@ public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeM try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + try container.encode(headlineBody, forKey: .headlineBody) try container.encode(rightLabel, forKey: .rightLabel) try container.encode(arrow, forKey: .arrow) } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index 8170e402..f27a38d8 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -97,7 +97,7 @@ import UIKit // Ensures accessory view aligns to the center y derived from the if let _ = heroAccessoryCenter { - alignAccessoryToHero() + _ = alignAccessoryToHero() } } @@ -215,14 +215,16 @@ import UIKit } /// NOTE: Should only be called when displayed or about to be displayed. - public func alignAccessoryToHero() { + public func alignAccessoryToHero() -> CGPoint? { // Layout call required to force draw in memory to get dimensions of subviews. layoutIfNeeded() - guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } + guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return nil } let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) - accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y + let y = convert(UIView(frame: rect).center, from: heroLabel).y + accessoryView?.center.y = y heroAccessoryCenter = accessoryView?.center + return heroAccessoryCenter ?? CGPoint(x: 0, y: y) } /// Traverses the view hierarchy for a 🦸‍♂️ heroic Label. @@ -269,7 +271,7 @@ import UIKit } public func willDisplay() { - alignAccessoryToHero() + _ = alignAccessoryToHero() } // MARK: - Separator From 0bfd72f38443110bba60b41fbfc37cbc87abcbae Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Sat, 18 Apr 2020 19:10:15 -0400 Subject: [PATCH 067/136] recorder --- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 3aff695d..bebdd424 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -139,11 +139,10 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self) From e7272d311b297cb0d8677f442eb3aeec0950844c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Sat, 18 Apr 2020 19:22:53 -0400 Subject: [PATCH 068/136] hero update, reorganize --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++---- .../LeftVariable/ListLeftVariableCheckboxBodyText.swift | 2 +- .../ListLeftVariableCheckboxBodyTextModel.swift | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 37d39323..767e9f32 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -192,9 +192,9 @@ AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; - AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; }; AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */; }; + AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; @@ -629,9 +629,9 @@ AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; - AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = ""; }; + AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; @@ -1369,14 +1369,14 @@ children = ( 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */, 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */, + AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */, + AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */, 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, 0A6682A32434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift */, 0A6682A12434DB4F00AD3CA1 /* ListLeftVariableRadioButtonBodyText.swift */, - AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */, - AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */, ); path = LeftVariable; sourceTree = ""; diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift index ed9e84df..e1f823ce 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyText.swift @@ -44,7 +44,7 @@ import Foundation //---------------------------------------------------- open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.set(with: model, delegateObject, additionalData) - guard let model = model as? ListLeftVariableCheckboxBodyTextModel else { return} + guard let model = model as? ListLeftVariableCheckboxBodyTextModel else { return } checkbox.set(with: model.checkbox, delegateObject, additionalData) headlineBody.set(with: model.headlineBody, delegateObject, additionalData) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift index 5ee50501..f6fb19fc 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxBodyTextModel.swift @@ -28,6 +28,9 @@ open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelPr open override func setDefaults() { super.setDefaults() headlineBody.style = .item + if let headline = headlineBody.headline { + headline.hero = 0 + } } //-------------------------------------------------- From d5a27fa98d97e192d1fd7ea62f3869605de9185f Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Mon, 20 Apr 2020 12:34:37 +0530 Subject: [PATCH 069/136] fix for CXTDT_74295 --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 956c2afc..5018c42b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -62,7 +62,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) didSet { isUserInteractionEnabled = isEnabled changeStateNoAnimation(isEnabled ? isOn : false) - backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container + backgroundColor = isEnabled ? isOn ? containerTintColor?.on : containerTintColor?.off : disabledTintColor?.container knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob } } From 56c901a993c56866e199a8b07677da5ec1ce3b45 Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Mon, 20 Apr 2020 18:36:17 +0530 Subject: [PATCH 070/136] update parentheses --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 5018c42b..0932791a 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -62,7 +62,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) didSet { isUserInteractionEnabled = isEnabled changeStateNoAnimation(isEnabled ? isOn : false) - backgroundColor = isEnabled ? isOn ? containerTintColor?.on : containerTintColor?.off : disabledTintColor?.container + backgroundColor = isEnabled ? (isOn ? containerTintColor?.on : containerTintColor?.off) : disabledTintColor?.container knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob } } From 9c59ff13ab5339d95f035776d757304511493b35 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 09:54:42 -0400 Subject: [PATCH 071/136] toggle changes --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 40 +++++++--------- .../Atomic/Atoms/Views/ToggleModel.swift | 46 +++++++++++++------ 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 0932791a..cf272129 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool) //-------------------------------------------------- /// Holds the on and off colors for the container. - public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmGreen, off: .mvmBlack) + public var containerTintColor: (on: UIColor, off: UIColor)? = (on: .mvmGreen, off: .mvmBlack) /// Holds the on and off colors for the knob. - public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmWhite, off: .mvmWhite) + public var knobTintColor: (on: UIColor, off: UIColor)? = (on: .mvmWhite, off: .mvmWhite) /// Holds the on and off colors for the disabled state.. - public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mvmCoolGray3, knob: .mvmWhite) + public var disabledTintColor: (container: UIColor, knob: UIColor)? = (container: .mvmCoolGray3, knob: .mvmWhite) /// Set this flag to false if you do not want to animate state changes. public var isAnimated = true @@ -63,7 +63,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) isUserInteractionEnabled = isEnabled changeStateNoAnimation(isEnabled ? isOn : false) backgroundColor = isEnabled ? (isOn ? containerTintColor?.on : containerTintColor?.off) : disabledTintColor?.container - knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob + knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor?.on : knobTintColor?.off) : disabledTintColor?.knob } } @@ -101,7 +101,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) self.constrainKnob() } - (model as? ToggleModel)?.state = isOn + toggleModel?.state = isOn _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") setNeedsLayout() @@ -109,6 +109,10 @@ public typealias ActionBlockConfirmation = () -> (Bool) } } + public var toggleModel: ToggleModel? { + return model as? ToggleModel + } + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -189,7 +193,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override func setupView() { super.setupView() - guard subviews.isEmpty else { return } + isAccessibilityElement = true accessibilityTraits = .button accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint") @@ -224,7 +228,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) backgroundColor = containerTintColor?.off knobView.backgroundColor = knobTintColor?.off - isAnimated = false + isAnimated = true isOn = false constrainKnob() didToggleAction = nil @@ -344,26 +348,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - if let color = model.onTintColor?.uiColor { - containerTintColor?.on = color - } - - if let color = model.offTintColor?.uiColor { - containerTintColor?.off = color - } - - if let color = model.onKnobTintColor?.uiColor { - knobTintColor?.on = color - } - - if let color = model.offKnobTintColor?.uiColor { - knobTintColor?.off = color - } - + containerTintColor?.on = model.onTintColor.uiColor + containerTintColor?.off = model.offTintColor.uiColor + knobTintColor?.on = model.onKnobTintColor.uiColor + knobTintColor?.off = model.offKnobTintColor.uiColor changeStateNoAnimation(model.state) isAnimated = model.animated isEnabled = model.enabled - + if let actionMap = model.action?.toJSON() { didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift index 9eb2f4b5..b39003d2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift @@ -8,8 +8,12 @@ import UIKit -public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol { +public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "toggle" public var backgroundColor: Color? public var state: Bool = false @@ -18,10 +22,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo public var action: ActionModelProtocol? public var alternateAction: ActionModelProtocol? public var accessibilityText: String? - public var onTintColor: Color? - public var offTintColor: Color? - public var onKnobTintColor: Color? - public var offKnobTintColor: Color? + public var onTintColor: Color = Color(uiColor: .mvmGreen) + public var offTintColor: Color = Color(uiColor: .mvmBlack) + public var onKnobTintColor: Color = Color(uiColor: .mvmWhite) + public var offKnobTintColor: Color = Color(uiColor: .mvmWhite) public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName @@ -75,19 +79,35 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.state = state } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } + if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) { self.animated = animated } + action = try typeContainer.decodeModelIfPresent(codingKey: .action) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) - offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) - onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) - offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) + + if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) { + self.onTintColor = onTintColor + } + + if let offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) { + self.offTintColor = offTintColor + } + + if let onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) { + self.onKnobTintColor = onKnobTintColor + } + + if let offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) { + self.offKnobTintColor = offKnobTintColor + } + accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) baseValue = state @@ -106,10 +126,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo try container.encode(state, forKey: .state) try container.encode(animated, forKey: .animated) try container.encode(enabled, forKey: .enabled) - try container.encodeIfPresent(onTintColor, forKey: .onTintColor) - try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) - try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) - try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor) + try container.encode(onTintColor, forKey: .onTintColor) + try container.encode(onKnobTintColor, forKey: .onKnobTintColor) + try container.encode(onKnobTintColor, forKey: .onKnobTintColor) + try container.encode(offKnobTintColor, forKey: .offKnobTintColor) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) From be29a5dfbcd5ee5a740340c53149c37d7613b81b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 09:59:02 -0400 Subject: [PATCH 072/136] removed unneded optional wrapper --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index cf272129..75e9675a 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool) //-------------------------------------------------- /// Holds the on and off colors for the container. - public var containerTintColor: (on: UIColor, off: UIColor)? = (on: .mvmGreen, off: .mvmBlack) + public var containerTintColor: (on: UIColor, off: UIColor) = (on: .mvmGreen, off: .mvmBlack) /// Holds the on and off colors for the knob. - public var knobTintColor: (on: UIColor, off: UIColor)? = (on: .mvmWhite, off: .mvmWhite) + public var knobTintColor: (on: UIColor, off: UIColor) = (on: .mvmWhite, off: .mvmWhite) /// Holds the on and off colors for the disabled state.. - public var disabledTintColor: (container: UIColor, knob: UIColor)? = (container: .mvmCoolGray3, knob: .mvmWhite) + public var disabledTintColor: (container: UIColor, knob: UIColor) = (container: .mvmCoolGray3, knob: .mvmWhite) /// Set this flag to false if you do not want to animate state changes. public var isAnimated = true @@ -62,8 +62,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) didSet { isUserInteractionEnabled = isEnabled changeStateNoAnimation(isEnabled ? isOn : false) - backgroundColor = isEnabled ? (isOn ? containerTintColor?.on : containerTintColor?.off) : disabledTintColor?.container - knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor?.on : knobTintColor?.off) : disabledTintColor?.knob + backgroundColor = isEnabled ? (isOn ? containerTintColor.on : containerTintColor.off) : disabledTintColor.container + knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor.on : knobTintColor.off) : disabledTintColor.knob } } @@ -80,12 +80,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) if isAnimated { UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: { if self.isOn { - self.knobView.backgroundColor = self.knobTintColor?.on - self.backgroundColor = self.containerTintColor?.on + self.knobView.backgroundColor = self.knobTintColor.on + self.backgroundColor = self.containerTintColor.on } else { - self.knobView.backgroundColor = self.knobTintColor?.off - self.backgroundColor = self.containerTintColor?.off + self.knobView.backgroundColor = self.knobTintColor.off + self.backgroundColor = self.containerTintColor.off } }, completion: nil) @@ -96,8 +96,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) }, completion: nil) } else { - backgroundColor = isOn ? containerTintColor?.on : containerTintColor?.off - knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off + backgroundColor = isOn ? containerTintColor.on : containerTintColor.off + knobView.backgroundColor = isOn ? knobTintColor.on : knobTintColor.off self.constrainKnob() } @@ -206,7 +206,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) widthConstraint?.isActive = true layer.cornerRadius = Self.containerSize.height / 2.0 - backgroundColor = containerTintColor?.off + backgroundColor = containerTintColor.off addSubview(knobView) @@ -226,8 +226,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override func reset() { super.reset() - backgroundColor = containerTintColor?.off - knobView.backgroundColor = knobTintColor?.off + backgroundColor = containerTintColor.off + knobView.backgroundColor = knobTintColor.off isAnimated = true isOn = false constrainKnob() @@ -348,10 +348,10 @@ public typealias ActionBlockConfirmation = () -> (Bool) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - containerTintColor?.on = model.onTintColor.uiColor - containerTintColor?.off = model.offTintColor.uiColor - knobTintColor?.on = model.onKnobTintColor.uiColor - knobTintColor?.off = model.offKnobTintColor.uiColor + containerTintColor.on = model.onTintColor.uiColor + containerTintColor.off = model.offTintColor.uiColor + knobTintColor.on = model.onKnobTintColor.uiColor + knobTintColor.off = model.offKnobTintColor.uiColor changeStateNoAnimation(model.state) isAnimated = model.animated isEnabled = model.enabled From ac8de65e24f4f54659855e4baba86da6c8020724 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 13:07:37 -0400 Subject: [PATCH 073/136] changes to improve --- .../Atoms/Views/LeftRightLabelView.swift | 101 ++++++++++-------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift index a7c59cd3..1147e013 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift @@ -14,8 +14,8 @@ import Foundation // MARK: - Outlets //------------------------------------------------------ - let leftTextLabel = Label.commonLabelB1(true) - let rightTextLabel = Label.commonLabelB1(true) + let leftTextLabel = Label.createLabelBoldBodySmall(true) + let rightTextLabel = Label.createLabelBoldBodySmall(true) //------------------------------------------------------ // MARK: - Constraints @@ -23,6 +23,33 @@ import Foundation var rightTextLabelLeading: NSLayoutConstraint? var leftTextLabelTrailing: NSLayoutConstraint? + var rightTextLabelTrailing: NSLayoutConstraint? + + private func constrainLeftLabelOnly() { + + deactivateMiddleConstraint() + leftTextLabelTrailing?.isActive = false + leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor) + leftTextLabelTrailing?.isActive = true + } + + private func constrainRightLabelOnly() { + + deactivateMiddleConstraint() + rightTextLabelLeading?.isActive = false + rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) + rightTextLabelLeading?.isActive = true + + rightTextLabelTrailing?.isActive = false + rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) + rightTextLabelTrailing?.isActive = true + } + + private func deactivateMiddleConstraint() { + + leftTextLabelTrailing?.isActive = false + rightTextLabelLeading?.isActive = false + } //------------------------------------------------------ // MARK: - Initialization @@ -43,8 +70,6 @@ import Foundation override open func setupView() { super.setupView() - guard subviews.isEmpty else { return } - addSubview(leftTextLabel) addSubview(rightTextLabel) @@ -67,7 +92,7 @@ import Foundation // Resolves text layout issues found between both dynamically sized labels, number is not exact but performs as required. if leftTextLabel.hasText && rightTextLabel.hasText { let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2 - let maximumTextWidth = (size - (padding + 16)) * 0.4 + let maximumTextWidth = (size - (padding + Padding.Four)) * 0.4 // Subtracting 10 resolves issues of SE and iPad rightTextLabel.preferredMaxLayoutWidth = round(maximumTextWidth) - 10 } else { @@ -84,57 +109,39 @@ import Foundation leftTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true leftTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true - let leftTextBottom = leftTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor) + let leftTextBottom = bottomAnchor.constraint(equalTo: leftTextLabel.bottomAnchor) leftTextBottom.priority = UILayoutPriority(249) leftTextBottom.isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: leftTextLabel.bottomAnchor).isActive = true - rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: 16) + rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: Padding.Four) rightTextLabelLeading?.isActive = true rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true - let rightLayout = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) - rightLayout.priority = UILayoutPriority(rawValue: 995) - rightLayout.isActive = true - let rightTextBottom = rightTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor) + rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) + rightTextLabelTrailing?.priority = UILayoutPriority(rawValue: 999) + rightTextLabelTrailing?.isActive = true + + let rightTextBottom = bottomAnchor.constraint(equalTo: rightTextLabel.bottomAnchor) rightTextBottom.priority = UILayoutPriority(rawValue: 249) rightTextBottom.isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: rightTextLabel.bottomAnchor).isActive = true - let leftTextWidth = leftTextLabel.widthAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6) + let leftTextWidth = leftTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6) leftTextWidth.priority = UILayoutPriority(rawValue: 995) leftTextWidth.isActive = true - let rightTextWidth = rightTextLabel.widthAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4) - rightTextWidth.priority = UILayoutPriority(rawValue: 906) + let rightTextWidth = rightTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4) + rightTextWidth.priority = UILayoutPriority(rawValue: 995) rightTextWidth.isActive = true - leftTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) - rightTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) - - leftTextLabel.setContentHuggingPriority(.required, for: .vertical) - rightTextLabel.setContentHuggingPriority(.required, for: .vertical) - + rightTextLabel.setContentHuggingPriority(.required, for: .horizontal) leftTextLabel.setContentCompressionResistancePriority(.required, for: .vertical) rightTextLabel.setContentCompressionResistancePriority(.required, for: .vertical) - rightTextLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 902), for: .horizontal) - } - - private func constrainLeftLabel() { - - deactivateMiddleConstraint() - leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor) - leftTextLabelTrailing?.isActive = true - } - - private func constrainRightLabel() { - - deactivateMiddleConstraint() - rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) - rightTextLabelLeading?.isActive = true + rightTextLabel.setContentCompressionResistancePriority(.required, for: .horizontal) } override open func reset() { @@ -144,31 +151,31 @@ import Foundation constrainBothLabels() leftTextLabel.text = "" rightTextLabel.text = "" + leftTextLabel.textAlignment = .left + rightTextLabel.textAlignment = .right backgroundColor = nil } - private func deactivateMiddleConstraint() { - - leftTextLabelTrailing?.isActive = false - rightTextLabelLeading?.isActive = false - } - //------------------------------------------------------ // MARK: - Atomization //------------------------------------------------------ open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let leftRightLabelModel = model as? LeftRightLabelModel else { - return - } + + guard let leftRightLabelModel = model as? LeftRightLabelModel else { return } + leftTextLabel.set(with: leftRightLabelModel.leftText, delegateObject, additionalData) rightTextLabel.setOptional(with: leftRightLabelModel.rightText, delegateObject, additionalData) - + + // Label defaults to .left if no textAlignment value is provided in model. + rightTextLabel.textAlignment = leftRightLabelModel.rightText?.textAlignment ?? .right + if !leftTextLabel.hasText { - constrainRightLabel() + constrainRightLabelOnly() + } else if !rightTextLabel.hasText { - constrainLeftLabel() + constrainLeftLabelOnly() } } } From 3320819b3708b4b97fd5c9e307113f6d966446b9 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 13:23:37 -0400 Subject: [PATCH 074/136] required now works due to changes --- MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift index 1147e013..c26307f2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift @@ -121,7 +121,7 @@ import Foundation rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) - rightTextLabelTrailing?.priority = UILayoutPriority(rawValue: 999) + rightTextLabelTrailing?.priority = .required rightTextLabelTrailing?.isActive = true let rightTextBottom = bottomAnchor.constraint(equalTo: rightTextLabel.bottomAnchor) From 0461ead97434ab1c627274e5cde85ec2bb017024 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 13:25:15 -0400 Subject: [PATCH 075/136] required --- MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift index c26307f2..6ed56187 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift @@ -121,7 +121,6 @@ import Foundation rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) - rightTextLabelTrailing?.priority = .required rightTextLabelTrailing?.isActive = true let rightTextBottom = bottomAnchor.constraint(equalTo: rightTextLabel.bottomAnchor) From 193105ea29279a9571f065ed1587fb4e15342e35 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 13:27:12 -0400 Subject: [PATCH 076/136] not needed --- MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift index 6ed56187..a7d85f86 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift @@ -39,10 +39,6 @@ import Foundation rightTextLabelLeading?.isActive = false rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) rightTextLabelLeading?.isActive = true - - rightTextLabelTrailing?.isActive = false - rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor) - rightTextLabelTrailing?.isActive = true } private func deactivateMiddleConstraint() { From 6b02d04866d695d00ee3b973eeb72668e1599c55 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 14:20:34 -0400 Subject: [PATCH 077/136] remove title --- MVMCoreUI/Actions/ActionCollapseNotificationModel.swift | 1 - MVMCoreUI/Actions/ActionOpenPanelModel.swift | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift index a305436b..581c8687 100644 --- a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift +++ b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift @@ -9,7 +9,6 @@ import UIKit @objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol { - public var title: String? public static var identifier: String = "collapseNotification" public var actionType: String diff --git a/MVMCoreUI/Actions/ActionOpenPanelModel.swift b/MVMCoreUI/Actions/ActionOpenPanelModel.swift index 4e2c26bf..9149b32b 100644 --- a/MVMCoreUI/Actions/ActionOpenPanelModel.swift +++ b/MVMCoreUI/Actions/ActionOpenPanelModel.swift @@ -9,9 +9,7 @@ import Foundation public class ActionOpenPanelModel: ActionModelProtocol { - public var title: String? - - + public enum Panel: String, Codable { case left case right From 8c662a0992f21d0a5410b89fd05ef49260d3acb7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 14:22:54 -0400 Subject: [PATCH 078/136] remove title --- MVMCoreUI/Actions/ActionTopAlertModel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Actions/ActionTopAlertModel.swift b/MVMCoreUI/Actions/ActionTopAlertModel.swift index dbcf6371..82d9fa17 100644 --- a/MVMCoreUI/Actions/ActionTopAlertModel.swift +++ b/MVMCoreUI/Actions/ActionTopAlertModel.swift @@ -9,7 +9,6 @@ import Foundation @objcMembers public class ActionTopAlertModel: ActionModelProtocol { - public var title: String? public static var identifier: String = "topAlert" public var actionType: String = ActionTopAlertModel.identifier From 11d1515a46ba3c8a9378ce3f4da24960f75b9ccc Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 14:34:55 -0400 Subject: [PATCH 079/136] path based on delegate existence --- .../Atomic/Atoms/TextFields/DigitEntryField.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index aff5ec75..5fa17417 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -335,8 +335,14 @@ import UIKit } for digitBox in digitBoxes { - digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self, - action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + + if let observingTextFieldelegate = delegateObject?.observingTextFieldDelegate { + digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldelegate, + action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + } else { + digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: self, + action: #selector(dismissFieldInput)) + } } super.set(with: model, delegateObject, additionalData) From 554be6cc671e2a2bb3ad047a18bcec5186a091a6 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 14:35:47 -0400 Subject: [PATCH 080/136] path based on delegate existence --- MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 5fa17417..977447ff 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -338,7 +338,7 @@ import UIKit if let observingTextFieldelegate = delegateObject?.observingTextFieldDelegate { digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldelegate, - action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + action: #selector(observingTextFieldelegate.dismissFieldInput)) } else { digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: self, action: #selector(dismissFieldInput)) From 7c22229c2b5d6b0216a13b88d17e3c16d8af8e85 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 14:42:42 -0400 Subject: [PATCH 081/136] path based on delegate existence --- .../Atoms/TextFields/DigitEntryField.swift | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 977447ff..01305a95 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -334,17 +334,13 @@ import UIKit setAsSecureTextEntry(entryType == .secure || entryType == .password) } - for digitBox in digitBoxes { - - if let observingTextFieldelegate = delegateObject?.observingTextFieldDelegate { - digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldelegate, - action: #selector(observingTextFieldelegate.dismissFieldInput)) - } else { - digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: self, - action: #selector(dismissFieldInput)) - } - } + let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self + digitBoxes.forEach { + $0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, + action: #selector(observingDelegate.dismissFieldInput)) + } + super.set(with: model, delegateObject, additionalData) } From 1437bc60180f3b0442e28680a919b578bce1b290 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 14:47:50 -0400 Subject: [PATCH 082/136] path based on delegate existence --- MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 01305a95..8ae4365f 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -211,8 +211,9 @@ import UIKit let digitBox = DigitBox() digitBox.isAccessibilityElement = true - digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self, - action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self + digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, + action: #selector(observingDelegate.dismissFieldInput)) digitBox.digitField.delegate = self digitBox.digitBoxDelegate = self return digitBox From c8f0341e4c9bdb3fed9f45efdf60257c337e2530 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 15:54:27 -0400 Subject: [PATCH 083/136] bringing back groupname --- MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index d6b7e279..4e9cfb7e 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -93,6 +93,9 @@ import Foundation text = try typeContainer.decodeIfPresent(String.self, forKey: .text) baseValue = text fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } } public func encode(to encoder: Encoder) throws { From c8b4eaac067a3e10a196da77937e564f21bef8f4 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 16:26:42 -0400 Subject: [PATCH 084/136] moved code. changed options --- MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift | 4 ++-- .../Atoms/TextFields/ItemDropdownEntryFieldModel.swift | 4 +--- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 6 +++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 4e9cfb7e..337d847d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -105,11 +105,11 @@ import Foundation try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(text, forKey: .text) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(groupName, forKey: .groupName) 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(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index 8554244b..ac7fbab1 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -35,9 +35,7 @@ try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - if let options = try typeContainer.decodeIfPresent([String].self, forKey: .options) { - self.options = options - } + options = try typeContainer.decode([String].self, forKey: .options) if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { self.selectedIndex = selectedIndex diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 0abf4b93..f95c918d 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -214,9 +214,9 @@ import UIKit } open func setupTextFieldToolbar() { - - textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self, - action: #selector(observingTextFieldDelegate?.dismissFieldInput)) + let observingDelegate = observingTextFieldDelegate ?? self + textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, + action: #selector(observingDelegate.dismissFieldInput)) } //-------------------------------------------------- From 81cef4fdf15edf5a6ad30a67a0faaa59f65b0bed Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 17:24:18 -0400 Subject: [PATCH 085/136] beginning changes --- .../ToggleMolecules/LabelToggle.swift | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift index 9ce24d3b..17a645ed 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift @@ -9,10 +9,17 @@ import UIKit @objcMembers open class LabelToggle: View { - public let label = Label.commonLabelB1(true) + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public let label = Label.createLabelBoldBodySmall(true) public let toggle = Toggle() + //-------------------------------------------------- // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open override func updateView(_ size: CGFloat) { super.updateView(size) label.updateView(size) @@ -21,17 +28,13 @@ import UIKit open override func setupView() { super.setupView() - guard toggle.superview == nil else { - return - } addSubview(label) addSubview(toggle) - label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + label.setContentHuggingPriority(.required, for: .vertical) NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false) } - // MARK:- MoleculeViewProtocol open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { guard let model = model as? LabelToggleModel, let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject), @@ -40,9 +43,9 @@ import UIKit } 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) toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData) } @@ -52,6 +55,6 @@ import UIKit super.reset() label.reset() toggle.reset() - label.styleB1(true) + label.styleBoldBodySmall(true) } } From 82c7b372c94eb638e0ddfd8e9e7e8f07f0ed1237 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 17:36:16 -0400 Subject: [PATCH 086/136] latest --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 30 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 75e9675a..c14e20fc 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -131,8 +131,31 @@ public typealias ActionBlockConfirmation = () -> (Bool) private var widthConstraint: NSLayoutConstraint? private func constrainKnob() { - knobLeadingConstraint?.isActive = !isOn - knobTrailingConstraint?.isActive = isOn + + knobLeadingConstraint?.isActive = false + knobTrailingConstraint?.isActive = false + + if isOn { + constrainKnobOn() + + } else { + 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) } //-------------------------------------------------- @@ -218,8 +241,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true - knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1) - knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) + constrainKnobOff() knobLeadingConstraint?.isActive = true } From d8d691f2cc5267f0b0725b2b7b5eea84896896e1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 17:46:50 -0400 Subject: [PATCH 087/136] resolvong a constraint issue --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 8 +------- .../LeftRightViews/ToggleMolecules/LabelToggle.swift | 5 ++++- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index c14e20fc..eab07e0f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -135,12 +135,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) knobLeadingConstraint?.isActive = false knobTrailingConstraint?.isActive = false - if isOn { - constrainKnobOn() - - } else { - constrainKnobOff() - } + _ = isOn ? constrainKnobOn() : constrainKnobOff() knobTrailingConstraint?.isActive = true knobLeadingConstraint?.isActive = true @@ -242,7 +237,6 @@ public typealias ActionBlockConfirmation = () -> (Bool) bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true constrainKnobOff() - knobLeadingConstraint?.isActive = true } public override func reset() { diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift index 17a645ed..3ff3a41f 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift @@ -8,6 +8,7 @@ import UIKit + @objcMembers open class LabelToggle: View { //-------------------------------------------------- // MARK: - Properties @@ -38,7 +39,9 @@ import UIKit open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { guard let model = model as? LabelToggleModel, 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) } From 630c51d83b9c57bce434eede900f069a5772e8cb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 17:57:59 -0400 Subject: [PATCH 088/136] changes for refrsh --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index eab07e0f..8efd0a3c 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -207,6 +207,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) layer.cornerRadius = Self.getContainerHeight() / 2.0 knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0 + + changeStateNoAnimation(isOn) } public override func setupView() { @@ -245,8 +247,6 @@ public typealias ActionBlockConfirmation = () -> (Bool) backgroundColor = containerTintColor.off knobView.backgroundColor = knobTintColor.off isAnimated = true - isOn = false - constrainKnob() didToggleAction = nil shouldToggleAction = { return true } } @@ -368,7 +368,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) containerTintColor.off = model.offTintColor.uiColor knobTintColor.on = model.onKnobTintColor.uiColor knobTintColor.off = model.offKnobTintColor.uiColor - changeStateNoAnimation(model.state) + isOn = model.state + changeStateNoAnimation(isOn) isAnimated = model.animated isEnabled = model.enabled From 5f17e909217ac125cc3655040c9453963c6c8744 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 20 Apr 2020 18:28:03 -0400 Subject: [PATCH 089/136] code compression --- MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift index 49826504..cad763a6 100644 --- a/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift @@ -40,10 +40,7 @@ public extension UIToolbar { class func addDismissToolbar(to object: TextFieldOrView, delegate: Any?, action: Selector) { - let toolbar = createEmptyToolbar() - let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action) - toolbar.items = [space, dismissButton] + let toolbar = Self.getToolbarWithDoneButton(delegate: delegate, action: action) switch object { case is UITextField: From e5a5415dd3a8ac26804db152404794acd916e24e Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Tue, 21 Apr 2020 11:06:25 +0530 Subject: [PATCH 090/136] initial commi --- MVMCoreUI.xcodeproj/project.pbxproj | 12 ++- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 4 + .../List/ListDeviceComplexButtonMedium.swift | 72 ++++++++++++++++++ .../ListDeviceComplexButtonMediumModel.swift | 75 +++++++++++++++++++ 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index fe06c483..64c9ff42 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -151,7 +151,7 @@ 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; }; 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; }; - 943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; }; + 943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; }; 94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.swift */; }; 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; }; @@ -199,6 +199,8 @@ AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; + 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 */; }; BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; @@ -635,6 +637,8 @@ AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = ""; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; + BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; + BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = ""; }; BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = ""; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = ""; }; @@ -1351,6 +1355,8 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( + BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */, + BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */, 52267A0523FFE0A900906CBA /* OneColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */, 8DD1E36C243B3CD900D8F2DF /* ThreeColumn */, @@ -2149,6 +2155,7 @@ D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */, + BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */, 014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */, @@ -2197,7 +2204,7 @@ D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */, - EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, + EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, @@ -2392,6 +2399,7 @@ D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, + BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, 0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */, 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 2e98d344..748dfced 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -166,6 +166,10 @@ import Foundation // Designed Headers MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) + + + // Device Items + MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self) // TODO: Need View try? ModelRegistry.register(TabsModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift new file mode 100644 index 00000000..435ef03f --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift @@ -0,0 +1,72 @@ +// +// 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 stack: Stack + public let eyebrow = Label.commonLabelB3(true) + public let headline = Label.commonLabelB1(true) + public let body = Label.commonLabelB2(true) + public let body2 = Label.commonLabelB2(true) + public let button = Button(frame: .zero) + public let rightImageView = MFLoadImageView(pinnedEdges: .all) + public var imageViewStack: Stack + + + + // MARK: - Initializers + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.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(horizontalAlignment: .leading))], + axis: .vertical) + imageViewStack = Stack.createStack(with: [(view: stack, model: StackItemModel(horizontalAlignment: .leading)), + (view: rightImageView, model: StackItemModel(horizontalAlignment: .fill,verticalAlignment: .center))], + axis: .horizontal,spacing: 10) + 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() + } + + // 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 } + eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) + headline.setOptional(with: model.headline, delegateObject, additionalData) + body.setOptional(with: model.body, delegateObject, additionalData) + body2.setOptional(with: model.body, delegateObject, additionalData) + button.set(with: model.button, delegateObject, additionalData) + rightImageView.set(with: model.image, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 120 + } + + open override func reset() { + super.reset() + eyebrow.styleRegularMicro(true) + headline.styleBoldTitleMedium(true) + body.styleRegularBodySmall(true) + body2.styleRegularBodySmall(true) + + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift new file mode 100644 index 00000000..5325f8ee --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift @@ -0,0 +1,75 @@ +// +// 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() + eyebrow?.fontStyle = .RegularMicro + eyebrow?.textColor = Color(uiColor: .mvmCoolGray6) + headline?.fontStyle = .BoldTitleMedium + body?.fontStyle = .RegularBodySmall + body2?.fontStyle = .RegularBodySmall + 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) + } +} From 124a46f8d6fc396c36cfa1473e2ca2d999b19109 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 21 Apr 2020 13:53:10 +0530 Subject: [PATCH 091/136] 19109(iOS - List - Device - Complex - Link - Medium) initial commit --- MVMCoreUI.xcodeproj/project.pbxproj | 20 +++++++++++++++++-- .../ListDeviceComplexLinkMedium.swift | 9 +++++++++ .../ListDeviceComplexLinkMediumModel.swift | 9 +++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index fe06c483..e958a395 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -151,7 +151,7 @@ 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; }; 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; }; - 943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; }; + 943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; }; 94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.swift */; }; 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; }; @@ -189,6 +189,8 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */; }; AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; + AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */; }; + AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; }; @@ -625,6 +627,8 @@ AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = ""; }; AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; + AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkMedium.swift; sourceTree = ""; }; + AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkMediumModel.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; @@ -1102,6 +1106,15 @@ name = "Recovered References"; sourceTree = ""; }; + AA2AD114244EE43900BBFFE3 /* DeviceItems */ = { + isa = PBXGroup; + children = ( + AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */, + AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */, + ); + path = DeviceItems; + sourceTree = ""; + }; AA4FC2A323F4F69600E251DB /* RightVariable */ = { isa = PBXGroup; children = ( @@ -1351,6 +1364,7 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( + AA2AD114244EE43900BBFFE3 /* DeviceItems */, 52267A0523FFE0A900906CBA /* OneColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */, 8DD1E36C243B3CD900D8F2DF /* ThreeColumn */, @@ -2103,6 +2117,7 @@ D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */, 0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */, + AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, @@ -2197,7 +2212,7 @@ D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */, - EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, + EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, @@ -2314,6 +2329,7 @@ 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */, 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */, + AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift new file mode 100644 index 00000000..bd49e09e --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift @@ -0,0 +1,9 @@ +// +// ListDeviceComplexLinkMedium.swift +// MVMCoreUI +// +// Created by Lekshmi S on 21/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift new file mode 100644 index 00000000..30cf9a6a --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift @@ -0,0 +1,9 @@ +// +// ListDeviceComplexLinkMediumModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 21/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation From 5a4805d1a4fb27c76fe5857aa550fd0a354626a6 Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Tue, 21 Apr 2020 16:26:59 +0530 Subject: [PATCH 092/136] Applied styles as per confluence --- .../List/ListDeviceComplexButtonMedium.swift | 43 +++++++++++-------- .../ListDeviceComplexButtonMediumModel.swift | 7 --- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift index 435ef03f..3d1971fa 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift @@ -9,28 +9,31 @@ import Foundation @objcMembers open class ListDeviceComplexButtonMedium: TableViewCell { - public var stack: Stack + public var verticalStack: Stack public let eyebrow = Label.commonLabelB3(true) public let headline = Label.commonLabelB1(true) public let body = Label.commonLabelB2(true) public let body2 = Label.commonLabelB2(true) - public let button = Button(frame: .zero) + public let button = PillButton(frame: .zero) public let rightImageView = MFLoadImageView(pinnedEdges: .all) - public var imageViewStack: Stack - + public var stack: Stack + // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - stack = Stack.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(horizontalAlignment: .leading))], - axis: .vertical) - imageViewStack = Stack.createStack(with: [(view: stack, model: StackItemModel(horizontalAlignment: .leading)), - (view: rightImageView, model: StackItemModel(horizontalAlignment: .fill,verticalAlignment: .center))], - axis: .horizontal,spacing: 10) + rightImageView.heightAnchor.constraint(equalToConstant: 116.0).isActive = true + rightImageView.widthAnchor.constraint(equalToConstant: 116.0).isActive = true + + verticalStack = Stack.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:10,horizontalAlignment: .leading))], + axis: .vertical,spacing: 0) + stack = Stack.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading,verticalAlignment: .center)), + (view: rightImageView, model: StackItemModel(horizontalAlignment: .fill,verticalAlignment: .center))], + axis: .horizontal,spacing: 10) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -43,6 +46,7 @@ import Foundation super.setupView() addMolecule(stack) stack.restack() + verticalStack.restack() } // MARK: - ModelMoleculeViewProtocol @@ -52,7 +56,7 @@ import Foundation eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) headline.setOptional(with: model.headline, delegateObject, additionalData) body.setOptional(with: model.body, delegateObject, additionalData) - body2.setOptional(with: model.body, delegateObject, additionalData) + body2.setOptional(with: model.body2, delegateObject, additionalData) button.set(with: model.button, delegateObject, additionalData) rightImageView.set(with: model.image, delegateObject, additionalData) } @@ -60,13 +64,16 @@ import Foundation open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 120 } - - open override func reset() { - super.reset() + 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() } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift index 5325f8ee..7f676795 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift @@ -15,8 +15,6 @@ public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelPro 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 @@ -31,11 +29,6 @@ public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelPro /// Defaults to set override public func setDefaults() { super.setDefaults() - eyebrow?.fontStyle = .RegularMicro - eyebrow?.textColor = Color(uiColor: .mvmCoolGray6) - headline?.fontStyle = .BoldTitleMedium - body?.fontStyle = .RegularBodySmall - body2?.fontStyle = .RegularBodySmall button.size = .tiny button.style = .secondary } From 92ca8f23266e43cd7cc0ad593c08d1876c9e1f9d Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 21 Apr 2020 18:33:41 +0530 Subject: [PATCH 093/136] Added model and molecule class files. --- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../ListDeviceComplexLinkMedium.swift | 66 +++++++++++++++++ .../ListDeviceComplexLinkMediumModel.swift | 71 +++++++++++++++++++ 3 files changed, 138 insertions(+) diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 2e98d344..0395f37e 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -151,6 +151,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self) // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift index bd49e09e..53c957b4 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift @@ -7,3 +7,69 @@ // import Foundation +@objcMembers open class ListDeviceComplexLinkMedium: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + private let stack: Stack + 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 link = Link() + public let rightImage = MFLoadImageView(pinnedEdges: .all) + let leftStack: Stack + + //------------------------------------------------------ + // MARK: - Initializers + //------------------------------------------------------ + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + leftStack = Stack.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: link, model: StackItemModel(horizontalAlignment: .leading))], axis: .vertical, spacing: 0) + leftStack.stackModel?.molecules[4].spacing = 16 + rightImage.addSizeConstraintsForAspectRatio = true + stack = Stack.createStack(with: [(view: leftStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //----------------------------------------------------- + open override func setupView() { + super.setupView() + addMolecule(stack) + stack.restack() + leftStack.restack() + } + + //------------------------------------------------------ + // MARK: - Molecule + //------------------------------------------------------ + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListDeviceComplexLinkMediumModel else { return } + eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) + headline.setOptional(with: model.headline, delegateObject, additionalData) + body.setOptional(with: model.body, delegateObject, additionalData) + body2.setOptional(with: model.body2, delegateObject, additionalData) + link.set(with: model.link, delegateObject, additionalData) + rightImage.set(with: model.image, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 120 + } + + open override func reset() { + super.reset() + eyebrow.styleRegularMicro(true) + headline.styleBoldTitleMedium(true) + body.styleRegularBodySmall(true) + body2.styleRegularBodySmall(true) + } +} + diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift index 30cf9a6a..683a7d52 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift @@ -7,3 +7,74 @@ // import Foundation +public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProtocol { + + public static var identifier: String = "listDvcLnkM" + public var eyebrow: LabelModel? + public var headline: LabelModel? + public var body: LabelModel? + public var body2: LabelModel? + public var link: LinkModel + public var image: ImageViewModel + + public init(eyebrow: LabelModel, headline: LabelModel, body: LabelModel, body2: LabelModel, link: LinkModel, image: ImageViewModel) { + self.eyebrow = eyebrow + self.headline = headline + self.body = body + self.body2 = body2 + self.link = link + self.image = image + super.init() + } + + /// Defaults to set + override public func setDefaults() { + super.setDefaults() + eyebrow?.textColor = Color(uiColor: .mvmCoolGray6) + if image.width == nil, image.height == nil { + image.width = 116 + image.height = 116 + } + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrow + case headline + case body + case body2 + case link + case image + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + if let eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) { + self.eyebrow = eyebrow + } + if let headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) { + self.headline = headline + } + if let body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) { + self.body = body + } + if let body2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body2) { + self.body2 = body2 + } + link = try typeContainer.decode(LinkModel.self, forKey: .link) + 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(link, forKey: .link) + try container.encode(image, forKey: .image) + } +} From c2c612aba85e0ea46ab212b879ed950fb0b7a970 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 21 Apr 2020 10:59:35 -0400 Subject: [PATCH 094/136] fix break to background color --- MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift | 3 +++ MVMCoreUI/Atomic/Organisms/StackModel.swift | 2 ++ 2 files changed, 5 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift index dc01fd11..1a6bced6 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift @@ -17,6 +17,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName + case backgroundColor case spacing case percent case gone @@ -33,6 +34,7 @@ import Foundation if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) { self.gone = gone } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) } @@ -43,5 +45,6 @@ import Foundation try container.encodeIfPresent(spacing, forKey: .spacing) try container.encodeIfPresent(percent, forKey: .percent) try container.encode(gone, forKey: .gone) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } } diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index cc8f7d0e..3f13a580 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -48,6 +48,7 @@ import Foundation if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { self.spacing = spacing } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) } @@ -58,5 +59,6 @@ import Foundation try container.encodeIfPresent(axis.rawValueString, forKey: .axis) try container.encodeIfPresent(spacing, forKey: .spacing) try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } } From 5268e6356c44caa15364a1898355a45a1db0c88e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 21 Apr 2020 13:03:15 -0400 Subject: [PATCH 095/136] correcting spacing issue --- MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m index 4ebfd013..d5ad9a83 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m @@ -198,7 +198,7 @@ [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: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; } } else { @@ -210,7 +210,7 @@ } 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; } From 02a39a2f913dd49dfabc88f596eb358b33f3841d Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 21 Apr 2020 14:52:58 -0400 Subject: [PATCH 096/136] slection --- .../Atoms/TextFields/ItemDropdownEntryFieldModel.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index ac7fbab1..345817fd 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -17,6 +17,10 @@ public var options: [String] = [] public var selectedIndex: Int = 0 + + public override func formFieldValue() -> AnyHashable? { + return options[selectedIndex] + } //-------------------------------------------------- // MARK: - Keys @@ -26,7 +30,7 @@ case options case selectedIndex } - + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- From db61701c2c0478c8d4e5af6b7ce782950475ba3a Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 21 Apr 2020 15:09:40 -0400 Subject: [PATCH 097/136] guard --- .../Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index 345817fd..2105120c 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -18,7 +18,8 @@ public var options: [String] = [] public var selectedIndex: Int = 0 - public override func formFieldValue() -> AnyHashable? { + public override func formFieldValue() -> AnyHashable? { + guard !options.isEmpty else { return nil } return options[selectedIndex] } From c1655369a870808f711af05ad3e98f212e02400a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 21 Apr 2020 15:51:49 -0400 Subject: [PATCH 098/136] navigation and template --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++++- .../NavigationItemModelProtocol.swift | 66 +++++++++---------- .../Templates/ThreeLayerCenterTemplate.swift | 15 +++++ .../ThreeLayerCenterTemplateModel.swift | 15 +++++ .../Atomic/Templates/ThreeLayerTemplate.swift | 4 +- .../Containers/NavigationController.swift | 4 +- ...iewControllerMappingObject+Extension.swift | 29 ++++++++ .../MVMCoreUIViewControllerMappingObject.m | 25 +++---- 8 files changed, 117 insertions(+), 57 deletions(-) create mode 100644 MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplate.swift create mode 100644 MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplateModel.swift create mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 1b4ab44b..b5d1bf58 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -152,7 +152,7 @@ 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; }; 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; }; - 943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; }; + 943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; }; 94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.swift */; }; 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; }; @@ -224,6 +224,9 @@ C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; }; D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; }; + D209234F244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */; }; + D2092351244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */; }; + D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; @@ -652,6 +655,9 @@ C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = ""; }; D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = ""; }; D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = ""; }; + D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCenterTemplate.swift; sourceTree = ""; }; + D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCenterTemplateModel.swift; sourceTree = ""; }; + D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIViewControllerMappingObject+Extension.swift"; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; @@ -1495,6 +1501,8 @@ 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */, 014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */, D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */, + D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */, + D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */, D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */, D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */, D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */, @@ -1747,6 +1755,7 @@ D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */, D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */, D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */, + D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */, D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */, ); path = OtherHandlers; @@ -2070,6 +2079,7 @@ AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */, + D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, 94382086243238D100B43AF3 /* WebViewModel.swift in Sources */, @@ -2106,6 +2116,7 @@ D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, + D2092351244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift in Sources */, D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, @@ -2168,7 +2179,7 @@ D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */, - EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, + EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, @@ -2195,6 +2206,7 @@ C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, 0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, + D209234F244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift in Sources */, 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, 94FB966323D797DA003D482B /* MFTextButton.m in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift index d7df7cc9..f15a847a 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift @@ -10,17 +10,16 @@ import Foundation public protocol NavigationItemModelProtocol { var title: String? { get set } - var titleView: MoleculeModelProtocol? { get set } var hidden: Bool { get set } var backgroundColor: Color? { get set } - var transparent: Bool { get set } + var translucent: Bool { get set } var tintColor: Color { get set } var line: LineModel? { get set } - var systemBackButton: Bool { get set } - var showLeftPanelButton: Bool? { get set } - var showRightPanelButton: Bool? { get set } - var additionalLeftItems: [NavigationItemButtonModel]? { get set } - var additionalRightItems: [NavigationItemButtonModel]? { get set } + var showLeftPanelButton: Bool { get set } + var showRightPanelButton: Bool { get set } + var backButton: NavigationItemButtonModel? { get set } + var additionalLeftButtons: [NavigationItemButtonModel]? { get set } + var additionalRightButtons: [NavigationItemButtonModel]? { get set } } public class NavigationItemButtonModel: Codable { @@ -52,74 +51,73 @@ public class NavigationItemButtonModel: Codable { public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol { public class var identifier: String { - return "navigationItem" + return "navigationBar" } public var title: String? - public var titleView: MoleculeModelProtocol? public var hidden: Bool public var backgroundColor: Color? - public var transparent: Bool + public var translucent: Bool public var tintColor: Color public var line: LineModel? - public var systemBackButton = false - public var showLeftPanelButton: Bool? - public var showRightPanelButton: Bool? - public var additionalLeftItems: [NavigationItemButtonModel]? - public var additionalRightItems: [NavigationItemButtonModel]? + public var showLeftPanelButton: Bool + public var showRightPanelButton: Bool + public var backButton: NavigationItemButtonModel? + public var additionalLeftButtons: [NavigationItemButtonModel]? + public var additionalRightButtons: [NavigationItemButtonModel]? - init() { + public init() { hidden = false - transparent = false + translucent = false backgroundColor = Color(uiColor: .white) tintColor = Color(uiColor: .black) line = LineModel(type: .standard) + showLeftPanelButton = true + showRightPanelButton = true + backButton = NavigationItemButtonModel(with: "back", action: ActionBackModel()) } private enum CodingKeys: String, CodingKey { case title - case titleView case hidden case backgroundColor - case transparent + case translucent case tintColor case line - case systemBackButton + case backButton case showLeftPanelButton case showRightPanelButton - case additionalLeftItems - case additionalRightItems + case additionalLeftButtons + case additionalRightButtons } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) - titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView) hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white) - transparent = try typeContainer.decodeIfPresent(Bool.self, forKey: .transparent) ?? false + translucent = try typeContainer.decodeIfPresent(Bool.self, forKey: .translucent) ?? false tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) - systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false - showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) - showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) - additionalLeftItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftItems) - additionalRightItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightItems) + backButton = try typeContainer.decodeIfPresent(NavigationItemButtonModel.self, forKey: .backButton) ?? NavigationItemButtonModel(with: "back", action: ActionBackModel()) + showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) ?? true + showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) ?? true + additionalLeftButtons = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftButtons) + additionalRightButtons = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightButtons) } open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(title, forKey: .title) - try container.encodeModelIfPresent(titleView, forKey: .titleView) try container.encode(hidden, forKey: .hidden) try container.encode(backgroundColor, forKey: .backgroundColor) - try container.encode(transparent, forKey: .transparent) + try container.encode(translucent, forKey: .translucent) try container.encode(tintColor, forKey: .tintColor) try container.encodeIfPresent(line, forKey: .line) - try container.encode(systemBackButton, forKey: .systemBackButton) + try container.encodeIfPresent(backButton, forKey: .backButton) try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton) try container.encode(showRightPanelButton, forKey: .showRightPanelButton) - try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems) - try container.encodeIfPresent(additionalRightItems, forKey: .additionalRightItems) + try container.encodeIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons) + try container.encodeIfPresent(additionalRightButtons, forKey: .additionalRightButtons) } } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplate.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplate.swift new file mode 100644 index 00000000..3d0119a9 --- /dev/null +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplate.swift @@ -0,0 +1,15 @@ +// +// ThreeLayerCenterTemplate.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/21/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ThreeLayerCenterTemplate: ThreeLayerTemplate { + open override func spaceBetweenTopAndMiddle() -> CGFloat? { + return nil + } +} diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplateModel.swift new file mode 100644 index 00000000..4bea76f2 --- /dev/null +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplateModel.swift @@ -0,0 +1,15 @@ +// +// ThreeLayerCenterTemplateModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/21/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ThreeLayerCenterPageTemplateModel: ThreeLayerPageTemplateModel { + public override class var identifier: String { + return "threeLayerCenter" + } +} diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift index 96e85fad..ae2079d3 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift @@ -8,8 +8,8 @@ import UIKit -@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { - public var templateModel: ThreeLayerPageTemplateModel? +@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { + public var templateModel: TemplateModel? open override func parsePageJSON() throws { try parseTemplate(json: loadObject?.pageJSON) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index eb869e89..03d73240 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -43,10 +43,10 @@ import UIKit public static func set(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) { viewController.navigationItem.title = navigationItemModel.title viewController.navigationItem.accessibilityLabel = navigationItemModel.title - viewController.navigationItem.hidesBackButton = !navigationItemModel.systemBackButton + viewController.navigationItem.hidesBackButton = (navigationItemModel.backButton != nil) navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) - UIColor.setBackgroundColor(navigationItemModel.backgroundColor?.uiColor ?? .white, for: navigationController.navigationBar, isTransparent: navigationItemModel.transparent) + UIColor.setBackgroundColor(navigationItemModel.backgroundColor?.uiColor ?? .white, for: navigationController.navigationBar, isTransparent: navigationItemModel.translucent) let tint = navigationItemModel.tintColor.uiColor navigationController.navigationBar.tintColor = tint diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift new file mode 100644 index 00000000..686f6358 --- /dev/null +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift @@ -0,0 +1,29 @@ +// +// MVMCoreUIViewControllerMappingObject+Extension.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/21/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public extension MVMCoreUIViewControllerMappingObject { + func register(template: T.Type) { + add(toTemplateViewControllerMapping: [template.TemplateModel.identifier: MVMCoreViewControllerProgrammaticMappingObject(with: template)!]) + } + + @objc func registerTemplates() { + register(template: MoleculeStackTemplate.self) + register(template: MoleculeStackCenteredTemplate.self) + add(toTemplateViewControllerMapping: ["modalStack": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeStackTemplate.self)!]) + + register(template: MoleculeListTemplate.self) + add(toTemplateViewControllerMapping: ["modalList": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeListTemplate.self)!]) + + register(template: ThreeLayerTemplate.self) + register(template: ThreeLayerCenterTemplate.self) + + register(template: CollectionTemplate.self) + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index 20fb924e..0ad51d4c 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -12,23 +12,14 @@ @implementation MVMCoreUIViewControllerMappingObject -- (NSMutableDictionary *)viewControllerMapping { - - // Keeps a mapping of the given page type - static dispatch_once_t onceToken; - static NSMutableDictionary *viewControllerMapping; - dispatch_once(&onceToken, ^{ - viewControllerMapping = [@{ - @"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], - @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], - @"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], - @"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]], - @"modalStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeStackTemplate class]], - @"modalList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeListTemplate class]], - @"collection" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[CollectionTemplate class]] - } mutableCopy]; - }); - return viewControllerMapping; +- (instancetype)init { + if (self = [super init]) { + if (self.viewControllerMapping == nil) { + self.viewControllerMapping = [NSMutableDictionary dictionary]; + } + [self registerTemplates]; + } + return self; } @end From 565c01148cfad81abcc02f723104aa1c1bac83a7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 21 Apr 2020 16:03:21 -0400 Subject: [PATCH 099/136] background color --- .../Atomic/Protocols/ModelProtocols/PageModelProtocol.swift | 1 + MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift | 3 +++ MVMCoreUI/Atomic/Templates/TemplateModel.swift | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift index be4e4e65..ec2bead8 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift @@ -12,5 +12,6 @@ public protocol PageModelProtocol { var pageType: String { get set } /// Temporary: for legacy response var screenHeading: String? { get set } + var backgroundColor: Color? { get set } var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set } } diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 56b1a86c..fc9873bd 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -22,5 +22,8 @@ public extension TemplateProtocol where Self: ViewController { let templateModel = try decoder.decode(TemplateModel.self, from: data) self.templateModel = templateModel self.pageModel = templateModel as? MVMControllerModelProtocol + if let backgroundColor = templateModel.backgroundColor { + view.backgroundColor = backgroundColor.uiColor + } } } diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index dbbbc494..86da1981 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -17,6 +17,7 @@ import Foundation // Although this is done in the extension, it is needed for the encoding. return Self.identifier } + public var backgroundColor: Color? public var screenHeading: String? public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? @@ -29,6 +30,7 @@ import Foundation case pageType case template case screenHeading + case backgroundColor case formRules case navigationItem } @@ -37,6 +39,7 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) pageType = try typeContainer.decode(String.self, forKey: .pageType) screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem) } @@ -45,6 +48,7 @@ import Foundation var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(pageType, forKey: .pageType) try container.encode(template, forKey: .template) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(screenHeading, forKey: .screenHeading) try container.encodeIfPresent(formRules, forKey: .formRules) try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem) From a697fea926ecbe69c7d288c84b738f33a254dc3c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 21 Apr 2020 18:40:23 -0400 Subject: [PATCH 100/136] threelayer base. Anchored header footer for non table --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ .../ThreeLayerTemplateModelProtocol.swift | 17 ++++++ .../Templates/CollectionTemplateModel.swift | 10 +--- .../Templates/ListPageTemplateModel.swift | 10 +--- .../Templates/MoleculeStackTemplate.swift | 6 +++ .../Templates/StackPageTemplateModel.swift | 11 +--- .../Templates/ThreeLayerModelBase.swift | 49 +++++++++++++++++ .../ThreeLayerPageTemplateModel.swift | 10 +--- .../Atomic/Templates/ThreeLayerTemplate.swift | 9 +--- .../ThreeLayerViewController.swift | 54 ++++++++++++++----- ...iewControllerMappingObject+Extension.swift | 2 +- 11 files changed, 128 insertions(+), 58 deletions(-) create mode 100644 MVMCoreUI/Atomic/Protocols/ModelProtocols/ThreeLayerTemplateModelProtocol.swift create mode 100644 MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d8d3bde6..d48bba00 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -238,6 +238,8 @@ D209234F244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */; }; D2092351244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */; }; D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */; }; + D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */; }; + D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; @@ -680,6 +682,8 @@ D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCenterTemplate.swift; sourceTree = ""; }; D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCenterTemplateModel.swift; sourceTree = ""; }; D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIViewControllerMappingObject+Extension.swift"; sourceTree = ""; }; + D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplateModelProtocol.swift; sourceTree = ""; }; + D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerModelBase.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; @@ -938,6 +942,7 @@ D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */, 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */, D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */, + D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */, ); path = ModelProtocols; sourceTree = ""; @@ -1523,6 +1528,7 @@ isa = PBXGroup; children = ( D22D8392241C27B100D3DF69 /* TemplateModel.swift */, + D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */, 014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */, D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */, @@ -2236,6 +2242,7 @@ 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */, 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */, + D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */, 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, @@ -2348,6 +2355,7 @@ 94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, + D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ThreeLayerTemplateModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ThreeLayerTemplateModelProtocol.swift new file mode 100644 index 00000000..3f05a1e5 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ThreeLayerTemplateModelProtocol.swift @@ -0,0 +1,17 @@ +// +// ThreeLayerTemplateModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/21/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ThreeLayerTemplateModelProtocol: TemplateModelProtocol { + var anchorHeader: Bool { get set } + var header: MoleculeModelProtocol? { get set } + + var anchorFooter: Bool { get set } + var footer: MoleculeModelProtocol? { get set } +} diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift index 56c56456..f9d8c0a7 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class CollectionTemplateModel: TemplateModel { +@objcMembers public class CollectionTemplateModel: ThreeLayerModelBase { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -16,9 +16,7 @@ import Foundation public override class var identifier: String { return "collection" } - public var header: MoleculeModelProtocol? public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]? - public var footer: MoleculeModelProtocol? public var columns: Int? //-------------------------------------------------- @@ -37,8 +35,6 @@ import Foundation private enum CodingKeys: String, CodingKey { case molecules - case header - case footer case columns } @@ -49,8 +45,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules) - header = try typeContainer.decodeModelIfPresent(codingKey: .header) - footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) columns = try typeContainer.decodeIfPresent(Int.self, forKey: .columns) try super.init(from: decoder) } @@ -59,8 +53,6 @@ import Foundation try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeModelsIfPresent(molecules, forKey: .molecules) - try container.encodeModelIfPresent(header, forKey: .header) - try container.encodeModelIfPresent(footer, forKey: .footer) try container.encodeIfPresent(columns, forKey: .columns) } } diff --git a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift index d2418cbc..b239bd81 100644 --- a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class ListPageTemplateModel: TemplateModel { +@objcMembers public class ListPageTemplateModel: ThreeLayerModelBase { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -16,9 +16,7 @@ import Foundation public override class var identifier: String { return "list" } - public var header: MoleculeModelProtocol? public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]? - public var footer: MoleculeModelProtocol? public var line: LineModel? //-------------------------------------------------- @@ -37,8 +35,6 @@ import Foundation private enum CodingKeys: String, CodingKey { case molecules - case header - case footer case line } @@ -49,8 +45,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules) - header = try typeContainer.decodeModelIfPresent(codingKey: .header) - footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) try super.init(from: decoder) } @@ -59,8 +53,6 @@ import Foundation try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeModelsIfPresent(molecules, forKey: .molecules) - try container.encodeModelIfPresent(header, forKey: .header) - try container.encodeModelIfPresent(footer, forKey: .footer) try container.encode(line, forKey: .line) } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift index b26bbc8a..90096145 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift @@ -11,6 +11,12 @@ import UIKit open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? + + open override func handleNewData() { + topViewOutsideOfScroll = templateModel?.anchorHeader ?? false + bottomViewOutsideOfScroll = templateModel?.anchorFooter ?? false + super.handleNewData() + } open override func parsePageJSON() throws { try parseTemplate(json: loadObject?.pageJSON) diff --git a/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift index c7b5239a..f21a0421 100644 --- a/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/StackPageTemplateModel.swift @@ -9,14 +9,11 @@ import Foundation -@objcMembers public class StackPageTemplateModel: TemplateModel { +@objcMembers public class StackPageTemplateModel: ThreeLayerModelBase { public override class var identifier: String { return "stack" } - - public var header: MoleculeModelProtocol? public var moleculeStack: StackModel - public var footer: MoleculeModelProtocol? public init(pageType: String, moleculeStack: StackModel) { self.moleculeStack = moleculeStack @@ -24,16 +21,12 @@ import Foundation } private enum CodingKeys: String, CodingKey { - case header - case footer case stack } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) moleculeStack = try typeContainer.decode(StackModel.self, forKey: .stack) - header = try typeContainer.decodeModelIfPresent(codingKey: .header) - footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) try super.init(from: decoder) } @@ -41,7 +34,5 @@ import Foundation try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeStack, forKey: .stack) - try container.encodeModelIfPresent(header, forKey: .header) - try container.encodeModelIfPresent(footer, forKey: .footer) } } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift new file mode 100644 index 00000000..f0276979 --- /dev/null +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift @@ -0,0 +1,49 @@ +// +// ThreeLayerModelBase.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/21/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ThreeLayerModelBase: TemplateModel, ThreeLayerTemplateModelProtocol { + public var anchorHeader: Bool = false + public var header: MoleculeModelProtocol? + public var anchorFooter: Bool = false + public var footer: MoleculeModelProtocol? + + public override init(pageType: String) { + super.init(pageType: pageType) + } + + private enum CodingKeys: String, CodingKey { + case anchorHeader + case header + case anchorFooter + case footer + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + if let anchor = try typeContainer.decodeIfPresent(Bool.self, forKey: .anchorHeader) { + anchorHeader = anchor + } + header = try typeContainer.decodeModelIfPresent(codingKey: .header) + if let anchor = try typeContainer.decodeIfPresent(Bool.self, forKey: .anchorFooter) { + anchorFooter = anchor + } + footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) + 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.encodeIfPresent(anchorHeader, forKey: .anchorHeader) + try container.encodeModelIfPresent(header, forKey: .header) + try container.encodeIfPresent(anchorFooter, forKey: .anchorFooter) + try container.encodeModelIfPresent(footer, forKey: .footer) + } +} diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift index 61476707..c4e93f7a 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerPageTemplateModel.swift @@ -8,13 +8,11 @@ import Foundation -@objcMembers public class ThreeLayerPageTemplateModel: TemplateModel { +@objcMembers public class ThreeLayerPageTemplateModel: ThreeLayerModelBase { public override class var identifier: String { return "threeLayer" } - public var header: MoleculeModelProtocol? public var middle: MoleculeModelProtocol? - public var footer: MoleculeModelProtocol? public init(pageType: String, header: MoleculeModelProtocol?, middle: MoleculeModelProtocol?, footer: MoleculeModelProtocol?) { super.init(pageType: pageType) @@ -24,24 +22,18 @@ import Foundation } private enum CodingKeys: String, CodingKey { - case header - case footer case middle } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - header = try typeContainer.decodeModelIfPresent(codingKey: .header) middle = try typeContainer.decodeModelIfPresent(codingKey: .middle) - footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) 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.encodeModelIfPresent(header, forKey: .header) try container.encodeModelIfPresent(header, forKey: .middle) - try container.encodeModelIfPresent(footer, forKey: .footer) } } diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift index ae2079d3..4884d5b1 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift @@ -16,15 +16,10 @@ import UIKit try super.parsePageJSON() } - override open func viewDidLoad() { - super.viewDidLoad() - bottomViewOutsideOfScroll = true - // Do any additional setup after loading the view. - } - open override func handleNewData() { + topViewOutsideOfScroll = templateModel?.anchorHeader ?? false + bottomViewOutsideOfScroll = templateModel?.anchorFooter ?? false super.handleNewData() - heightConstraint?.isActive = true } open override func viewForTop() -> UIView? { diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index 9eacd25c..de909995 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -18,6 +18,9 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { var bottomView: UIView? var useMargins: Bool = false + // The top view can be put outside of the scrolling area. + var topViewOutsideOfScroll = false + // The bottom view can be put outside of the scrolling area. var bottomViewOutsideOfScroll = false @@ -118,13 +121,21 @@ extension ThreeLayerViewController { topView = MVMCoreUICommonViewsUtility.commonView() topView?.heightAnchor.constraint(equalToConstant: 0).isActive = true } - guard let topView = topView, let contentView = contentView else { - return nil + guard var topView = topView else { return nil } + + // Adds the top view outside the scroll if directed. + if topViewOutsideOfScroll { + topConstraint?.isActive = false; + addViewOutsideOfScrollViewTop(topView) + + // Adds and returns an empty view to use for the internal logic. + topView = MVMCoreUICommonViewsUtility.commonView() + topView.heightAnchor.constraint(equalToConstant: 0).isActive = true + addViewInsideOfScrollViewTop(topView) + } else { + topConstraint?.isActive = true; + addViewInsideOfScrollViewTop(topView) } - contentView.addSubview(topView) - NSLayoutConstraint.pinViewTop(toSuperview: topView, useMargins: useMargins, constant: 0).isActive = true - NSLayoutConstraint.pinViewLeft(toSuperview: topView, useMargins: useMargins, constant: 0).isActive = true - NSLayoutConstraint.pinViewRight(toSuperview: topView, useMargins: useMargins, constant: 0).isActive = true return topView } @@ -135,9 +146,7 @@ extension ThreeLayerViewController { middleView = MVMCoreUICommonViewsUtility.commonView() middleView?.heightAnchor.constraint(equalToConstant: 0).isActive = true } - guard let middleView = middleView, let contentView = contentView else { - return nil - } + guard let middleView = middleView, let contentView = contentView else { return nil } contentView.addSubview(middleView) NSLayoutConstraint.pinViewLeft(toSuperview: middleView, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: middleView, useMargins: useMargins, constant: 0).isActive = true @@ -152,15 +161,17 @@ extension ThreeLayerViewController { bottomView = MVMCoreUICommonViewsUtility.commonView() bottomView?.heightAnchor.constraint(equalToConstant: 0).isActive = true } - guard let bottomView = bottomView else { - return nil - } + guard var bottomView = bottomView else { return nil } // Adds the bottom view outside the scroll if directed. if bottomViewOutsideOfScroll { bottomConstraint?.isActive = false; - addViewInsideOfScrollViewBottom(ViewConstrainingView.empty()) addViewOutsideOfScrollViewBottom(bottomView) + + // Adds and returns an empty view to use for the internal logic. + bottomView = MVMCoreUICommonViewsUtility.commonView() + bottomView.heightAnchor.constraint(equalToConstant: 0).isActive = true + addViewInsideOfScrollViewBottom(bottomView) } else { bottomConstraint?.isActive = true; addViewInsideOfScrollViewBottom(bottomView) @@ -221,6 +232,23 @@ extension ThreeLayerViewController { } } + func addViewInsideOfScrollViewTop(_ view: UIView) { + guard let contentView = contentView else { return } + contentView.addSubview(view) + NSLayoutConstraint.pinViewTop(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + } + + func addViewOutsideOfScrollViewTop(_ view: UIView) { + guard let scrollView = scrollView, let parentView = self.view else { return } + self.view?.addSubview(view) + scrollView.topAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + view.topAnchor.constraint(equalTo: parentView.safeAreaLayoutGuide.topAnchor).isActive = true + } + func addViewInsideOfScrollViewBottom(_ view: UIView) { guard let contentView = contentView else { return diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift index 686f6358..5cb2abdb 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject+Extension.swift @@ -15,7 +15,7 @@ public extension MVMCoreUIViewControllerMappingObject { @objc func registerTemplates() { register(template: MoleculeStackTemplate.self) - register(template: MoleculeStackCenteredTemplate.self) + add(toTemplateViewControllerMapping: [StackCenteredPageTemplateModel.identifier: MVMCoreViewControllerProgrammaticMappingObject(with: MoleculeStackCenteredTemplate.self)!]) add(toTemplateViewControllerMapping: ["modalStack": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeStackTemplate.self)!]) register(template: MoleculeListTemplate.self) From 7b3bb5ffb20433d888b560c523f8b8eee8316457 Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Wed, 22 Apr 2020 11:00:31 +0530 Subject: [PATCH 101/136] label font changes updated --- .../List/ListDeviceComplexButtonMedium.swift | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift index 3d1971fa..9847a7a8 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift @@ -10,26 +10,23 @@ import Foundation @objcMembers open class ListDeviceComplexButtonMedium: TableViewCell { public var verticalStack: Stack - public let eyebrow = Label.commonLabelB3(true) - public let headline = Label.commonLabelB1(true) - public let body = Label.commonLabelB2(true) - public let body2 = Label.commonLabelB2(true) + 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(pinnedEdges: .all) public var stack: Stack - - // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { rightImageView.heightAnchor.constraint(equalToConstant: 116.0).isActive = true rightImageView.widthAnchor.constraint(equalToConstant: 116.0).isActive = true - - verticalStack = Stack.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .leading)), + verticalStack = Stack.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:10,horizontalAlignment: .leading))], + (view: button, model: StackItemModel(spacing:16,horizontalAlignment: .leading))], axis: .vertical,spacing: 0) stack = Stack.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading,verticalAlignment: .center)), (view: rightImageView, model: StackItemModel(horizontalAlignment: .fill,verticalAlignment: .center))], From 211e3b6e586066f2f4790925d7b1dd31de9e4234 Mon Sep 17 00:00:00 2001 From: Kruthika KP <> Date: Wed, 22 Apr 2020 11:27:11 +0530 Subject: [PATCH 102/136] 19024 - List - Three Column - Data Usage - Initial commit --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++ MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../ListThreeColumnDataUsage.swift | 61 +++++++++++++++++++ .../ListThreeColumnDataUsageModel.swift | 48 +++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsageModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 767e9f32..3cf7884e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -143,6 +143,8 @@ 8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; }; 8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; }; 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; }; + 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 */; }; 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */; }; 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; }; @@ -581,6 +583,8 @@ 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinks.swift; sourceTree = ""; }; 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalDataModel.swift; sourceTree = ""; }; 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = ""; }; + 8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsage.swift; sourceTree = ""; }; + 8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageModel.swift; sourceTree = ""; }; 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = ""; }; 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = ""; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = ""; }; @@ -1067,6 +1071,8 @@ children = ( 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */, 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */, + 8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */, + 8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */, ); path = ThreeColumn; sourceTree = ""; @@ -2188,6 +2194,7 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, + 8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */, AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */, @@ -2196,6 +2203,7 @@ 525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */, D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, + 8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */, BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */, D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index e31e18a1..8026dfec 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -152,6 +152,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self) // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift new file mode 100644 index 00000000..0884997a --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift @@ -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 + + //------------------------------------------------------ + // MARK: - Initializers + //------------------------------------------------------ + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 37, horizontalAlignment: .leading)), + (view: centerLabel, model: StackItemModel(percent: 33, horizontalAlignment: .leading)), + (view: rightLabel, model: StackItemModel(percent: 30, 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.styleBoldBodySmall(true) + centerLabel.styleBoldBodySmall(true) + rightLabel.styleBoldBodySmall(true) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsageModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsageModel.swift new file mode 100644 index 00000000..56f1e402 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsageModel.swift @@ -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) + } +} + From 0ceb0e97393c638339989dab3e30f437cb27aef4 Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Wed, 22 Apr 2020 15:10:17 +0530 Subject: [PATCH 103/136] spacing between stack items modified --- .../DesignedComponents/List/ListDeviceComplexButtonMedium.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift index 9847a7a8..90e0fc60 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift @@ -30,7 +30,7 @@ import Foundation axis: .vertical,spacing: 0) stack = Stack.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading,verticalAlignment: .center)), (view: rightImageView, model: StackItemModel(horizontalAlignment: .fill,verticalAlignment: .center))], - axis: .horizontal,spacing: 10) + axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } From 59622ac372b351306ff9bbc279fc138f200ce25a Mon Sep 17 00:00:00 2001 From: Kruthika KP <> Date: Wed, 22 Apr 2020 17:02:06 +0530 Subject: [PATCH 104/136] style change --- .../List/ThreeColumn/ListThreeColumnDataUsage.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift index 0884997a..2611943a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift @@ -22,9 +22,9 @@ import Foundation // MARK: - Initializers //------------------------------------------------------ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 37, horizontalAlignment: .leading)), - (view: centerLabel, model: StackItemModel(percent: 33, horizontalAlignment: .leading)), - (view: rightLabel, model: StackItemModel(percent: 30, horizontalAlignment: .leading))], + stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 35, horizontalAlignment: .leading)), + (view: centerLabel, model: StackItemModel(percent: 35, horizontalAlignment: .leading)), + (view: rightLabel, model: StackItemModel(percent: 30, horizontalAlignment: .center))], axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -54,8 +54,8 @@ import Foundation open override func reset() { super.reset() - leftLabel.styleBoldBodySmall(true) - centerLabel.styleBoldBodySmall(true) - rightLabel.styleBoldBodySmall(true) + leftLabel.styleRegularBodySmall(true) + centerLabel.styleRegularBodySmall(true) + rightLabel.styleRegularBodySmall(true) } } From 9366469f354dc3395578fb152e9c72cefc8c60e0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 12:11:33 -0400 Subject: [PATCH 105/136] add anchor logic to table three layer and list Safe area for scrollview remove safeAreaView itself for now until requirement comes in --- .../Templates/MoleculeListTemplate.swift | 2 + .../ProgrammaticScrollViewController.swift | 8 +- .../ThreeLayerTableViewController.swift | 88 +++++++++++-------- .../ThreeLayerViewController.swift | 6 -- 4 files changed, 59 insertions(+), 45 deletions(-) diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index b236e332..e40fbc33 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -81,6 +81,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } open override func handleNewData() { + topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false + bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false setup() registerWithTable() super.handleNewData() diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift index b6ed6353..cec6c3fd 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift @@ -39,11 +39,13 @@ open class ProgrammaticScrollViewController: ScrollingViewController { topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint + // Sets the constraints for the content view let contentView = MVMCoreUICommonViewsUtility.commonView() scrollView.addSubview(contentView) - - // Sets the constraints for the content view - NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) + contentView.leftAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leftAnchor).isActive = true + scrollView.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true + contentView.topAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.topAnchor).isActive = true + scrollView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true // Super will set later. contentWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: 320.0) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 000f2e7f..15dc037b 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -15,9 +15,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { private var bottomView: UIView? private var headerView: UIView? private var footerView: UIView? - private var safeAreaView: UIView? var useMargins: Bool = true public var bottomViewOutsideOfScrollArea: Bool = false + public var topViewOutsideOfScrollArea: Bool = false private var topViewBottomConstraint: NSLayoutConstraint? private var bottomViewTopConstraint: NSLayoutConstraint? @@ -76,14 +76,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { var totalMinimumSpace: CGFloat = 0 var fillTop = false - if spaceBelowTopView() == nil, self.tableView?.tableHeaderView != nil { + if spaceBelowTopView() == nil, tableView.tableHeaderView != nil { fillTop = true currentSpace += topViewBottomConstraint?.constant ?? 0 totalMinimumSpace += minimumSpace } var fillBottom = false - if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, self.tableView?.tableFooterView != nil { + if spaceAboveBottomView() == nil, tableView.tableFooterView != nil { fillBottom = true currentSpace += bottomViewTopConstraint?.constant ?? 0 totalMinimumSpace += minimumSpace @@ -109,12 +109,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { showHeader(width) showFooter(width) } else if fillTop { - // Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one. - if bottomViewOutsideOfScrollArea { - topViewBottomConstraint?.constant = newSpace / 2 - } else { - topViewBottomConstraint?.constant = newSpace - } + topViewBottomConstraint?.constant = newSpace showHeader(width) } else if fillBottom { // Only bottom is spaced. @@ -127,9 +122,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { //MARK: - Header Footer /// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader. open func createViewForTableHeader() { - let topView = viewForTop() + var topView = viewForTop() self.topView = topView + // If top view is outside of scroll area, create a dummy view for the header. + if topViewOutsideOfScrollArea { + topView = MVMCoreUICommonViewsUtility.commonView() + topView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true + } let headerView = MVMCoreUICommonViewsUtility.commonView() headerView.addSubview(topView) topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true @@ -143,9 +143,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { /// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter. open func createViewForTableFooter() { - let bottomView = viewForBottom() + var bottomView = viewForBottom() self.bottomView = bottomView + // If bottom view is outside of scroll area, create a dummy view for the header. + if bottomViewOutsideOfScrollArea { + bottomView = MVMCoreUICommonViewsUtility.commonView() + bottomView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true + } let footerView = MVMCoreUICommonViewsUtility.commonView() footerView.addSubview(bottomView) bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0) @@ -161,10 +166,20 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { func showHeader(_ sizingWidth: CGFloat?) { headerView?.removeFromSuperview() tableView?.tableHeaderView = nil - guard let headerView = headerView else { - return - } + guard let topView = topView, + let headerView = headerView else { return } + if topViewOutsideOfScrollArea { + // put top view outside of scrolling area. + topConstraint?.isActive = false + view.addSubview(topView) + topView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true + topView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true + view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true + tableView.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true + } else { + topConstraint?.isActive = true + } // This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout. headerView.setNeedsLayout() headerView.layoutIfNeeded() @@ -173,41 +188,42 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { tableHeaderView.addSubview(headerView) NSLayoutConstraint.constraintPinSubview(toSuperview: headerView) tableView?.tableHeaderView = tableHeaderView + } /// Takes the current footerView and adds it to the tableFooterView func showFooter(_ sizingWidth: CGFloat?) { footerView?.removeFromSuperview() - safeAreaView?.removeFromSuperview() - guard let footerView = footerView, let tableView = tableView else { - return + guard let bottomView = bottomView, + let footerView = footerView, + let tableView = tableView else { + self.tableView?.tableFooterView = nil + return } if bottomViewOutsideOfScrollArea { // put bottom view outside of scrolling area. bottomConstraint?.isActive = false - view.addSubview(footerView) - footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true - footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true - view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true - view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true - safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view) - safeAreaView?.backgroundColor = bottomView?.backgroundColor + view.addSubview(bottomView) + bottomView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true + bottomView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true + view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true + view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true } else { bottomConstraint?.isActive = true - var y: CGFloat? - if let tableFooterView = tableView.tableFooterView { - // if footer already exists, use the same y location to avoid strange moving animation - y = tableFooterView.frame.minY - } - - // This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout. - MVMCoreUIUtility.sizeView(toFit: footerView) - let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height)) - tableFooterView.addSubview(footerView) - NSLayoutConstraint.constraintPinSubview(toSuperview: footerView) - tableView.tableFooterView = tableFooterView } + var y: CGFloat? + if let tableFooterView = tableView.tableFooterView { + // if footer already exists, use the same y location to avoid strange moving animation + y = tableFooterView.frame.minY + } + + // This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout. + MVMCoreUIUtility.sizeView(toFit: footerView) + let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height)) + tableFooterView.addSubview(footerView) + NSLayoutConstraint.constraintPinSubview(toSuperview: footerView) + tableView.tableFooterView = tableFooterView } //MARK: - Functions to subclass diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index de909995..a4cc66d7 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -24,7 +24,6 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { // The bottom view can be put outside of the scrolling area. var bottomViewOutsideOfScroll = false - private var safeAreaView: UIView? var heightConstraint: NSLayoutConstraint? open override func updateViews() { @@ -71,7 +70,6 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { topView?.removeFromSuperview() middleView?.removeFromSuperview() bottomView?.removeFromSuperview() - safeAreaView?.removeFromSuperview() if let subViews = contentView?.subviews { for view in subViews { view.removeFromSuperview() @@ -266,10 +264,6 @@ extension ThreeLayerViewController { NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true - if let safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: parentView) { - safeAreaView.backgroundColor = bottomView?.backgroundColor - self.safeAreaView = safeAreaView - } } } } From 5a26ce2529f196b26e7fc0416e33e893fecae06b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 22 Apr 2020 14:01:32 -0400 Subject: [PATCH 106/136] accessibility for toggle --- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 8efd0a3c..14cfb7b7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -246,6 +246,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) backgroundColor = containerTintColor.off knobView.backgroundColor = knobTintColor.off + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel") isAnimated = true didToggleAction = nil shouldToggleAction = { return true } @@ -373,6 +374,10 @@ public typealias ActionBlockConfirmation = () -> (Bool) isAnimated = model.animated isEnabled = model.enabled + if let accessibileString = model.accessibilityText { + accessibilityLabel = accessibileString + } + if let actionMap = model.action?.toJSON() { didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } From 02e1de9b88bce99a02634b21f1d7649f0c5c5a00 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 14:03:02 -0400 Subject: [PATCH 107/136] cleanup --- .../ThreeLayerCollectionViewController.swift | 53 +++++-------------- .../ThreeLayerTableViewController.swift | 28 +++------- ...VMCoreUICommonViewsUtility+Extension.swift | 6 +++ 3 files changed, 25 insertions(+), 62 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift index aa34f2f2..e16d760f 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift @@ -17,6 +17,8 @@ import Foundation private var footerView: ContainerCollectionReusableView? private let headerID = "header" private let footerID = "footer" + public var bottomViewOutsideOfScrollArea: Bool = false + public var topViewOutsideOfScrollArea: Bool = false /// Updates the padding for flexible space (header or footer) private func updateFlexibleSpace() { @@ -41,16 +43,8 @@ import Foundation } guard fillTop || fillBottom else { return } - let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace) - - // If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value. - var currentSpaceForCompare: CGFloat = currentSpace - if fillTop { - currentSpaceForCompare = currentSpace * 2; - } - - if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 1) { + if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpace, 1) { if fillTop && fillBottom { // space both let half = newSpace / 2 @@ -89,11 +83,11 @@ import Foundation self.invalidateCollectionLayout() } } - + open override func handleNewData() { super.handleNewData() - createViewForHeader() - createViewForFooter() + topView = viewForTop() + bottomView = viewForBottom() reloadCollectionData() } @@ -118,27 +112,6 @@ import Foundation open func minimumFillSpace() -> CGFloat { return 0 } - - //MARK: - Header Footer - /// Creates the top view. - open func createViewForHeader() { - guard let topView = viewForTop() else { - self.topView = nil - self.headerView = nil - return - } - self.topView = topView - } - - /// Creates the footer - open func createViewForFooter() { - guard let bottomView = viewForBottom() else { - self.bottomView = nil - self.footerView = nil - return - } - self.bottomView = bottomView - } //MARK: - Functions to subclass /// Subclass for a top view. @@ -187,18 +160,14 @@ import Foundation } open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - guard let _ = topView, - section == 0 else { return .zero } - + guard section == 0 else { return .zero } // Calculate the height of the header since apple doesn't support autolayout. Width is fixed, height is tall as content. let header = headerView ?? self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader, at: IndexPath(row: 0, section: section)) return header.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel) } open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { - guard let _ = bottomView, - section == numberOfSections(in: collectionView) - 1 else { return .zero } - + guard section == numberOfSections(in: collectionView) - 1 else { return .zero } // Calculate the height of the footr since apple doesn't support autolayout. Width is fixed, height is tall as content. let footer = footerView ?? self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionFooter, at: IndexPath(row: 0, section: section)) return footer.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel) @@ -207,13 +176,15 @@ import Foundation open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionFooter, let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerID, for: indexPath) as? ContainerCollectionReusableView { - footerView.addAndContain(view: bottomView!) + let bottomView = self.bottomView ?? MVMCoreUICommonViewsUtility.getView(with: 0) + footerView.addAndContain(view: bottomView) footerView.topConstraint?.constant = spaceAboveBottomView() ?? 0 self.footerView = footerView return footerView } else if kind == UICollectionView.elementKindSectionHeader, let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerID, for: indexPath) as? ContainerCollectionReusableView { - headerView.addAndContain(view: topView!) + let topView = self.topView ?? MVMCoreUICommonViewsUtility.getView(with: 0) + headerView.addAndContain(view: topView) headerView.bottomConstraint?.constant = spaceBelowTopView() ?? 0 self.headerView = headerView return headerView diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 15dc037b..1ddeb6c0 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -92,15 +92,8 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { guard fillTop || fillBottom else { return } let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace) - - // If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value. - var currentSpaceForCompare: CGFloat = currentSpace - if fillTop && bottomViewOutsideOfScrollArea { - currentSpaceForCompare = currentSpace * 2; - } - let width = view.bounds.width - if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 0.1) { + if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpace, 0.1) { if fillTop && fillBottom { // space both let half = newSpace / 2 @@ -125,10 +118,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { var topView = viewForTop() self.topView = topView - // If top view is outside of scroll area, create a dummy view for the header. + // If top view is outside of scroll area, create a dummy view for the header. Small height is needed to stop apple from adding padding for grouped tables when no header. if topViewOutsideOfScrollArea { - topView = MVMCoreUICommonViewsUtility.commonView() - topView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true + topView = MVMCoreUICommonViewsUtility.getView(with: 0.5) } let headerView = MVMCoreUICommonViewsUtility.commonView() headerView.addSubview(topView) @@ -146,10 +138,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { var bottomView = viewForBottom() self.bottomView = bottomView - // If bottom view is outside of scroll area, create a dummy view for the header. + // If bottom view is outside of scroll area, create a dummy view for the header. Small height is needed to stop apple from adding padding for grouped tables when no header. if bottomViewOutsideOfScrollArea { - bottomView = MVMCoreUICommonViewsUtility.commonView() - bottomView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true + bottomView = MVMCoreUICommonViewsUtility.getView(with: 0.5) } let footerView = MVMCoreUICommonViewsUtility.commonView() footerView.addSubview(bottomView) @@ -188,7 +179,6 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { tableHeaderView.addSubview(headerView) NSLayoutConstraint.constraintPinSubview(toSuperview: headerView) tableView?.tableHeaderView = tableHeaderView - } /// Takes the current footerView and adds it to the tableFooterView @@ -229,18 +219,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { //MARK: - Functions to subclass /// Subclass for a top view. open func viewForTop() -> UIView { - let view = MVMCoreUICommonViewsUtility.commonView() // Small height is needed to stop apple from adding padding for grouped tables when no header. - view.heightAnchor.constraint(equalToConstant: 1).isActive = true - return view + return MVMCoreUICommonViewsUtility.getView(with: 1) } /// Subclass for a bottom view. open func viewForBottom() -> UIView { // Default spacing is standard when no buttons. - let view = MVMCoreUICommonViewsUtility.commonView() - view.heightAnchor.constraint(equalToConstant: PaddingDefaultVerticalSpacing).isActive = true - return view + return MVMCoreUICommonViewsUtility.getView(with: PaddingDefaultVerticalSpacing) } deinit { diff --git a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift index 704cf801..84a6534c 100644 --- a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift +++ b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift @@ -20,4 +20,10 @@ public extension MVMCoreUICommonViewsUtility { return toolbar } + + static func getView(with height: CGFloat) -> UIView { + let view = self.commonView() + view.heightAnchor.constraint(equalToConstant: height).isActive = true + return view + } } From ca389567cc3c009cecd51881783d2b51a461c637 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 14:08:45 -0400 Subject: [PATCH 108/136] fix update constraints --- .../BaseControllers/ScrollingViewController.swift | 2 +- .../ThreeLayerTableViewController.swift | 13 +++++++++---- .../BaseControllers/ThreeLayerViewController.swift | 3 ++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ScrollingViewController.swift b/MVMCoreUI/BaseControllers/ScrollingViewController.swift index 97e83f98..65812d79 100644 --- a/MVMCoreUI/BaseControllers/ScrollingViewController.swift +++ b/MVMCoreUI/BaseControllers/ScrollingViewController.swift @@ -44,9 +44,9 @@ open class ScrollingViewController: ViewController { } open override func updateViewConstraints() { - super.updateViewConstraints() // Sets the width of the content to the width of the screen. contentWidthConstraint?.constant = view.bounds.width - scrollView.contentInset.left - scrollView.contentInset.right + super.updateViewConstraints() } open override func viewDidLayoutSubviews() { diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 1ddeb6c0..d884af42 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -67,9 +67,10 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { } open override func updateViewConstraints() { - super.updateViewConstraints() - - guard let tableView = tableView else { return } + guard let tableView = tableView else { + super.updateViewConstraints() + return + } let minimumSpace: CGFloat = minimumFillSpace() var currentSpace: CGFloat = 0 @@ -89,7 +90,10 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { totalMinimumSpace += minimumSpace } - guard fillTop || fillBottom else { return } + guard fillTop || fillBottom else { + super.updateViewConstraints() + return + } let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace) let width = view.bounds.width @@ -110,6 +114,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { showFooter(width) } } + super.updateViewConstraints() } //MARK: - Header Footer diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index a4cc66d7..91791109 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -42,8 +42,8 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { } open override func updateViewConstraints() { - super.updateViewConstraints() guard let scrollView = scrollView else { + super.updateViewConstraints() return } @@ -52,6 +52,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { } else { heightConstraint?.constant = -scrollView.contentInset.top - scrollView.contentInset.bottom } + super.updateViewConstraints() } open override func loadView() { From 8f4e7f82c3a9eb2d9455d169edbd975b29037575 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 15:10:41 -0400 Subject: [PATCH 109/136] update cells --- .../ProgrammaticTableViewController.swift | 5 +++++ .../ThreeLayerTableViewController.swift | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift index b27845b3..20ec3c43 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift @@ -67,6 +67,11 @@ open class ProgrammaticTableViewController: ProgrammaticScrollViewController, UI tableView.sectionFooterHeight = CGFloat.leastNormalMagnitude } + open func refreshTable() { + tableView.beginUpdates() + tableView.endUpdates() + } + /// For subclassing, returns the number of sections for table. This function calls numberOfSectionsForTableview aftre ensuring the table is setup properly. open func getNumberOfSections() -> Int { return 1 diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index d884af42..a8230381 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -15,7 +15,6 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { private var bottomView: UIView? private var headerView: UIView? private var footerView: UIView? - var useMargins: Bool = true public var bottomViewOutsideOfScrollArea: Bool = false public var topViewOutsideOfScrollArea: Bool = false private var topViewBottomConstraint: NSLayoutConstraint? @@ -113,6 +112,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { bottomViewTopConstraint?.constant = newSpace showFooter(width) } + DispatchQueue.main.async { + self.refreshTable() + } } super.updateViewConstraints() } @@ -162,10 +164,10 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { func showHeader(_ sizingWidth: CGFloat?) { headerView?.removeFromSuperview() tableView?.tableHeaderView = nil - guard let topView = topView, - let headerView = headerView else { return } + guard let headerView = headerView else { return } - if topViewOutsideOfScrollArea { + if topViewOutsideOfScrollArea, + let topView = topView { // put top view outside of scrolling area. topConstraint?.isActive = false view.addSubview(topView) @@ -189,14 +191,14 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { /// Takes the current footerView and adds it to the tableFooterView func showFooter(_ sizingWidth: CGFloat?) { footerView?.removeFromSuperview() - guard let bottomView = bottomView, - let footerView = footerView, + guard let footerView = footerView, let tableView = tableView else { self.tableView?.tableFooterView = nil return } - if bottomViewOutsideOfScrollArea { + if bottomViewOutsideOfScrollArea, + let bottomView = bottomView { // put bottom view outside of scrolling area. bottomConstraint?.isActive = false view.addSubview(bottomView) From e0d17f727044e9a8d84ef8b9d82abd8524e719ef Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 15:20:50 -0400 Subject: [PATCH 110/136] remove unused ? --- MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index a8230381..01eabfe6 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -32,7 +32,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { bottomView.updateView(width) showFooter(width) } - tableView?.reloadData() + tableView.reloadData() } open override func handleNewData() { From a97132c8971618438ce02d0563f20127a0e00dd6 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 16:33:13 -0400 Subject: [PATCH 111/136] three layer collection anchoring --- .../Atomic/Templates/CollectionTemplate.swift | 2 + ...ProgrammaticCollectionViewController.swift | 6 ++- .../ThreeLayerCollectionViewController.swift | 40 +++++++++++++++++-- .../ThreeLayerViewController.swift | 19 ++++----- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift index 1d2f07a6..be4273df 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift @@ -79,6 +79,8 @@ import Foundation open override func handleNewData() { + topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false + bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false setup() registerCells() super.handleNewData() diff --git a/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift index 5e7b87b0..c70a3ef1 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift @@ -12,6 +12,8 @@ import Foundation @objc open class ProgrammaticCollectionViewController: ScrollingViewController { public var collectionView: UICollectionView? + public var topConstraint: NSLayoutConstraint? + public var bottomConstraint: NSLayoutConstraint? open override func loadView() { let view = UIView() @@ -19,7 +21,9 @@ import Foundation let collection = createCollectionView() view.addSubview(collection) - NSLayoutConstraint.constraintPinSubview(toSuperview: collection) + let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: collection) + topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint + bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint collectionView = collection scrollView = collectionView diff --git a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift index e16d760f..63f86ac2 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift @@ -52,16 +52,34 @@ import Foundation footerView?.topConstraint?.constant = half collectionView?.collectionViewLayout.invalidateLayout() } else if fillTop { - // Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one. + // Only top is spaced. headerView?.bottomConstraint?.constant = newSpace collectionView?.collectionViewLayout.invalidateLayout() } else if fillBottom { // Only bottom is spaced. footerView?.topConstraint?.constant = newSpace - collectionView?.collectionViewLayout.invalidateLayout() + collectionView.collectionViewLayout.invalidateLayout() } } } + + func addTopViewOutside() { + guard let collectionView = collectionView, let topView = topView else { return } + view.addSubview(topView) + topView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true + topView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true + view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true + collectionView.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true + } + + func addBottomViewOutside() { + guard let collectionView = collectionView, let bottomView = bottomView else { return } + view.addSubview(bottomView) + bottomView.topAnchor.constraint(equalTo: collectionView.bottomAnchor).isActive = true + bottomView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true + view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true + view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true + } //MARK: - ViewController open override func updateViews() { @@ -86,8 +104,22 @@ import Foundation open override func handleNewData() { super.handleNewData() + topView?.removeFromSuperview() + bottomView?.removeFromSuperview() topView = viewForTop() bottomView = viewForBottom() + if topViewOutsideOfScrollArea { + topConstraint?.isActive = false + addTopViewOutside() + } else { + topConstraint?.isActive = true + } + if bottomViewOutsideOfScrollArea { + bottomConstraint?.isActive = false + addBottomViewOutside() + } else { + bottomConstraint?.isActive = true + } reloadCollectionData() } @@ -176,14 +208,14 @@ import Foundation open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionFooter, let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerID, for: indexPath) as? ContainerCollectionReusableView { - let bottomView = self.bottomView ?? MVMCoreUICommonViewsUtility.getView(with: 0) + let bottomView = (bottomViewOutsideOfScrollArea ? nil : self.bottomView) ?? MVMCoreUICommonViewsUtility.getView(with: 0.5) footerView.addAndContain(view: bottomView) footerView.topConstraint?.constant = spaceAboveBottomView() ?? 0 self.footerView = footerView return footerView } else if kind == UICollectionView.elementKindSectionHeader, let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerID, for: indexPath) as? ContainerCollectionReusableView { - let topView = self.topView ?? MVMCoreUICommonViewsUtility.getView(with: 0) + let topView = (topViewOutsideOfScrollArea ? nil : self.topView) ?? MVMCoreUICommonViewsUtility.getView(with: 0.5) headerView.addAndContain(view: topView) headerView.bottomConstraint?.constant = spaceBelowTopView() ?? 0 self.headerView = headerView diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index 91791109..2b0d60ca 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -117,22 +117,20 @@ extension ThreeLayerViewController { if let topView = viewForTop() { self.topView = topView } else { - topView = MVMCoreUICommonViewsUtility.commonView() - topView?.heightAnchor.constraint(equalToConstant: 0).isActive = true + topView = MVMCoreUICommonViewsUtility.getView(with: 0) } guard var topView = topView else { return nil } // Adds the top view outside the scroll if directed. if topViewOutsideOfScroll { - topConstraint?.isActive = false; + topConstraint?.isActive = false addViewOutsideOfScrollViewTop(topView) // Adds and returns an empty view to use for the internal logic. - topView = MVMCoreUICommonViewsUtility.commonView() - topView.heightAnchor.constraint(equalToConstant: 0).isActive = true + topView = MVMCoreUICommonViewsUtility.getView(with: 0) addViewInsideOfScrollViewTop(topView) } else { - topConstraint?.isActive = true; + topConstraint?.isActive = true addViewInsideOfScrollViewTop(topView) } return topView @@ -142,8 +140,7 @@ extension ThreeLayerViewController { if let middleView = viewForMiddle() { self.middleView = middleView } else { - middleView = MVMCoreUICommonViewsUtility.commonView() - middleView?.heightAnchor.constraint(equalToConstant: 0).isActive = true + middleView = MVMCoreUICommonViewsUtility.getView(with: 0) } guard let middleView = middleView, let contentView = contentView else { return nil } contentView.addSubview(middleView) @@ -157,8 +154,7 @@ extension ThreeLayerViewController { if let bottomView = viewForBottom() { self.bottomView = bottomView } else { - bottomView = MVMCoreUICommonViewsUtility.commonView() - bottomView?.heightAnchor.constraint(equalToConstant: 0).isActive = true + bottomView = MVMCoreUICommonViewsUtility.getView(with: 0) } guard var bottomView = bottomView else { return nil } @@ -168,8 +164,7 @@ extension ThreeLayerViewController { addViewOutsideOfScrollViewBottom(bottomView) // Adds and returns an empty view to use for the internal logic. - bottomView = MVMCoreUICommonViewsUtility.commonView() - bottomView.heightAnchor.constraint(equalToConstant: 0).isActive = true + bottomView = MVMCoreUICommonViewsUtility.getView(with: 0) addViewInsideOfScrollViewBottom(bottomView) } else { bottomConstraint?.isActive = true; From c82b8654045c1385550ce04fc100be29da26e8ea Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 17:36:30 -0400 Subject: [PATCH 112/136] New TableView base --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +++ MVMCoreUI/BaseClasses/TableView.swift | 25 +++++++++++++++++++ .../ProgrammaticTableViewController.swift | 8 +++--- .../ThreeLayerCollectionViewController.swift | 8 +++--- .../ThreeLayerTableViewController.swift | 10 ++++++++ 5 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 MVMCoreUI/BaseClasses/TableView.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d48bba00..6458701e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -240,6 +240,7 @@ D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */; }; D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */; }; D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */; }; + D20923592450ECE00044AD09 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20923582450ECE00044AD09 /* TableView.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; @@ -684,6 +685,7 @@ D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIViewControllerMappingObject+Extension.swift"; sourceTree = ""; }; D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplateModelProtocol.swift; sourceTree = ""; }; D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerModelBase.swift; sourceTree = ""; }; + D20923582450ECE00044AD09 /* TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; @@ -1900,6 +1902,7 @@ D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B802360945C00A9AEDC /* View.swift */, 0AE14F63238315D2005417F8 /* TextField.swift */, + D20923582450ECE00044AD09 /* TableView.swift */, D2755D7A23689C7500485468 /* TableViewCell.swift */, D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */, D264FAA92440F97600D98315 /* CollectionView.swift */, @@ -2245,6 +2248,7 @@ D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */, 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, + D20923592450ECE00044AD09 /* TableView.swift in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */, AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */, diff --git a/MVMCoreUI/BaseClasses/TableView.swift b/MVMCoreUI/BaseClasses/TableView.swift new file mode 100644 index 00000000..9fb07ac7 --- /dev/null +++ b/MVMCoreUI/BaseClasses/TableView.swift @@ -0,0 +1,25 @@ +// +// TableView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/22/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class TableView: UITableView { + + /// A block that gets called on tableview frame changes + public var frameChangeAction: (() -> Void)? + + private var previousFrame = CGRect.zero + + open override func layoutSubviews() { + super.layoutSubviews() + if frame != previousFrame { + frameChangeAction?() + } + previousFrame = frame + } +} diff --git a/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift index 20ec3c43..21f1de1e 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift @@ -9,9 +9,9 @@ import Foundation open class ProgrammaticTableViewController: ProgrammaticScrollViewController, UITableViewDelegate, UITableViewDataSource { - @IBOutlet public var tableView: UITableView! + @IBOutlet public var tableView: TableView! - public init(with tableView: UITableView) { + public init(with tableView: TableView) { self.tableView = tableView super.init(with: tableView) } @@ -48,8 +48,8 @@ open class ProgrammaticTableViewController: ProgrammaticScrollViewController, UI } /// This class should create the table view that will be used here. Subclass this for different table styles. - open func createTableView() -> UITableView { - let tableView = UITableView(frame: .zero, style: .grouped) + open func createTableView() -> TableView { + let tableView = TableView(frame: .zero, style: .grouped) tableView.backgroundColor = .clear tableView.separatorStyle = UITableViewCell.SeparatorStyle.none tableView.delegate = self diff --git a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift index 63f86ac2..29d401f0 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift @@ -22,7 +22,7 @@ import Foundation /// Updates the padding for flexible space (header or footer) private func updateFlexibleSpace() { - guard let tableView = collectionView else { return } + guard false,let collectionView = collectionView else { return } let minimumSpace: CGFloat = minimumFillSpace() var currentSpace: CGFloat = 0 @@ -43,18 +43,18 @@ import Foundation } guard fillTop || fillBottom else { return } - let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace) + let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: collectionView, minimumHeight: totalMinimumSpace) if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpace, 1) { if fillTop && fillBottom { // space both let half = newSpace / 2 headerView?.bottomConstraint?.constant = half footerView?.topConstraint?.constant = half - collectionView?.collectionViewLayout.invalidateLayout() + collectionView.collectionViewLayout.invalidateLayout() } else if fillTop { // Only top is spaced. headerView?.bottomConstraint?.constant = newSpace - collectionView?.collectionViewLayout.invalidateLayout() + collectionView.collectionViewLayout.invalidateLayout() } else if fillBottom { // Only bottom is spaced. footerView?.topConstraint?.constant = newSpace diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 01eabfe6..5cd7086b 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -46,6 +46,11 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { super.viewDidLoad() // Do any additional setup after loading the view. setNoSectionHeadersFooters() + + // Ensures the footer and headers are the right size + tableView.frameChangeAction = { [weak self] in + self?.view.setNeedsUpdateConstraints() + } } //MARK: - Spacing @@ -239,4 +244,9 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { deinit { tableView?.delegate = nil } + + // Ensures the footer and headers are the right size + func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) { + view.setNeedsUpdateConstraints() + } } From 07b02963a6b3455983ac9ac30e0b90bf2118085a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 19:34:43 -0400 Subject: [PATCH 113/136] remove safe area for now until i can find consistency with contentView --- .../ThreeLayerTableViewController.swift | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 5cd7086b..8e01cf6c 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -177,8 +177,8 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { topConstraint?.isActive = false view.addSubview(topView) topView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true - topView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true - view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true + topView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + view.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true tableView.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true } else { topConstraint?.isActive = true @@ -208,21 +208,19 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { bottomConstraint?.isActive = false view.addSubview(bottomView) bottomView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true - bottomView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true - view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true + bottomView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + view.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true } else { bottomConstraint?.isActive = true } - var y: CGFloat? - if let tableFooterView = tableView.tableFooterView { - // if footer already exists, use the same y location to avoid strange moving animation - y = tableFooterView.frame.minY - } + + // if footer already exists, use the same y location to avoid strange moving animation + let y = tableView.tableFooterView?.frame.minY ?? 0.0 // This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout. MVMCoreUIUtility.sizeView(toFit: footerView) - let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height)) + let tableFooterView = UIView(frame: CGRect(x: 0, y: y, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height)) tableFooterView.addSubview(footerView) NSLayoutConstraint.constraintPinSubview(toSuperview: footerView) tableView.tableFooterView = tableFooterView @@ -232,7 +230,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { /// Subclass for a top view. open func viewForTop() -> UIView { // Small height is needed to stop apple from adding padding for grouped tables when no header. - return MVMCoreUICommonViewsUtility.getView(with: 1) + return MVMCoreUICommonViewsUtility.getView(with: 0.5) } /// Subclass for a bottom view. From 79b3b9b0c5dd4ea11bb8dee08c775743a3d71d0c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 20:44:37 -0400 Subject: [PATCH 114/136] three layer fixes --- .../ProgrammaticScrollViewController.swift | 17 ++-- .../ScrollingViewController.swift | 9 +- .../ThreeLayerViewController.swift | 83 +++++++------------ .../Containers/NavigationController.swift | 4 +- 4 files changed, 40 insertions(+), 73 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift index cec6c3fd..19c6f2b7 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift @@ -35,21 +35,20 @@ open class ProgrammaticScrollViewController: ScrollingViewController { view.addSubview(scrollView) // Sets the constraints for the scroll view - let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: scrollView) - topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint - bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint + scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + view.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true + topConstraint = scrollView.topAnchor.constraint(equalTo: view.topAnchor) + topConstraint?.isActive = true + bottomConstraint = view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor) + bottomConstraint?.isActive = true // Sets the constraints for the content view let contentView = MVMCoreUICommonViewsUtility.commonView() scrollView.addSubview(contentView) contentView.leftAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leftAnchor).isActive = true scrollView.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true - contentView.topAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.topAnchor).isActive = true - scrollView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true - - // Super will set later. - contentWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: 320.0) - contentWidthConstraint?.isActive = true + contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true + scrollView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true self.contentView = contentView self.scrollView = scrollView diff --git a/MVMCoreUI/BaseControllers/ScrollingViewController.swift b/MVMCoreUI/BaseControllers/ScrollingViewController.swift index 65812d79..0eea84cc 100644 --- a/MVMCoreUI/BaseControllers/ScrollingViewController.swift +++ b/MVMCoreUI/BaseControllers/ScrollingViewController.swift @@ -12,7 +12,6 @@ open class ScrollingViewController: ViewController { public var dismissKeyboardTapGesture: UITapGestureRecognizer? @IBOutlet public var scrollView: UIScrollView! public var contentView: UIView? - public var contentWidthConstraint: NSLayoutConstraint? private var keyboardNotificationsAdded = false private var keyboardIsShowing = false @@ -42,13 +41,7 @@ open class ScrollingViewController: ViewController { scrollView.alwaysBounceVertical = false scrollView.delegate = self } - - open override func updateViewConstraints() { - // Sets the width of the content to the width of the screen. - contentWidthConstraint?.constant = view.bounds.width - scrollView.contentInset.left - scrollView.contentInset.right - super.updateViewConstraints() - } - + open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() view.setNeedsUpdateConstraints() diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index 2b0d60ca..210148cf 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -41,25 +41,11 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { } } - open override func updateViewConstraints() { - guard let scrollView = scrollView else { - super.updateViewConstraints() - return - } - - if scrollView.contentInsetAdjustmentBehavior == UIScrollView.ContentInsetAdjustmentBehavior.automatic { - heightConstraint?.constant = -scrollView.adjustedContentInset.top - scrollView.adjustedContentInset.bottom - } else { - heightConstraint?.constant = -scrollView.contentInset.top - scrollView.contentInset.bottom - } - super.updateViewConstraints() - } - open override func loadView() { super.loadView() // The height is used to keep the bottom view at the bottom. if let contentView = contentView, let scrollView = scrollView { - heightConstraint = contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor, multiplier: 1.0) + heightConstraint = contentView.heightAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.heightAnchor, multiplier: 1.0) heightConstraint?.priority = UILayoutPriority.defaultLow } } @@ -78,6 +64,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { } // Reset constraints + topConstraint?.isActive = true bottomConstraint?.isActive = true heightConstraint?.isActive = false @@ -113,13 +100,9 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { //MARK:-Setup extension ThreeLayerViewController { - func setupViewAsTop() -> UIView? { - if let topView = viewForTop() { - self.topView = topView - } else { - topView = MVMCoreUICommonViewsUtility.getView(with: 0) - } - guard var topView = topView else { return nil } + func setupViewAsTop() -> UIView { + var topView = viewForTop() ?? MVMCoreUICommonViewsUtility.getView(with: 0) + self.topView = topView // Adds the top view outside the scroll if directed. if topViewOutsideOfScroll { @@ -136,13 +119,11 @@ extension ThreeLayerViewController { return topView } - func setupViewAsMiddle() -> UIView? { - if let middleView = viewForMiddle() { - self.middleView = middleView - } else { - middleView = MVMCoreUICommonViewsUtility.getView(with: 0) - } - guard let middleView = middleView, let contentView = contentView else { return nil } + func setupViewAsMiddle() -> UIView { + let middleView = viewForMiddle() ?? MVMCoreUICommonViewsUtility.getView(with: 0) + self.middleView = middleView + + guard let contentView = contentView else { return middleView } contentView.addSubview(middleView) NSLayoutConstraint.pinViewLeft(toSuperview: middleView, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: middleView, useMargins: useMargins, constant: 0).isActive = true @@ -150,33 +131,30 @@ extension ThreeLayerViewController { return middleView } - func setupViewAsBottom() -> UIView? { - if let bottomView = viewForBottom() { - self.bottomView = bottomView - } else { - bottomView = MVMCoreUICommonViewsUtility.getView(with: 0) - } - guard var bottomView = bottomView else { return nil } + func setupViewAsBottom() -> UIView { + var bottomView = viewForBottom() ?? MVMCoreUICommonViewsUtility.getView(with: 0) + self.bottomView = bottomView // Adds the bottom view outside the scroll if directed. if bottomViewOutsideOfScroll { - bottomConstraint?.isActive = false; + bottomConstraint?.isActive = false addViewOutsideOfScrollViewBottom(bottomView) // Adds and returns an empty view to use for the internal logic. bottomView = MVMCoreUICommonViewsUtility.getView(with: 0) addViewInsideOfScrollViewBottom(bottomView) } else { - bottomConstraint?.isActive = true; + bottomConstraint?.isActive = true addViewInsideOfScrollViewBottom(bottomView) } return bottomView } func setupLayers() { - guard let contentView = contentView, let topView = setupViewAsTop(), let middleView = setupViewAsMiddle(), let bottomView = setupViewAsBottom() else { - return - } + guard let contentView = contentView else { return } + let topView = setupViewAsTop() + let middleView = setupViewAsMiddle() + let bottomView = setupViewAsBottom() let spaceAbove = spaceBetweenTopAndMiddle() let spaceBelow = spaceBetweenMiddleAndBottom() if let spaceAbove = spaceAbove, let spaceBelow = spaceBelow { @@ -202,7 +180,7 @@ extension ThreeLayerViewController { contentView.addSubview(topSpacer) topSpacer.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true contentView.rightAnchor.constraint(equalTo: topSpacer.rightAnchor).isActive = true - topSpacer.heightAnchor.constraint(greaterThanOrEqualToConstant: PaddingTwo).isActive = true + topSpacer.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true topSpacer.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true middleView.topAnchor.constraint(equalTo: topSpacer.bottomAnchor).isActive = true bottomView.topAnchor.constraint(equalTo: middleView.bottomAnchor, constant: spaceBelow).isActive = true @@ -217,7 +195,7 @@ extension ThreeLayerViewController { bottomSpacer.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true contentView.rightAnchor.constraint(equalTo: bottomSpacer.rightAnchor).isActive = true topSpacer.heightAnchor.constraint(equalTo: bottomSpacer.heightAnchor).isActive = true - topSpacer.heightAnchor.constraint(greaterThanOrEqualToConstant: PaddingTwo).isActive = true + topSpacer.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true topSpacer.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true middleView.topAnchor.constraint(equalTo: topSpacer.bottomAnchor).isActive = true bottomSpacer.topAnchor.constraint(equalTo: middleView.bottomAnchor).isActive = true @@ -236,7 +214,7 @@ extension ThreeLayerViewController { func addViewOutsideOfScrollViewTop(_ view: UIView) { guard let scrollView = scrollView, let parentView = self.view else { return } - self.view?.addSubview(view) + parentView.addSubview(view) scrollView.topAnchor.constraint(equalTo: view.bottomAnchor).isActive = true NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true @@ -244,9 +222,7 @@ extension ThreeLayerViewController { } func addViewInsideOfScrollViewBottom(_ view: UIView) { - guard let contentView = contentView else { - return - } + guard let contentView = contentView else { return } contentView.addSubview(view); NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true @@ -254,12 +230,11 @@ extension ThreeLayerViewController { } func addViewOutsideOfScrollViewBottom(_ view: UIView) { - self.view?.addSubview(view) - if let scrollView = scrollView, let parentView = self.view { - view.topAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true - NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true - NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true - parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true - } + guard let scrollView = scrollView, let parentView = self.view else { return } + parentView.addSubview(view) + view.topAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true + NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true + parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true } } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 03d73240..f278236c 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -64,8 +64,8 @@ import UIKit if navigationController == MVMCoreUISplitViewController.main()?.navigationController, navigationController.topViewController == viewController { // Update Panels - MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton ?? false, for: viewController) - MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton ?? false, for: viewController) + MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton , for: viewController) + MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton , for: viewController) MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint) } } From 03abdd3a9130829761145baceb93051e2970f27d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 21:03:13 -0400 Subject: [PATCH 115/136] update collection for sizing properly --- MVMCoreUI/BaseClasses/CollectionView.swift | 13 +++++++++++++ .../ProgrammaticCollectionViewController.swift | 4 ++-- .../ThreeLayerCollectionViewController.swift | 6 +++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/BaseClasses/CollectionView.swift b/MVMCoreUI/BaseClasses/CollectionView.swift index a1a57376..4b034462 100644 --- a/MVMCoreUI/BaseClasses/CollectionView.swift +++ b/MVMCoreUI/BaseClasses/CollectionView.swift @@ -10,6 +10,11 @@ import Foundation open class CollectionView: UICollectionView, MVMCoreViewProtocol { + /// A block that gets called on tableview frame changes + public var frameChangeAction: (() -> Void)? + + private var previousFrame = CGRect.zero + private var initialSetupPerformed = false private func initialSetup() { @@ -29,6 +34,14 @@ open class CollectionView: UICollectionView, MVMCoreViewProtocol { initialSetup() } + open override func layoutSubviews() { + super.layoutSubviews() + if frame != previousFrame { + frameChangeAction?() + } + previousFrame = frame + } + public func updateView(_ size: CGFloat) { for cell in visibleCells { (cell as? MVMCoreViewProtocol)?.updateView(size) diff --git a/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift index c70a3ef1..85e0f3a7 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticCollectionViewController.swift @@ -11,7 +11,7 @@ import Foundation /// A base view controller with a collection view. @objc open class ProgrammaticCollectionViewController: ScrollingViewController { - public var collectionView: UICollectionView? + public var collectionView: CollectionView? public var topConstraint: NSLayoutConstraint? public var bottomConstraint: NSLayoutConstraint? @@ -49,7 +49,7 @@ import Foundation } /// Creates the collection view. - open func createCollectionView() -> UICollectionView { + open func createCollectionView() -> CollectionView { let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) collection.dataSource = self collection.delegate = self diff --git a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift index 29d401f0..880f5525 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift @@ -22,7 +22,7 @@ import Foundation /// Updates the padding for flexible space (header or footer) private func updateFlexibleSpace() { - guard false,let collectionView = collectionView else { return } + guard let collectionView = collectionView else { return } let minimumSpace: CGFloat = minimumFillSpace() var currentSpace: CGFloat = 0 @@ -126,6 +126,10 @@ import Foundation override open func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. + + collectionView?.frameChangeAction = { [weak self] in + self?.invalidateCollectionLayout() + } } //MARK: - Spacing From a094326ffbc1cb3c19eac38a3dafd97405fe75fb Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 21:17:57 -0400 Subject: [PATCH 116/136] use convenience function --- .../ContainerCollectionReusableView.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ContainerCollectionReusableView.swift b/MVMCoreUI/BaseControllers/ContainerCollectionReusableView.swift index d7fb0ed4..c59fd097 100644 --- a/MVMCoreUI/BaseControllers/ContainerCollectionReusableView.swift +++ b/MVMCoreUI/BaseControllers/ContainerCollectionReusableView.swift @@ -20,11 +20,8 @@ public class ContainerCollectionReusableView: UICollectionReusableView { view.setContentCompressionResistancePriority(.required, for: .vertical) addSubview(view) self.view = view - topConstraint = view.topAnchor.constraint(equalTo: topAnchor) - topConstraint?.isActive = true - bottomConstraint = bottomAnchor.constraint(equalTo: view.bottomAnchor) - bottomConstraint?.isActive = true - rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true - view.leftAnchor.constraint(equalTo: leftAnchor).isActive = true + let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: view) + topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint + bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint } } From ba16c18b957b508fe59dd1262f1e731a8abfc3f3 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 22 Apr 2020 21:42:55 -0400 Subject: [PATCH 117/136] fix sizing defect --- .../ThreeLayerCollectionViewController.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift index 880f5525..88d8157a 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerCollectionViewController.swift @@ -20,6 +20,12 @@ import Foundation public var bottomViewOutsideOfScrollArea: Bool = false public var topViewOutsideOfScrollArea: Bool = false + open override func updateViewConstraints() { + // Update the spacing on constraint update + updateFlexibleSpace() + super.updateViewConstraints() + } + /// Updates the padding for flexible space (header or footer) private func updateFlexibleSpace() { guard let collectionView = collectionView else { return } From ea6dd35952b2299cc328b30757a690d6a948b822 Mon Sep 17 00:00:00 2001 From: Damodaram <> Date: Thu, 23 Apr 2020 15:09:51 +0530 Subject: [PATCH 118/136] code alignment --- .../DesignedComponents/List/ListDeviceComplexButtonMedium.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift index 90e0fc60..441fc55f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift @@ -61,6 +61,7 @@ import Foundation open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 120 } + public func setDefault() { eyebrow.styleRegularMicro(true) headline.styleBoldTitleMedium(true) From a89511f10ca1fe919ad7edff5a04ef2bf377fe09 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 23 Apr 2020 10:43:55 -0400 Subject: [PATCH 119/136] code fixes --- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 2 +- .../List/ThreeColumn/ListThreeColumnDataUsage.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 66e6ff3f..7c57fd40 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -150,8 +150,8 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) - MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift index 2611943a..5e7d39c6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ThreeColumn/ListThreeColumnDataUsage.swift @@ -22,9 +22,9 @@ import Foundation // MARK: - Initializers //------------------------------------------------------ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 35, horizontalAlignment: .leading)), - (view: centerLabel, model: StackItemModel(percent: 35, horizontalAlignment: .leading)), - (view: rightLabel, model: StackItemModel(percent: 30, horizontalAlignment: .center))], + stack = Stack.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) } From ee1d847a41f264a156e8177f5e92f2f0e6bc53c7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 23 Apr 2020 11:43:55 -0400 Subject: [PATCH 120/136] minor --- MVMCoreUI.xcodeproj/project.pbxproj | 12 ++++++++++-- .../{ => Device}/ListDeviceComplexButtonMedium.swift | 8 ++++---- .../ListDeviceComplexButtonMediumModel.swift | 0 3 files changed, 14 insertions(+), 6 deletions(-) rename MVMCoreUI/Atomic/Molecules/DesignedComponents/List/{ => Device}/ListDeviceComplexButtonMedium.swift (92%) rename MVMCoreUI/Atomic/Molecules/DesignedComponents/List/{ => Device}/ListDeviceComplexButtonMediumModel.swift (100%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 6b8d0855..e98e8f7e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -1172,6 +1172,15 @@ path = FourColumn; sourceTree = ""; }; + D20FFFB42451E32100A31DA2 /* Device */ = { + isa = PBXGroup; + children = ( + BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */, + BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */, + ); + path = Device; + sourceTree = ""; + }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -1370,8 +1379,7 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( - BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */, - BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */, + D20FFFB42451E32100A31DA2 /* Device */, 52267A0523FFE0A900906CBA /* OneColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */, 8DD1E36C243B3CD900D8F2DF /* ThreeColumn */, diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift similarity index 92% rename from MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift index 441fc55f..a62a6d9b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift @@ -26,10 +26,10 @@ import Foundation (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.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading,verticalAlignment: .center)), - (view: rightImageView, model: StackItemModel(horizontalAlignment: .fill,verticalAlignment: .center))], + (view: button, model: StackItemModel(spacing:16, horizontalAlignment: .leading))], + axis: .vertical, spacing: 0) + stack = Stack.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) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListDeviceComplexButtonMediumModel.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift From be0c9b874288f0e295a6355022c7eb4e3fa36388 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 23 Apr 2020 12:25:26 -0400 Subject: [PATCH 121/136] Image stretch fix New convenience function for set/gone/restack --- .../ListDeviceComplexButtonMedium.swift | 14 +++++----- MVMCoreUI/Atomic/Organisms/Stack.swift | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift index a62a6d9b..f8ab918d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift @@ -15,11 +15,12 @@ import Foundation public let body = Label.createLabelRegularBodySmall(true) public let body2 = Label.createLabelRegularBodySmall(true) public let button = PillButton(frame: .zero) - public let rightImageView = MFLoadImageView(pinnedEdges: .all) + public let rightImageView = MFLoadImageView() public var stack: Stack // 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.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .leading)), @@ -50,11 +51,12 @@ import Foundation 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 } - eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) - headline.setOptional(with: model.headline, delegateObject, additionalData) - body.setOptional(with: model.body, delegateObject, additionalData) - body2.setOptional(with: model.body2, delegateObject, additionalData) - button.set(with: model.button, delegateObject, additionalData) + verticalStack.updateContainedMolecules(with: [model.eyebrow, + model.headline, + model.body, + model.body2, + model.button], + delegateObject, additionalData) rightImageView.set(with: model.image, delegateObject, additionalData) } diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index f539cf8b..ad961586 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -62,6 +62,32 @@ open class Stack: 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 //-------------------------------------------------- From 4b23a63823f8440fd45172f424e0149b3ddf4b80 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 23 Apr 2020 12:30:07 -0400 Subject: [PATCH 122/136] update others --- ...neColumnFullWidthTextAllTextAndLinks.swift | 20 +++++++------------ .../EyebrowHeadlineBodyLink.swift | 18 ++++++----------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 1ea1a4a9..ad74039a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -40,24 +40,18 @@ import Foundation override open func setupView() { super.setupView() addMolecule(stack) + stack.restack() } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){ super.set(with: model, delegateObject, additionalData) guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return } - eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) - headline.setOptional(with: model.headline, delegateObject, additionalData) - subHeadline.setOptional(with: model.subHeadline, delegateObject, additionalData) - body.setOptional(with: model.body, delegateObject, additionalData) - link.setOptional(with: 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() + stack.updateContainedMolecules(with: [model.eyebrow, + model.headline, + model.subHeadline, + model.body, + model.link], + delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index 82f83530..dd04140b 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -33,6 +33,7 @@ import UIKit stack.stackModel?.spacing = 0 addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) + stack.restack() } open override func updateView(_ size: CGFloat) { @@ -58,18 +59,11 @@ import UIKit open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - - eyebrow.setOptional(with: castModel?.eyebrow, delegateObject, additionalData) - headline.setOptional(with: castModel?.headline, delegateObject, additionalData) - body.setOptional(with: castModel?.body, delegateObject, additionalData) - link.setOptional(with: castModel?.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 = !body.hasText - stack.stackModel?.molecules[3].gone = (link.titleLabel?.text?.count ?? 0) == 0 - stack.restack() + stack.updateContainedMolecules(with: [castModel?.eyebrow, + castModel?.headline, + castModel?.body, + castModel?.link], + delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { From d3a73939f0f2c60e25029e08254a2b84f6c46d90 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 23 Apr 2020 15:13:29 -0400 Subject: [PATCH 123/136] container protocol updates and container model --- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../HeadersH2NoButtonsBodyTextModel.swift | 4 +- MVMCoreUI/Atomic/Molecules/FooterModel.swift | 39 +++----------- MVMCoreUI/Atomic/Molecules/HeaderModel.swift | 12 ++--- .../Molecules/Items/ListItemModel.swift | 8 +-- .../Items/MoleculeCollectionItemModel.swift | 27 +++------- .../Items/MoleculeCollectionViewCell.swift | 2 +- .../Items/MoleculeStackItemModel.swift | 12 ++--- .../Molecules/Items/StackItemModel.swift | 11 ++-- .../Molecules/Items/TabsListItemModel.swift | 4 +- .../Atomic/Molecules/ScrollerModel.swift | 7 +-- .../BGImageHeadlineBodyButtonModel.swift | 12 ++--- .../HeadlineBodyCaretLinkImageModel.swift | 12 ++--- .../ContainerModelProtocol.swift | 10 ++-- MVMCoreUI/BaseClasses/TableViewCell.swift | 20 +++---- .../Views/Container/ContainerHelper.swift | 9 +++- .../Views/Container/ContainerModel.swift | 52 ++++++++++++++----- .../Containers/Views/MoleculeContainer.swift | 4 +- .../Views/MoleculeContainerModel.swift | 11 +++- 19 files changed, 129 insertions(+), 128 deletions(-) diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 464238a7..e01bfe3b 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -120,6 +120,7 @@ import Foundation // Other Container Molecules + MoleculeObjectMapping.shared()?.register(viewClass: MoleculeContainer.self, viewModelClass: MoleculeContainerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self) MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyTextModel.swift index eb5502eb..816db00d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyTextModel.swift @@ -25,8 +25,8 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol public override func setDefaults() { super.setDefaults() - topMarginPadding = PaddingDefaultVerticalSpacing3 - bottomMarginPadding = PaddingDefaultVerticalSpacing3 + topPadding = PaddingDefaultVerticalSpacing3 + bottomPadding = PaddingDefaultVerticalSpacing3 } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/FooterModel.swift b/MVMCoreUI/Atomic/Molecules/FooterModel.swift index d61d1194..12e0eca8 100644 --- a/MVMCoreUI/Atomic/Molecules/FooterModel.swift +++ b/MVMCoreUI/Atomic/Molecules/FooterModel.swift @@ -9,47 +9,24 @@ import Foundation -@objcMembers public class FooterModel: MoleculeContainerModel, MoleculeModelProtocol { - public static var identifier: String = "footer" - public var backgroundColor: Color? - - private enum CodingKeys: String, CodingKey { - case moleculeName - case backgroundColor +@objcMembers public class FooterModel: MoleculeContainerModel { + public override class var identifier: String { + return "footer" } /// Defaults to set - func setDefaults() { + public override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } if useVerticalMargins == nil { useVerticalMargins = true } - if topMarginPadding == nil { - topMarginPadding = PaddingDefaultVerticalSpacing + if topPadding == nil { + topPadding = PaddingDefaultVerticalSpacing } - if bottomMarginPadding == nil { - bottomMarginPadding = PaddingDefaultVerticalSpacing + if bottomPadding == nil { + bottomPadding = PaddingDefaultVerticalSpacing } } - - public override init(with moleculeModel: MoleculeModelProtocol) { - super.init(with: moleculeModel) - setDefaults() - } - - required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - try super.init(from: decoder) - setDefaults() - } - - 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(backgroundColor, forKey: .backgroundColor) - } } diff --git a/MVMCoreUI/Atomic/Molecules/HeaderModel.swift b/MVMCoreUI/Atomic/Molecules/HeaderModel.swift index 6314947c..09fe077f 100644 --- a/MVMCoreUI/Atomic/Molecules/HeaderModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HeaderModel.swift @@ -18,18 +18,18 @@ import Foundation } /// Defaults to set - public func setDefaults() { + public override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } if useVerticalMargins == nil { useVerticalMargins = true } - if topMarginPadding == nil { - topMarginPadding = PaddingDefaultVerticalSpacing + if topPadding == nil { + topPadding = PaddingDefaultVerticalSpacing } - if bottomMarginPadding == nil { - bottomMarginPadding = PaddingDefaultVerticalSpacing + if bottomPadding == nil { + bottomPadding = PaddingDefaultVerticalSpacing } if line == nil { line = LineModel(type: .heavy) @@ -38,7 +38,6 @@ import Foundation public override init() { super.init() - setDefaults() } required public init(from decoder: Decoder) throws { @@ -46,7 +45,6 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - setDefaults() } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift index 9a00a94d..8fdb4d77 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift @@ -38,7 +38,7 @@ import Foundation //-------------------------------------------------- /// Defaults to set - open func setDefaults() { + open override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } @@ -54,9 +54,12 @@ import Foundation // MARK: - Initializer //-------------------------------------------------- + public override init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, useHorizontalMargins: Bool? = nil, leftPadding: CGFloat? = nil, rightPadding: CGFloat? = nil, useVerticalMargins: Bool? = nil, topPadding: CGFloat? = nil, bottomPadding: CGFloat? = nil) { + super.init(horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment, useHorizontalMargins: useHorizontalMargins, leftPadding: leftPadding, rightPadding: rightPadding, useVerticalMargins: useVerticalMargins, topPadding: topPadding, bottomPadding: bottomPadding) + } + public override init() { super.init() - setDefaults() } //-------------------------------------------------- @@ -71,7 +74,6 @@ import Foundation line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) style = try typeContainer.decodeIfPresent(String.self, forKey: .style) try super.init(from: decoder) - setDefaults() } open override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionItemModel.swift index ed9467fd..4f203813 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionItemModel.swift @@ -9,49 +9,36 @@ import Foundation /// A model for a collection item that is a container for any molecule. -@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol, MoleculeModelProtocol { - open class var identifier: String { +@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol { + open override class var identifier: String { return "collectionItem" } - public var backgroundColor: Color? /// Defaults to set - public func setDefaults() { + public override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } if useVerticalMargins == nil { useVerticalMargins = true } - if topMarginPadding == nil { - topMarginPadding = PaddingDefault + if topPadding == nil { + topPadding = PaddingDefault } - if bottomMarginPadding == nil { - bottomMarginPadding = PaddingDefault + if bottomPadding == nil { + bottomPadding = PaddingDefault } } - private enum CodingKeys: String, CodingKey { - case moleculeName - case backgroundColor - } - public override init(with moleculeModel: MoleculeModelProtocol) { super.init(with: moleculeModel) - setDefaults() } required public init(from decoder: Decoder) throws { - let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) - setDefaults() } 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(backgroundColor, forKey: .backgroundColor) } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift index 42af1a53..10b51bff 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeCollectionViewCell.swift @@ -54,6 +54,6 @@ open class MoleculeCollectionViewCell: CollectionViewCell { let height = classType.estimatedHeight(with: model.molecule, delegateObject) else { return 100 } - return height + (model.topMarginPadding ?? 0) + (model.bottomMarginPadding ?? 0) + return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0) } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift index 1a6bced6..1f6e4d88 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeStackItemModel.swift @@ -8,16 +8,15 @@ import Foundation -@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, MoleculeModelProtocol, StackItemModelProtocol { - public static var identifier: String = "stackItem" - public var backgroundColor: Color? +@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, StackItemModelProtocol { + public override class var identifier: String { + return "stackItem" + } public var spacing: CGFloat? public var percent: Int? public var gone: Bool = false private enum CodingKeys: String, CodingKey { - case moleculeName - case backgroundColor case spacing case percent case gone @@ -34,17 +33,14 @@ import Foundation if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) { self.gone = gone } - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) 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(spacing, forKey: .spacing) try container.encodeIfPresent(percent, forKey: .percent) try container.encode(gone, forKey: .gone) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/StackItemModel.swift index 436ed9cd..69fe570d 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/StackItemModel.swift @@ -24,16 +24,17 @@ import Foundation // MARK: - Initializer //-------------------------------------------------- - public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) { - self.init() - - self.horizontalAlignment = horizontalAlignment - self.verticalAlignment = verticalAlignment + public init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) { self.spacing = spacing self.percent = percent if let gone = gone { self.gone = gone } + super.init(horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment) + } + + required public init(from decoder: Decoder) throws { + fatalError("init(from:) has not been implemented") } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift index e49b4adb..c83b8933 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift @@ -24,8 +24,8 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol { hideArrow = true action = nil style = nil - topMarginPadding = 8 - bottomMarginPadding = 0 + topPadding = 8 + bottomPadding = 0 } public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) { diff --git a/MVMCoreUI/Atomic/Molecules/ScrollerModel.swift b/MVMCoreUI/Atomic/Molecules/ScrollerModel.swift index 74256e99..697556b5 100644 --- a/MVMCoreUI/Atomic/Molecules/ScrollerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/ScrollerModel.swift @@ -8,8 +8,9 @@ import UIKit -public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol { - public static var identifier: String = "scroller" +public class ScrollerModel: MoleculeContainerModel { + public override class var identifier: String { + return "scroller" + } public var moleculeName: String = ScrollerModel.identifier - public var backgroundColor: Color? } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift index 650e4875..f6fd4fcf 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift @@ -20,22 +20,21 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc self.headlineBody = headlineBody self.image = image super.init() - setDefaults() } /// Defaults to set - func setDefaults() { + public override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } if useVerticalMargins == nil { useVerticalMargins = true } - if topMarginPadding == nil { - topMarginPadding = PaddingDefault + if topPadding == nil { + topPadding = PaddingDefault } - if bottomMarginPadding == nil { - bottomMarginPadding = PaddingDefault + if bottomPadding == nil { + bottomPadding = PaddingDefault } if image.height == nil { image.height = BGImageHeadlineBodyButton.heightConstant @@ -59,7 +58,6 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc image = try typeContainer.decode(ImageViewModel.self, forKey: .image) button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button) try super.init(from: decoder) - setDefaults() } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift index f30b89ff..9fdd8612 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyCaretLinkImageModel.swift @@ -19,22 +19,21 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto self.headlineBody = headlineBody self.image = image super.init() - setDefaults() } /// Defaults to set - func setDefaults() { + public override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } if useVerticalMargins == nil { useVerticalMargins = true } - if topMarginPadding == nil { - topMarginPadding = PaddingDefault + if topPadding == nil { + topPadding = PaddingDefault } - if bottomMarginPadding == nil { - bottomMarginPadding = PaddingDefault + if bottomPadding == nil { + bottomPadding = PaddingDefault } if image.height == nil { image.height = HeadLineBodyCaretLinkImage.heightConstant @@ -56,7 +55,6 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto image = try typeContainer.decode(ImageViewModel.self, forKey: .image) caretLink = try typeContainer.decodeIfPresent(CaretLinkModel.self, forKey: .caretLink) try super.init(from: decoder) - setDefaults() } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ContainerModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ContainerModelProtocol.swift index bc230731..29e25903 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ContainerModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ContainerModelProtocol.swift @@ -11,10 +11,12 @@ import Foundation public protocol ContainerModelProtocol { var horizontalAlignment: UIStackView.Alignment? { get set } - var verticalAlignment: UIStackView.Alignment? { get set } var useHorizontalMargins: Bool? { get set } - + var leftPadding: CGFloat? { get set } + var rightPadding: CGFloat? { get set } + + var verticalAlignment: UIStackView.Alignment? { get set } var useVerticalMargins: Bool? { get set } - var topMarginPadding: CGFloat? { get set } - var bottomMarginPadding: CGFloat? { get set } + var topPadding: CGFloat? { get set } + var bottomPadding: CGFloat? { get set } } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index f27a38d8..30f9df22 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -51,36 +51,36 @@ import UIKit } open func styleStandard() { - listItemModel?.topMarginPadding = 24 - listItemModel?.bottomMarginPadding = 24 + listItemModel?.topPadding = 24 + listItemModel?.bottomPadding = 24 topSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.standard) } open func styleTallDivider() { - listItemModel?.topMarginPadding = 48 - listItemModel?.bottomMarginPadding = 16 + listItemModel?.topPadding = 48 + listItemModel?.bottomPadding = 16 topSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.thin) } open func styleShortDivider() { - listItemModel?.topMarginPadding = 32 - listItemModel?.bottomMarginPadding = 16 + listItemModel?.topPadding = 32 + listItemModel?.bottomPadding = 16 topSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.thin) } open func styleFooter() { - listItemModel?.topMarginPadding = 24 - listItemModel?.bottomMarginPadding = 0 + listItemModel?.topPadding = 24 + listItemModel?.bottomPadding = 0 topSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.none) } open func styleNone() { - listItemModel?.topMarginPadding = 0 - listItemModel?.bottomMarginPadding = 0 + listItemModel?.topPadding = 0 + listItemModel?.bottomPadding = 0 topSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.none) } diff --git a/MVMCoreUI/Containers/Views/Container/ContainerHelper.swift b/MVMCoreUI/Containers/Views/Container/ContainerHelper.swift index 223589fe..4ce97f5c 100644 --- a/MVMCoreUI/Containers/Views/Container/ContainerHelper.swift +++ b/MVMCoreUI/Containers/Views/Container/ContainerHelper.swift @@ -169,8 +169,15 @@ open class ContainerHelper: NSObject { } } + /// Updates the view margins according to model and size. If useHorizontalMargins is true, we will try to use the left and right padding, else we will default to the normal gutters. If useVerticalMargins is true, we will try to use the top and bottom padding. All else, we use zero. open func updateViewMargins(_ view: UIView, model: ContainerModelProtocol?, size: CGFloat) { - MFStyler.setMarginsFor(view, size: size, defaultHorizontal: model?.useHorizontalMargins ?? false, top: (model?.useVerticalMargins ?? false) ? (model?.topMarginPadding ?? 0) : 0, bottom: (model?.useVerticalMargins ?? false) ? (model?.bottomMarginPadding ?? 0) : 0) + let left = (model?.useHorizontalMargins ?? false) ? (model?.leftPadding ?? Padding.Component.horizontalPaddingForSize(size)) : 0.0 + let right = (model?.useHorizontalMargins ?? false) ? (model?.rightPadding ?? Padding.Component.horizontalPaddingForSize(size)) : 0.0 + let top = (model?.useVerticalMargins ?? false) ? (model?.topPadding ?? 0.0) : 0.0 + let bottom = (model?.useVerticalMargins ?? false) ? (model?.bottomPadding ?? 0.0) : 0.0 + MVMCoreDispatchUtility.performBlock(onMainThread: { + MVMCoreUIUtility.setMarginsFor(view, leading: left, top: top, trailing: right, bottom: bottom) + }) } open func set(with model: ContainerModelProtocol, for contained: MVMCoreUIViewConstrainingProtocol?) { diff --git a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift index ec6f9769..ea7d8012 100644 --- a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift +++ b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift @@ -9,41 +9,61 @@ import Foundation open class ContainerModel: ContainerModelProtocol, Codable { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public var horizontalAlignment: UIStackView.Alignment? - public var verticalAlignment: UIStackView.Alignment? public var useHorizontalMargins: Bool? + public var leftPadding: CGFloat? + public var rightPadding: CGFloat? + public var verticalAlignment: UIStackView.Alignment? public var useVerticalMargins: Bool? - public var topMarginPadding: CGFloat? - public var bottomMarginPadding: CGFloat? + public var topPadding: CGFloat? + public var bottomPadding: CGFloat? //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case verticalAlignment case horizontalAlignment case useHorizontalMargins + case leftPadding + case rightPadding + case verticalAlignment case useVerticalMargins - case topMarginPadding - case bottomMarginPadding + case topPadding + case bottomPadding } + //-------------------------------------------------- + // MARK: - Subclassable + //-------------------------------------------------- + + /// Sets the default values. Should be called on init. + public func setDefaults() {} + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- - public init() {} + public init() { + setDefaults() + } - public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) { - self.init() + public init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, useHorizontalMargins: Bool? = nil, leftPadding: CGFloat? = nil, rightPadding: CGFloat? = nil, useVerticalMargins: Bool? = nil, topPadding: CGFloat? = nil, bottomPadding: CGFloat? = nil) { self.horizontalAlignment = horizontalAlignment self.verticalAlignment = verticalAlignment + self.useHorizontalMargins = useHorizontalMargins + self.leftPadding = leftPadding + self.rightPadding = rightPadding + self.useVerticalMargins = useVerticalMargins + self.topPadding = topPadding + self.bottomPadding = bottomPadding + setDefaults() } //-------------------------------------------------- @@ -59,9 +79,12 @@ open class ContainerModel: ContainerModelProtocol, Codable { horizontalAlignment = ContainerHelper.getAlignment(for: horizontalAlignmentString) } useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins) + leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding) + rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding) useVerticalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalMargins) - topMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .topMarginPadding) - bottomMarginPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .bottomMarginPadding) + topPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .topPadding) + bottomPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .bottomPadding) + setDefaults() } open func encode(to encoder: Encoder) throws { @@ -69,9 +92,10 @@ open class ContainerModel: ContainerModelProtocol, Codable { try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: verticalAlignment), forKey: .verticalAlignment) try container.encodeIfPresent(ContainerHelper.getAlignmentString(for: horizontalAlignment), forKey: .horizontalAlignment) try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins) + try container.encodeIfPresent(leftPadding, forKey: .leftPadding) + try container.encodeIfPresent(rightPadding, forKey: .rightPadding) try container.encodeIfPresent(useVerticalMargins, forKey: .useVerticalMargins) - // TODO: can add this back once we have type erasures. - //try container.encodeIfPresent(topMarginPadding, forKey: .topMarginPadding) - //try container.encodeIfPresent(bottomMarginPadding, forKey: .bottomMarginPadding) + try container.encodeIfPresent(topPadding, forKey: .topPadding) + try container.encodeIfPresent(bottomPadding, forKey: .bottomPadding) } } diff --git a/MVMCoreUI/Containers/Views/MoleculeContainer.swift b/MVMCoreUI/Containers/Views/MoleculeContainer.swift index 98ecfa28..4e2c6279 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainer.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainer.swift @@ -41,9 +41,9 @@ open class MoleculeContainer: Container { guard let containerModel = model as? MoleculeContainerModelProtocol else { return 0 } guard let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(containerModel.molecule), let moleculeHeight = moleculeClass.estimatedHeight(with: containerModel.molecule, delegateObject) else { - return (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) + return (containerModel.topPadding ?? 0) + (containerModel.bottomPadding ?? 0) } - return moleculeHeight + (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) + return moleculeHeight + (containerModel.topPadding ?? 0) + (containerModel.bottomPadding ?? 0) } public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift b/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift index 01116a48..86693823 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift @@ -8,11 +8,17 @@ import Foundation -public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol { +public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol { + public class var identifier: String { + return "container" + } + public var backgroundColor: Color? public var molecule: MoleculeModelProtocol private enum CodingKeys: String, CodingKey { + case moleculeName case molecule + case backgroundColor } public init(with moleculeModel: MoleculeModelProtocol) { @@ -23,12 +29,15 @@ public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProto required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) molecule = try typeContainer.decodeModel(codingKey: .molecule) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) 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.encodeModel(molecule, forKey: .molecule) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } } From 0f4c11e2f2b7e9cd906c66eb537d9296b6fe5aef Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 24 Apr 2020 12:40:11 +0530 Subject: [PATCH 124/136] Code cleanup and realigned file structure. --- MVMCoreUI.xcodeproj/project.pbxproj | 12 ++--------- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 3 +-- .../ListDeviceComplexLinkMedium.swift | 21 ++++++++----------- .../ListDeviceComplexLinkMediumModel.swift | 18 ++++------------ 4 files changed, 16 insertions(+), 38 deletions(-) rename MVMCoreUI/Atomic/Molecules/DesignedComponents/List/{DeviceItems => Device}/ListDeviceComplexLinkMedium.swift (65%) rename MVMCoreUI/Atomic/Molecules/DesignedComponents/List/{DeviceItems => Device}/ListDeviceComplexLinkMediumModel.swift (78%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2b5f17be..6511b1d2 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -1122,15 +1122,6 @@ name = "Recovered References"; sourceTree = ""; }; - AA2AD114244EE43900BBFFE3 /* DeviceItems */ = { - isa = PBXGroup; - children = ( - AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */, - AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */, - ); - path = DeviceItems; - sourceTree = ""; - }; AA4FC2A323F4F69600E251DB /* RightVariable */ = { isa = PBXGroup; children = ( @@ -1190,6 +1181,8 @@ children = ( BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */, BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */, + AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */, + AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */, ); path = Device; sourceTree = ""; @@ -1393,7 +1386,6 @@ isa = PBXGroup; children = ( D20FFFB42451E32100A31DA2 /* Device */, - AA2AD114244EE43900BBFFE3 /* DeviceItems */, 52267A0523FFE0A900906CBA /* OneColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */, 8DD1E36C243B3CD900D8F2DF /* ThreeColumn */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 3ea55ae6..55aa6e9a 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -152,7 +152,6 @@ import Foundation 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: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self) // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) @@ -169,9 +168,9 @@ import Foundation // Designed Headers MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) - // Device Items MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self) // TODO: Need View try? ModelRegistry.register(TabsModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift similarity index 65% rename from MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift index 53c957b4..e829554a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift @@ -12,23 +12,23 @@ import Foundation //----------------------------------------------------- // MARK: - Outlets //----------------------------------------------------- - private let stack: Stack 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 link = Link() - public let rightImage = MFLoadImageView(pinnedEdges: .all) - let leftStack: Stack + public let rightImage = MFLoadImageView() + let verticalStack: Stack + public let stack: Stack //------------------------------------------------------ // MARK: - Initializers //------------------------------------------------------ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - leftStack = Stack.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: link, model: StackItemModel(horizontalAlignment: .leading))], axis: .vertical, spacing: 0) - leftStack.stackModel?.molecules[4].spacing = 16 rightImage.addSizeConstraintsForAspectRatio = true - stack = Stack.createStack(with: [(view: leftStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal) + verticalStack = Stack.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: link, model: StackItemModel(spacing: 16, horizontalAlignment: .leading))], axis: .vertical, spacing: 0) + + stack = Stack.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal) super.init(style: style, reuseIdentifier: reuseIdentifier) } @@ -43,7 +43,7 @@ import Foundation super.setupView() addMolecule(stack) stack.restack() - leftStack.restack() + verticalStack.restack() } //------------------------------------------------------ @@ -52,11 +52,7 @@ import Foundation open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? ListDeviceComplexLinkMediumModel else { return } - eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) - headline.setOptional(with: model.headline, delegateObject, additionalData) - body.setOptional(with: model.body, delegateObject, additionalData) - body2.setOptional(with: model.body2, delegateObject, additionalData) - link.set(with: model.link, delegateObject, additionalData) + verticalStack.updateContainedMolecules(with: [model.eyebrow, model.headline, model.body, model.body2, model.link], delegateObject, additionalData) rightImage.set(with: model.image, delegateObject, additionalData) } @@ -70,6 +66,7 @@ import Foundation headline.styleBoldTitleMedium(true) body.styleRegularBodySmall(true) body2.styleRegularBodySmall(true) + eyebrow.textColor = .mvmCoolGray6 } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift similarity index 78% rename from MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift index 683a7d52..66c88183 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/DeviceItems/ListDeviceComplexLinkMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift @@ -8,7 +8,6 @@ import Foundation public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProtocol { - public static var identifier: String = "listDvcLnkM" public var eyebrow: LabelModel? public var headline: LabelModel? @@ -30,7 +29,6 @@ public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProto /// Defaults to set override public func setDefaults() { super.setDefaults() - eyebrow?.textColor = Color(uiColor: .mvmCoolGray6) if image.width == nil, image.height == nil { image.width = 116 image.height = 116 @@ -49,18 +47,10 @@ public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProto required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - if let eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) { - self.eyebrow = eyebrow - } - if let headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) { - self.headline = headline - } - if let body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) { - self.body = body - } - if let body2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body2) { - self.body2 = body2 - } + 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) link = try typeContainer.decode(LinkModel.self, forKey: .link) image = try typeContainer.decode(ImageViewModel.self, forKey: .image) try super.init(from: decoder) From 4ede519024dc20a49bac39749d33ad8e2835fedd Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 24 Apr 2020 16:38:42 +0530 Subject: [PATCH 125/136] Minor changes --- .../List/Device/ListDeviceComplexLinkMedium.swift | 2 ++ .../List/Device/ListDeviceComplexLinkMediumModel.swift | 9 --------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift index e829554a..4875e563 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift @@ -26,6 +26,8 @@ import Foundation //------------------------------------------------------ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { rightImage.addSizeConstraintsForAspectRatio = true + rightImage.heightAnchor.constraint(equalToConstant: 116.0).isActive = true + rightImage.widthAnchor.constraint(equalToConstant: 116.0).isActive = true verticalStack = Stack.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: link, model: StackItemModel(spacing: 16, horizontalAlignment: .leading))], axis: .vertical, spacing: 0) stack = Stack.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift index 66c88183..b85a6539 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift @@ -26,15 +26,6 @@ public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProto super.init() } - /// Defaults to set - override public func setDefaults() { - super.setDefaults() - if image.width == nil, image.height == nil { - image.width = 116 - image.height = 116 - } - } - private enum CodingKeys: String, CodingKey { case moleculeName case eyebrow From 283524d72b3dc0e34c17fc25fab439cabf2e1be3 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 24 Apr 2020 16:47:42 +0530 Subject: [PATCH 126/136] 19121(iOS - List - Device - Complex - Link - Small) story commit --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 2 +- .../Device/ListDeviceComplexLinkSmall.swift | 73 +++++++++++++++++++ .../ListDeviceComplexLinkSmallModel.swift | 61 ++++++++++++++++ 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift create mode 100644 MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e98e8f7e..60d9cc58 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -196,6 +196,8 @@ AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; + AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA617AAF2453010A00910B8F /* ListDeviceComplexLinkSmall.swift */; }; + AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA617AB12453012400910B8F /* ListDeviceComplexLinkSmallModel.swift */; }; AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; }; AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */; }; AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; @@ -639,6 +641,8 @@ AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = ""; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = ""; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = ""; }; + AA617AAF2453010A00910B8F /* ListDeviceComplexLinkSmall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkSmall.swift; sourceTree = ""; }; + AA617AB12453012400910B8F /* ListDeviceComplexLinkSmallModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkSmallModel.swift; sourceTree = ""; }; AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = ""; }; AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; @@ -1177,6 +1181,8 @@ children = ( BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */, BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */, + AA617AB12453012400910B8F /* ListDeviceComplexLinkSmallModel.swift */, + AA617AAF2453010A00910B8F /* ListDeviceComplexLinkSmall.swift */, ); path = Device; sourceTree = ""; @@ -2167,6 +2173,7 @@ D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, + AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */, @@ -2363,6 +2370,7 @@ 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, + AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 464238a7..c3f8639f 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -168,9 +168,9 @@ import Foundation // Designed Headers MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) - // Device Items MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkSmall.self, viewModelClass: ListDeviceComplexLinkSmallModel.self) // TODO: Need View try? ModelRegistry.register(TabsModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift new file mode 100644 index 00000000..c57b3b18 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift @@ -0,0 +1,73 @@ +// +// ListDeviceComplexLinkSmall.swift +// MVMCoreUI +// +// Created by Lekshmi S on 24/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers open class ListDeviceComplexLinkSmall: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + 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 link = Link() + public let rightImage = MFLoadImageView() + let verticalStack: Stack + public let stack: Stack + + //------------------------------------------------------ + // MARK: - Initializers + //------------------------------------------------------ + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + rightImage.addSizeConstraintsForAspectRatio = true + rightImage.heightAnchor.constraint(equalToConstant: 71.0).isActive = true + rightImage.widthAnchor.constraint(equalToConstant: 71.0).isActive = true + verticalStack = Stack.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: link, model: StackItemModel(spacing: 16, horizontalAlignment: .leading))], axis: .vertical, spacing: 0) + + stack = Stack.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //----------------------------------------------------- + open override func setupView() { + super.setupView() + addMolecule(stack) + stack.restack() + verticalStack.restack() + } + + //------------------------------------------------------ + // MARK: - Molecule + //------------------------------------------------------ + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListDeviceComplexLinkSmallModel else { return } + verticalStack.updateContainedMolecules(with: [model.eyebrow, model.headline, model.body, model.body2, model.link], delegateObject, additionalData) + rightImage.set(with: model.image, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 120 + } + + open override func reset() { + super.reset() + eyebrow.styleRegularMicro(true) + headline.styleBoldTitleMedium(true) + body.styleRegularBodySmall(true) + body2.styleRegularBodySmall(true) + eyebrow.textColor = .mvmCoolGray6 + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift new file mode 100644 index 00000000..03eeb902 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift @@ -0,0 +1,61 @@ +// +// ListDeviceComplexLinkSmallModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 24/04/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +public class ListDeviceComplexLinkSmallModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "listDvcLnkS" + public var eyebrow: LabelModel? + public var headline: LabelModel? + public var body: LabelModel? + public var body2: LabelModel? + public var link: LinkModel + public var image: ImageViewModel + + public init(eyebrow: LabelModel, headline: LabelModel, body: LabelModel, body2: LabelModel, link: LinkModel, image: ImageViewModel) { + self.eyebrow = eyebrow + self.headline = headline + self.body = body + self.body2 = body2 + self.link = link + self.image = image + super.init() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrow + case headline + case body + case body2 + case link + 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) + link = try typeContainer.decode(LinkModel.self, forKey: .link) + 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(link, forKey: .link) + try container.encode(image, forKey: .image) + } +} From e854eef315fe27d0cacc728ea578f307ea701e3d Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 24 Apr 2020 16:53:12 +0530 Subject: [PATCH 127/136] Removed extra line. --- .../List/Device/ListDeviceComplexLinkMedium.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift index 4875e563..f6e18184 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift @@ -71,4 +71,3 @@ import Foundation eyebrow.textColor = .mvmCoolGray6 } } - From 0dc329894218500c38e30202182b560b81019ae0 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Apr 2020 10:30:23 -0400 Subject: [PATCH 128/136] adding accessibility state to radio button --- .../Atomic/Atoms/Selectors/RadioButton.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index 1a968b7a..af1e7905 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -23,6 +23,7 @@ import UIKit public override var isSelected: Bool { didSet { radioModel?.state = isSelected + updateAccessibilityLabel() } } @@ -118,6 +119,19 @@ import UIKit return radioModel?.fieldValue } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + /// Adjust accessibility label based on state of RadioButton. + func updateAccessibilityLabel() { + // Attention: This needs to be addressed with the accessibility team. + // NOTE: Currently emptying description part of MVMCoreUICheckBox accessibility label to avoid crashing! + if let state = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { + accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", state) + } + } + //-------------------------------------------------- // MARK: - MVMViewProtocol //-------------------------------------------------- @@ -136,14 +150,15 @@ import UIKit isAccessibilityElement = true accessibilityTraits = .button accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + updateAccessibilityLabel() } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) + self.delegateObject = delegateObject guard let model = model as? RadioButtonModel else { return } - self.delegateObject = delegateObject isSelected = model.state isEnabled = model.enabled RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject) From 9620548a43030f590025cd6f8fb23a1d1168722d Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Apr 2020 10:33:14 -0400 Subject: [PATCH 129/136] updates and revision --- .../Atomic/Atoms/Selectors/RadioButton.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index af1e7905..8d2563d0 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -19,14 +19,14 @@ import UIKit widthConstraint?.constant = diameter } } - + public override var isSelected: Bool { didSet { radioModel?.state = isSelected updateAccessibilityLabel() } } - + public var enabledColor: UIColor = .mvmBlack public var disabledColor: UIColor = .mvmCoolGray3 public var delegateObject: MVMCoreUIDelegateObject? @@ -40,12 +40,12 @@ import UIKit }() lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { - if let radioGroupName = radioGroupName, - let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] { - return radioButtonModel - } else { - return nil - } + + guard let radioGroupName = radioGroupName, + let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] + else { return nil } + + return radioButtonModel }() public override var isEnabled: Bool { @@ -128,7 +128,7 @@ import UIKit // Attention: This needs to be addressed with the accessibility team. // NOTE: Currently emptying description part of MVMCoreUICheckBox accessibility label to avoid crashing! if let state = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { - accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", state) + accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", isSelected) } } From 181ed2f6b0191bf95cbeaf020995cf87a84ce37a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 24 Apr 2020 11:38:57 -0400 Subject: [PATCH 130/136] add convenience inits. --- MVMCoreUI/Actions/ActionCollapseNotificationModel.swift | 7 ++++++- MVMCoreUI/Actions/ActionOpenPanelModel.swift | 4 +++- MVMCoreUI/Actions/ActionTopAlertModel.swift | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift index 581c8687..4663d539 100644 --- a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift +++ b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift @@ -11,7 +11,12 @@ import UIKit @objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol { public static var identifier: String = "collapseNotification" - public var actionType: String + public var actionType: String = ActionCollapseNotificationModel.identifier public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? + + public init(_ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) { + self.extraParameters = extraParameters + self.analyticsData = analyticsData + } } diff --git a/MVMCoreUI/Actions/ActionOpenPanelModel.swift b/MVMCoreUI/Actions/ActionOpenPanelModel.swift index 9149b32b..eaad4746 100644 --- a/MVMCoreUI/Actions/ActionOpenPanelModel.swift +++ b/MVMCoreUI/Actions/ActionOpenPanelModel.swift @@ -23,7 +23,9 @@ public class ActionOpenPanelModel: ActionModelProtocol { public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? - public init(panel: Panel) { + public init(panel: Panel, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) { self.panel = panel + self.extraParameters = extraParameters + self.analyticsData = analyticsData } } diff --git a/MVMCoreUI/Actions/ActionTopAlertModel.swift b/MVMCoreUI/Actions/ActionTopAlertModel.swift index 82d9fa17..62e496c2 100644 --- a/MVMCoreUI/Actions/ActionTopAlertModel.swift +++ b/MVMCoreUI/Actions/ActionTopAlertModel.swift @@ -16,7 +16,9 @@ import Foundation public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? - public init(pageType: String) { + public init(pageType: String, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) { self.pageType = pageType + self.extraParameters = extraParameters + self.analyticsData = analyticsData } } From ac29a7d885f331abb56bfdaee231f3f18169500a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 24 Apr 2020 16:04:41 -0400 Subject: [PATCH 131/136] remove space --- .../List/Device/ListDeviceComplexLinkMediumModel.swift | 2 +- .../List/Device/ListDeviceComplexLinkSmallModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift index b85a6539..c07d7788 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMediumModel.swift @@ -47,7 +47,7 @@ public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProto try super.init(from: decoder) } - public override func encode(to encoder: Encoder) throws { + 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) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift index 03eeb902..a0b3047b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmallModel.swift @@ -47,7 +47,7 @@ public class ListDeviceComplexLinkSmallModel: ListItemModel, MoleculeModelProtoc try super.init(from: decoder) } - public override func encode(to encoder: Encoder) throws { + 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) From 77811e1f246d98b5f970d2e33539785d5c51658f Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Apr 2020 16:39:23 -0400 Subject: [PATCH 132/136] revised --- MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index 8d2563d0..2b22fcee 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -125,10 +125,9 @@ import UIKit /// Adjust accessibility label based on state of RadioButton. func updateAccessibilityLabel() { - // Attention: This needs to be addressed with the accessibility team. - // NOTE: Currently emptying description part of MVMCoreUICheckBox accessibility label to avoid crashing! + if let state = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { - accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", isSelected) + accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", state) } } From 6fec6b53f29ef37443ae046bdf146bd8eb129847 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 13:00:42 -0400 Subject: [PATCH 133/136] update legacy font --- MVMCoreUI/Utility/MFFonts.m | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 533b3a87..99ad05c4 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -84,15 +84,19 @@ NSString * const DS55Rg = @"NHaasGroteskDSStd-55Rg"; + (nonnull UIFont *)mfFont75Bd:(CGFloat)size { - [self loadMVMFonts]; - UIFont *font = [UIFont fontWithName:DS75Bd size:size]; - return font ?: [UIFont boldSystemFontOfSize:size]; + if (size >= 15) { + return [MFFonts mfFontDSBold:size]; + } else { + return [MFFonts mfFontTXBold:size]; + } } + (nonnull UIFont *)mfFont55Rg:(CGFloat)size { - [self loadMVMFonts]; - UIFont *font = [UIFont fontWithName:DS55Rg size:size]; - return font ?: [UIFont systemFontOfSize:size]; + if (size >= 15) { + return [MFFonts mfFontDSRegular:size]; + } else { + return [MFFonts mfFontTXRegular:size]; + } } + (nullable UIFont *)mfFontOcratxt:(CGFloat)size { From 320976e5ae836762535bc6fb7b360b838030e40e Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 14:09:37 -0400 Subject: [PATCH 134/136] weak delegate --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 2 +- .../Atomic/Molecules/HorizontalCombinationViews/Tabs.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 6bb82fe1..03454d06 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -41,7 +41,7 @@ import UIKit // MARK: - Delegate //-------------------------------------------------- - weak var delegateObject: MVMCoreUIDelegateObject? + var delegateObject: MVMCoreUIDelegateObject? //-------------------------------------------------- // MARK: - Stored Properties diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index d49cd414..6caa6a03 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -32,7 +32,7 @@ import UIKit var bottomLineWidthConstraint: NSLayoutConstraint? //delegate - public var delegate: TabsDelegate? + weak public var delegate: TabsDelegate? //control var public var heightConstraint: NSLayoutConstraint? @@ -93,7 +93,7 @@ import UIKit bottomScrollView.delegate = self addSubview(bottomScrollView) bottomScrollView.addSubview(bottomContentView) - bottomLine.backgroundColor = .mfTomatoRed() + bottomLine.backgroundColor = .mvmRed bottomContentView.addSubview(bottomLine) bringSubviewToFront(bottomScrollView) } From 3b23101710b802566ad4492832e6c8a4f943fa27 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 15:22:40 -0400 Subject: [PATCH 135/136] update tabs model --- .../HorizontalCombinationViews/Tabs.swift | 53 ++++++------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 6caa6a03..dc8b9cae 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -31,6 +31,8 @@ import UIKit var bottomLineLeftConstraint: NSLayoutConstraint? var bottomLineWidthConstraint: NSLayoutConstraint? + private var widthLabel = Label() + //delegate weak public var delegate: TabsDelegate? @@ -186,11 +188,14 @@ extension Tabs: UICollectionViewDelegateFlowLayout { return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight) } + //pre calculate the width of the collection cell + //when user select tabs, it will reload related collectionview, if we use autosize, it would relayout the width, need to keep the cell width constant. func getLabelWidth(_ labelModel: LabelModel?) -> CGSize { guard let labelModel = labelModel else { return .zero} - let label = Label() - label.set(with: labelModel, nil, nil) - return label.intrinsicContentSize + widthLabel.set(with: labelModel, nil, nil) + let cgSize = widthLabel.intrinsicContentSize + widthLabel.reset() + return cgSize } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { @@ -244,6 +249,10 @@ extension Tabs: UICollectionViewDelegateFlowLayout { extension Tabs: UIScrollViewDelegate { public func scrollViewDidScroll(_ scrollView: UIScrollView) { + /*bottomScrollview is subview of self, it's not belongs to collectionview. + When collectionview is scrolling, bottomScrollView will stay without moving + Adding collectionview's offset to bottomScrollView, will make the bottomScrollview looks like scrolling with the selected tab item. + */ guard let offsetX = collectionView?.contentOffset.x else { return } bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false) } @@ -272,46 +281,14 @@ extension Tabs { animationBlock() } } - - public func progress(fromIndex: Int, toIndex: Int, progressPercentage percent: CGFloat) { - guard let _ = collectionView else { return } - MVMCoreDispatchUtility.performBlock(onMainThread: { - self.setBottomLine(fromIndex: IndexPath(row: fromIndex, section: 0), toIndex: IndexPath(row: toIndex, section: 0), percent: percent) - }) - } - - func setBottomLine(fromIndex: IndexPath, toIndex: IndexPath, percent: CGFloat) { - guard let fromCell = collectionView?.cellForItem(at: fromIndex) as? TabItemCell, let toCell = collectionView?.cellForItem(at: toIndex) as? TabItemCell else { - return - } - let fromWidth = getLabelWidth(fromCell.labelModel).width - let toWidth = getLabelWidth(toCell.labelModel).width - let finalWidth = (toWidth - fromWidth) * percent + fromWidth - bottomLineWidthConstraint?.constant = finalWidth - let xDifference = toCell.frame.origin.x - fromCell.frame.origin.x - let finalX = xDifference * percent + fromCell.frame.origin.x - bottomLineLeftConstraint?.constant = finalX - bottomContentView.layoutIfNeeded() - } } - - -@objcMembers public class TabItemCell: UICollectionViewCell { +@objcMembers public class TabItemCell: CollectionViewCell { public let label = Label() public var labelModel: LabelModel? - override init(frame: CGRect) { - super.init(frame: frame) - setupView() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setupView() - } - - func setupView() { + public override func setupView() { + super.setupView() contentView.addSubview(label) NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true) label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true From af3c373d0a3cad0f7dc526150aa54ab0c31484f1 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 16:38:08 -0400 Subject: [PATCH 136/136] update acc before do animation --- MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m index 6fc7121f..bc45656e 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m @@ -301,11 +301,12 @@ [weakSelf.viewToLayout layoutIfNeeded]; }; + //accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed + weakSelf.accessibilityElements = @[weakSelf.buttonView]; + weakSelf.shortView.isAccessibilityElement = NO; + weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel]; + void(^completion)(void) = ^(void) { - //accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed - weakSelf.accessibilityElements = @[weakSelf.buttonView]; - weakSelf.shortView.isAccessibilityElement = NO; - weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.buttonView.label); [operation markAsFinished]; };