From 35e7052abbc806d8541ba20b8349fe203183380c Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Tue, 4 Feb 2020 14:10:01 +0530 Subject: [PATCH 01/96] WIP: LabelsWithCircleProgressBar --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ .../LabelsWithCircleProgressBar.swift | 91 +++++++++++++++++++ .../LabelsWithCircleProgressBarModel.swift | 50 ++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 2 + 4 files changed, 151 insertions(+) create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index a35514cb..4edba1af 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -130,6 +130,8 @@ C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */; }; C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5123C77A4900A3614A /* NumberedList.swift */; }; C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; + C7F8012123E8303200396FBD /* LabelsWithCircleProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012023E8303200396FBD /* LabelsWithCircleProgressBar.swift */; }; + C7F8012323E846C300396FBD /* LabelsWithCircleProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* LabelsWithCircleProgressBarModel.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -442,6 +444,8 @@ C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeStack.swift; sourceTree = ""; }; C6FA7D5123C77A4900A3614A /* NumberedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedList.swift; sourceTree = ""; }; C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; + C7F8012023E8303200396FBD /* LabelsWithCircleProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelsWithCircleProgressBar.swift; sourceTree = ""; }; + C7F8012223E846C300396FBD /* LabelsWithCircleProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelsWithCircleProgressBarModel.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -859,6 +863,8 @@ C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */, D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */, 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, + C7F8012023E8303200396FBD /* LabelsWithCircleProgressBar.swift */, + C7F8012223E846C300396FBD /* LabelsWithCircleProgressBarModel.swift */, ); path = VerticalCombinationViews; sourceTree = ""; @@ -1586,6 +1592,7 @@ D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */, D28A838D23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, + C7F8012323E846C300396FBD /* LabelsWithCircleProgressBarModel.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, @@ -1680,6 +1687,7 @@ D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */, D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, + C7F8012123E8303200396FBD /* LabelsWithCircleProgressBar.swift in Sources */, D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift new file mode 100644 index 00000000..016403c8 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift @@ -0,0 +1,91 @@ +// +// LabelsWithCircleProgressBar.swift +// MVMCoreUI +// +// Created by Arora, Prateek on 20/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers public class LabelsWithCircleProgressBar: Container { + + let progressBar = GraphView(frame: .zero) + let leftLabel = Label(frame: .zero) + let rightLabel = Label(frame: .zero) + let leftLabelWidthConstant : CGFloat = 151.0 + let rightLabelWidthConstant : CGFloat = 84.0 + let progressBarTrailingConstant : CGFloat = -92.0 + let progressBarLeadingConstant : CGFloat = 195.0 + // MARK: - MVMCoreViewProtocol + open override func updateView(_ size: CGFloat) { + super.updateView(size) + progressBar.updateView(size) + leftLabel.updateView(size) + rightLabel.updateView(size) + } + + open override func setupView() { + super.setupView() + guard leftLabel.superview == nil else { + return + } + let container = MVMCoreUICommonViewsUtility.commonView() + addAndContain(container) + container.addSubview(progressBar) + container.addSubview(leftLabel) + container.addSubview(rightLabel) + + self.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + leftLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor), + leftLabel.topAnchor.constraint(equalTo: container.topAnchor), + leftLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), + leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) + ]) + + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:-PaddingHorizontalBetweenRelatedItems) + NSLayoutConstraint.activate([ + rightLabelTrailing, + rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor), + rightLabel.topAnchor.constraint(equalTo: container.topAnchor), + rightLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), + rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) + ]) + rightLabelTrailing.priority = .defaultHigh + + NSLayoutConstraint.activate([ + progressBar.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:progressBarTrailingConstant), + progressBar.topAnchor.constraint(equalTo: container.topAnchor), + progressBar.bottomAnchor.constraint(equalTo: container.bottomAnchor), + ]) + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + leftLabel.setWithJSON(json?.optionalDictionaryForKey("leftLabel"), delegateObject: delegateObject, additionalData: additionalData) + rightLabel.setWithJSON(json?.optionalDictionaryForKey("rightLabel"), delegateObject: delegateObject, additionalData: additionalData) + progressBar.setWithJSON(json?.optionalDictionaryForKey("progressBar"), delegateObject: delegateObject, additionalData: additionalData) + } + + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? LabelsWithCircleProgressBarModel else { return } + leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) + rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) + progressBar.setWithModel(model.progressBar, delegateObject, additionalData) + } + // MARK:- ModelMoleculeViewProtocol + + open override func reset() { + super.reset() + leftLabel.reset() + rightLabel.reset() + progressBar.reset() + } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 43 + } +} diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift new file mode 100644 index 00000000..9d4af2b6 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift @@ -0,0 +1,50 @@ +// +// LabelsWithCircleProgressBarModel.swift +// MVMCoreUI +// +// Created by Arora, Prateek on 03/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { + + public var backgroundColor: Color? + + public static var identifier: String = "labelsWithCircleProgressBar" + public var leftLabel: LabelModel + public var rightLabel: LabelModel + public var progressBar : CircleProgressModel + + init(leftLabel: LabelModel, rightLabel: LabelModel, progressBar: CircleProgressModel) { + self.leftLabel = leftLabel + self.rightLabel = rightLabel + self.progressBar = progressBar + } + + + private enum CodingKeys: String, CodingKey { + case moleculeName + case leftLabel + case rightLabel + case progressBar + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) + rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) + progressBar = try typeContainer.decode(CircleProgressModel.self, forKey: .progressBar) + } + + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(LabelsWithCircleProgressBarModel.identifier, forKey: .moleculeName) + try container.encode(leftLabel, forKey: .leftLabel) + try container.encode(rightLabel, forKey: .rightLabel) + try container.encodeIfPresent(progressBar, forKey: .progressBar) + } + +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index d3523ccf..76be5d23 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -62,6 +62,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: EyebrowHeadlineBodyLink.self, viewModelClass: EyebrowHeadlineBodyLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLink.self, viewModelClass: HeadlineBodyLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyButton.self, viewModelClass: HeadlineBodyButtonModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass:LabelsWithCircleProgressBar.self, viewModelClass: LabelsWithCircleProgressBarModel.self) // Left Right Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CornerLabels.self, viewModelClass: CornerLabelsModel.self) @@ -102,6 +103,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButton.self, forKey: "radioButton" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButtonLabel.self, forKey: "radioButtonLabel" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MVMCoreUIPageControl.self, forKey: "barsPager" as NSString) + // TODO: Need View ModelRegistry.register(TabsModel.self) From d56335d1036c3aa33ba8a7050303aeaa5ff94e3c Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 6 Feb 2020 16:59:42 +0530 Subject: [PATCH 02/96] Progress bar molecule changes --- .../LabelsWithCircleProgressBar.swift | 5 ++--- .../LabelsWithCircleProgressBarModel.swift | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift index 016403c8..f1913627 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift @@ -14,8 +14,7 @@ import Foundation let rightLabel = Label(frame: .zero) let leftLabelWidthConstant : CGFloat = 151.0 let rightLabelWidthConstant : CGFloat = 84.0 - let progressBarTrailingConstant : CGFloat = -92.0 - let progressBarLeadingConstant : CGFloat = 195.0 + let progressBarTrailingConstant : CGFloat = -100.0 // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { super.updateView(size) @@ -43,7 +42,7 @@ import Foundation leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) ]) - let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:-PaddingHorizontalBetweenRelatedItems) + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:0) NSLayoutConstraint.activate([ rightLabelTrailing, rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor), diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift index 9d4af2b6..9d7e6c02 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift @@ -36,6 +36,8 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) progressBar = try typeContainer.decode(CircleProgressModel.self, forKey: .progressBar) + progressBar.size = .small; + progressBar.style = .unlimited; } From 07d8ef5d13daecd05b598344c56065b1f09e129a Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 6 Feb 2020 17:30:29 +0530 Subject: [PATCH 03/96] Progress bar molecule changes --- .../LabelsWithCircleProgressBar.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift index f1913627..d109cbe8 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift @@ -14,7 +14,7 @@ import Foundation let rightLabel = Label(frame: .zero) let leftLabelWidthConstant : CGFloat = 151.0 let rightLabelWidthConstant : CGFloat = 84.0 - let progressBarTrailingConstant : CGFloat = -100.0 + let progressBarTrailingConstant : CGFloat = -72.0 // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { super.updateView(size) @@ -42,10 +42,10 @@ import Foundation leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) ]) - let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:0) + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor) NSLayoutConstraint.activate([ rightLabelTrailing, - rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor), + rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor, constant: 8.0), rightLabel.topAnchor.constraint(equalTo: container.topAnchor), rightLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) From 8f225dda70d44296e4b65a8dc07922d3e704f202 Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 6 Feb 2020 18:19:15 +0530 Subject: [PATCH 04/96] Code clean --- .../LabelsWithCircleProgressBar.swift | 70 ++++++++++--------- .../LabelsWithCircleProgressBarModel.swift | 7 -- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift index d109cbe8..a636aa05 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift @@ -8,66 +8,70 @@ import Foundation @objcMembers public class LabelsWithCircleProgressBar: Container { - + let progressBar = GraphView(frame: .zero) let leftLabel = Label(frame: .zero) let rightLabel = Label(frame: .zero) let leftLabelWidthConstant : CGFloat = 151.0 let rightLabelWidthConstant : CGFloat = 84.0 let progressBarTrailingConstant : CGFloat = -72.0 - // MARK: - MVMCoreViewProtocol + let rightLabelLeadingAnchorConstant : CGFloat = 8.0 + + //------------------------------------------------- + // MARK: - View Cycle + //------------------------------------------------- open override func updateView(_ size: CGFloat) { super.updateView(size) progressBar.updateView(size) leftLabel.updateView(size) rightLabel.updateView(size) } - + + //------------------------------------------------- + // MARK: - Setup + //------------------------------------------------- open override func setupView() { super.setupView() guard leftLabel.superview == nil else { - return + return } let container = MVMCoreUICommonViewsUtility.commonView() addAndContain(container) container.addSubview(progressBar) container.addSubview(leftLabel) container.addSubview(rightLabel) - + + //------------------------------------------------- + // MARK: - Constraining + //------------------------------------------------- self.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ - leftLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor), - leftLabel.topAnchor.constraint(equalTo: container.topAnchor), - leftLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), - leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) + leftLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor), + leftLabel.topAnchor.constraint(equalTo: container.topAnchor), + leftLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), + leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) ]) let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor) NSLayoutConstraint.activate([ - rightLabelTrailing, - rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor, constant: 8.0), - rightLabel.topAnchor.constraint(equalTo: container.topAnchor), - rightLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), - rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) - ]) + rightLabelTrailing, + rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor, constant: rightLabelLeadingAnchorConstant), + rightLabel.topAnchor.constraint(equalTo: container.topAnchor), + rightLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), + rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) + ]) rightLabelTrailing.priority = .defaultHigh NSLayoutConstraint.activate([ - progressBar.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:progressBarTrailingConstant), - progressBar.topAnchor.constraint(equalTo: container.topAnchor), - progressBar.bottomAnchor.constraint(equalTo: container.bottomAnchor), + progressBar.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:progressBarTrailingConstant), + progressBar.topAnchor.constraint(equalTo: container.topAnchor), + progressBar.bottomAnchor.constraint(equalTo: container.bottomAnchor), ]) } - - // MARK: - MVMCoreUIMoleculeViewProtocol - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - leftLabel.setWithJSON(json?.optionalDictionaryForKey("leftLabel"), delegateObject: delegateObject, additionalData: additionalData) - rightLabel.setWithJSON(json?.optionalDictionaryForKey("rightLabel"), delegateObject: delegateObject, additionalData: additionalData) - progressBar.setWithJSON(json?.optionalDictionaryForKey("progressBar"), delegateObject: delegateObject, additionalData: additionalData) - } - + //------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //------------------------------------------------- public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? LabelsWithCircleProgressBarModel else { return } @@ -75,8 +79,10 @@ import Foundation rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) progressBar.setWithModel(model.progressBar, delegateObject, additionalData) } - // MARK:- ModelMoleculeViewProtocol - + + //------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //------------------------------------------------- open override func reset() { super.reset() leftLabel.reset() @@ -84,7 +90,7 @@ import Foundation progressBar.reset() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 43 - } + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 43 + } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift index 9d7e6c02..557a5364 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift @@ -11,7 +11,6 @@ import Foundation public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { public var backgroundColor: Color? - public static var identifier: String = "labelsWithCircleProgressBar" public var leftLabel: LabelModel public var rightLabel: LabelModel @@ -22,15 +21,12 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { self.rightLabel = rightLabel self.progressBar = progressBar } - - private enum CodingKeys: String, CodingKey { case moleculeName case leftLabel case rightLabel case progressBar } - required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) @@ -39,8 +35,6 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { progressBar.size = .small; progressBar.style = .unlimited; } - - public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(LabelsWithCircleProgressBarModel.identifier, forKey: .moleculeName) @@ -48,5 +42,4 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { try container.encode(rightLabel, forKey: .rightLabel) try container.encodeIfPresent(progressBar, forKey: .progressBar) } - } From b6762fc45516ac59da77d31cf983e6b82475ef12 Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 6 Feb 2020 18:21:28 +0530 Subject: [PATCH 05/96] Extra space removal --- MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 76be5d23..5c9cf5d5 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -103,7 +103,6 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButton.self, forKey: "radioButton" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButtonLabel.self, forKey: "radioButtonLabel" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MVMCoreUIPageControl.self, forKey: "barsPager" as NSString) - // TODO: Need View ModelRegistry.register(TabsModel.self) From 21c749489c673d9086ba8819ec8c3cabef39114a Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 6 Feb 2020 20:20:04 +0530 Subject: [PATCH 06/96] Review Comments --- .../LabelsWithCircleProgressBar.swift | 5 ++--- .../LabelsWithCircleProgressBarModel.swift | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift index a636aa05..9dba7558 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift @@ -51,8 +51,9 @@ import Foundation leftLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) ]) - + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor) + rightLabelTrailing.priority = .defaultHigh NSLayoutConstraint.activate([ rightLabelTrailing, rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor, constant: rightLabelLeadingAnchorConstant), @@ -60,8 +61,6 @@ import Foundation rightLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) ]) - rightLabelTrailing.priority = .defaultHigh - NSLayoutConstraint.activate([ progressBar.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:progressBarTrailingConstant), progressBar.topAnchor.constraint(equalTo: container.topAnchor), diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift index 557a5364..759b47e2 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift @@ -12,9 +12,9 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "labelsWithCircleProgressBar" - public var leftLabel: LabelModel - public var rightLabel: LabelModel - public var progressBar : CircleProgressModel + public var leftLabel: LabelModel? + public var rightLabel: LabelModel? + public var progressBar : CircleProgressModel? init(leftLabel: LabelModel, rightLabel: LabelModel, progressBar: CircleProgressModel) { self.leftLabel = leftLabel @@ -32,8 +32,8 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) progressBar = try typeContainer.decode(CircleProgressModel.self, forKey: .progressBar) - progressBar.size = .small; - progressBar.style = .unlimited; + progressBar?.size = .small; + progressBar?.style = .unlimited; } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) From 7572bf0214535f8972665b40efc074c26b942cb6 Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Fri, 7 Feb 2020 13:48:35 +0530 Subject: [PATCH 07/96] Fixes as per Review comments --- MVMCoreUI/Atoms/Views/CircleProgressModel.swift | 2 ++ .../LabelsWithCircleProgressBarModel.swift | 7 +------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift index feb69083..e7224ca8 100644 --- a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -73,6 +73,8 @@ public class CircleProgressModel: MoleculeModelProtocol { self.colors = colors } backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + updateSize() + updateStyle() } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift index 759b47e2..e55d5199 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift @@ -7,21 +7,18 @@ // import Foundation - public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { - public var backgroundColor: Color? public static var identifier: String = "labelsWithCircleProgressBar" public var leftLabel: LabelModel? public var rightLabel: LabelModel? public var progressBar : CircleProgressModel? - init(leftLabel: LabelModel, rightLabel: LabelModel, progressBar: CircleProgressModel) { self.leftLabel = leftLabel self.rightLabel = rightLabel self.progressBar = progressBar } - private enum CodingKeys: String, CodingKey { + private enum CodingKeys: String,CodingKey { case moleculeName case leftLabel case rightLabel @@ -32,8 +29,6 @@ public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) progressBar = try typeContainer.decode(CircleProgressModel.self, forKey: .progressBar) - progressBar?.size = .small; - progressBar?.style = .unlimited; } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) From 5ae5cfd2d8b5eeb9a2a2d872fec77add009766c5 Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Fri, 7 Feb 2020 17:03:33 +0530 Subject: [PATCH 08/96] WIP: New molecule changes --- MVMCoreUI.xcodeproj/project.pbxproj | 16 +++---- ...cleProgressBar.swift => ListRVWheel.swift} | 46 +++++++++---------- ...sBarModel.swift => ListRVWheelModel.swift} | 29 ++++++++---- .../OtherHandlers/MoleculeObjectMapping.swift | 2 +- 4 files changed, 51 insertions(+), 42 deletions(-) rename MVMCoreUI/Molecules/VerticalCombinationViews/{LabelsWithCircleProgressBar.swift => ListRVWheel.swift} (65%) rename MVMCoreUI/Molecules/VerticalCombinationViews/{LabelsWithCircleProgressBarModel.swift => ListRVWheelModel.swift} (53%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2d33a957..b2be14ab 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -134,8 +134,8 @@ C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */; }; C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FA7D5123C77A4900A3614A /* NumberedList.swift */; }; C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; - C7F8012123E8303200396FBD /* LabelsWithCircleProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012023E8303200396FBD /* LabelsWithCircleProgressBar.swift */; }; - C7F8012323E846C300396FBD /* LabelsWithCircleProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* LabelsWithCircleProgressBarModel.swift */; }; + C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012023E8303200396FBD /* ListRVWheel.swift */; }; + C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; @@ -452,8 +452,8 @@ C6FA7D5023C77A4800A3614A /* StringAndMoleculeStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeStack.swift; sourceTree = ""; }; C6FA7D5123C77A4900A3614A /* NumberedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberedList.swift; sourceTree = ""; }; C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; - C7F8012023E8303200396FBD /* LabelsWithCircleProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelsWithCircleProgressBar.swift; sourceTree = ""; }; - C7F8012223E846C300396FBD /* LabelsWithCircleProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelsWithCircleProgressBarModel.swift; sourceTree = ""; }; + C7F8012023E8303200396FBD /* ListRVWheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRVWheel.swift; sourceTree = ""; }; + C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; @@ -875,8 +875,8 @@ C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */, D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */, 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, - C7F8012023E8303200396FBD /* LabelsWithCircleProgressBar.swift */, - C7F8012223E846C300396FBD /* LabelsWithCircleProgressBarModel.swift */, + C7F8012023E8303200396FBD /* ListRVWheel.swift */, + C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, ); path = VerticalCombinationViews; sourceTree = ""; @@ -1606,7 +1606,7 @@ D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */, D28A838D23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, - C7F8012323E846C300396FBD /* LabelsWithCircleProgressBarModel.swift in Sources */, + C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, @@ -1702,7 +1702,7 @@ D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */, D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, - C7F8012123E8303200396FBD /* LabelsWithCircleProgressBar.swift in Sources */, + C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */, D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift similarity index 65% rename from MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift rename to MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift index 9dba7558..a4f18df6 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBar.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift @@ -1,5 +1,5 @@ // -// LabelsWithCircleProgressBar.swift +// ListRVWheel.swift // MVMCoreUI // // Created by Arora, Prateek on 20/01/20. @@ -7,14 +7,14 @@ // import Foundation -@objcMembers public class LabelsWithCircleProgressBar: Container { +@objcMembers public class ListRVWheel: TableViewCell { - let progressBar = GraphView(frame: .zero) + let wheel = GraphView(frame: .zero) let leftLabel = Label(frame: .zero) let rightLabel = Label(frame: .zero) let leftLabelWidthConstant : CGFloat = 151.0 let rightLabelWidthConstant : CGFloat = 84.0 - let progressBarTrailingConstant : CGFloat = -72.0 + let wheelTrailingConstant : CGFloat = -72.0 let rightLabelLeadingAnchorConstant : CGFloat = 8.0 //------------------------------------------------- @@ -22,7 +22,7 @@ import Foundation //------------------------------------------------- open override func updateView(_ size: CGFloat) { super.updateView(size) - progressBar.updateView(size) + wheel.updateView(size) leftLabel.updateView(size) rightLabel.updateView(size) } @@ -35,36 +35,36 @@ import Foundation guard leftLabel.superview == nil else { return } - let container = MVMCoreUICommonViewsUtility.commonView() - addAndContain(container) - container.addSubview(progressBar) - container.addSubview(leftLabel) - container.addSubview(rightLabel) + contentView.addSubview(wheel) + contentView.addSubview(leftLabel) + contentView.addSubview(rightLabel) + NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) + contentView.translatesAutoresizingMaskIntoConstraints = false //------------------------------------------------- // MARK: - Constraining //------------------------------------------------- self.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ - leftLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor), - leftLabel.topAnchor.constraint(equalTo: container.topAnchor), - leftLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), + leftLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + leftLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + leftLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) ]) - let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: container.trailingAnchor) + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) rightLabelTrailing.priority = .defaultHigh NSLayoutConstraint.activate([ rightLabelTrailing, - rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : progressBar.trailingAnchor, constant: rightLabelLeadingAnchorConstant), - rightLabel.topAnchor.constraint(equalTo: container.topAnchor), - rightLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor), + rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : wheel.trailingAnchor, constant: rightLabelLeadingAnchorConstant), + rightLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + rightLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) ]) NSLayoutConstraint.activate([ - progressBar.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant:progressBarTrailingConstant), - progressBar.topAnchor.constraint(equalTo: container.topAnchor), - progressBar.bottomAnchor.constraint(equalTo: container.bottomAnchor), + wheel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant:wheelTrailingConstant), + wheel.topAnchor.constraint(equalTo: contentView.topAnchor), + wheel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) } @@ -73,10 +73,10 @@ import Foundation //------------------------------------------------- public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? LabelsWithCircleProgressBarModel else { return } + guard let model = model as? ListRVWheelModel else { return } leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) - progressBar.setWithModel(model.progressBar, delegateObject, additionalData) + wheel.setWithModel(model.wheel, delegateObject, additionalData) } //------------------------------------------------- @@ -86,7 +86,7 @@ import Foundation super.reset() leftLabel.reset() rightLabel.reset() - progressBar.reset() + wheel.reset() } public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift similarity index 53% rename from MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift rename to MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift index e55d5199..5d8a041a 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/LabelsWithCircleProgressBarModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift @@ -1,5 +1,5 @@ // -// LabelsWithCircleProgressBarModel.swift +// ListRVWheelModel.swift // MVMCoreUI // // Created by Arora, Prateek on 03/02/20. @@ -7,34 +7,43 @@ // import Foundation -public class LabelsWithCircleProgressBarModel:MoleculeModelProtocol { +public class ListRVWheelModel:ListItemModelProtocol { public var backgroundColor: Color? - public static var identifier: String = "labelsWithCircleProgressBar" + public var line: LineModel? + public var hideArrow: Bool? + public var horizontalAlignment: UIStackView.Alignment? + public var verticalAlignment: UIStackView.Alignment? + public var useHorizontalMargins: Bool? + public var useVerticalMargins: Bool? + public var topMarginPadding: CGFloat? + public var bottomMarginPadding: CGFloat? + + public static var identifier: String = "listRVWheel" public var leftLabel: LabelModel? public var rightLabel: LabelModel? - public var progressBar : CircleProgressModel? - init(leftLabel: LabelModel, rightLabel: LabelModel, progressBar: CircleProgressModel) { + public var wheel : CircleProgressModel? + init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) { self.leftLabel = leftLabel self.rightLabel = rightLabel - self.progressBar = progressBar + self.wheel = wheel } private enum CodingKeys: String,CodingKey { case moleculeName case leftLabel case rightLabel - case progressBar + case wheel } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) - progressBar = try typeContainer.decode(CircleProgressModel.self, forKey: .progressBar) + wheel = try typeContainer.decode(CircleProgressModel.self, forKey: .wheel) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(LabelsWithCircleProgressBarModel.identifier, forKey: .moleculeName) + try container.encode(ListRVWheelModel.identifier, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) try container.encode(rightLabel, forKey: .rightLabel) - try container.encodeIfPresent(progressBar, forKey: .progressBar) + try container.encodeIfPresent(wheel, forKey: .wheel) } } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 5c9cf5d5..6037ba35 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -62,7 +62,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: EyebrowHeadlineBodyLink.self, viewModelClass: EyebrowHeadlineBodyLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLink.self, viewModelClass: HeadlineBodyLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyButton.self, viewModelClass: HeadlineBodyButtonModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass:LabelsWithCircleProgressBar.self, viewModelClass: LabelsWithCircleProgressBarModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) // Left Right Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CornerLabels.self, viewModelClass: CornerLabelsModel.self) From a87926a8107d14007be23a5d3ef87f091ee82e23 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Mon, 10 Feb 2020 15:41:12 +0530 Subject: [PATCH 09/96] Story - 19072: List - Right Variable - Payments Initial Commit Added Molecule Class, Model Class --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ .../RightVariablePaymentsList.swift | 106 ++++++++++++++++++ .../RightVariablePaymentsListModel.swift | 73 ++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 4 files changed, 188 insertions(+) create mode 100644 MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift create mode 100644 MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f97e81aa..aacab776 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -123,6 +123,8 @@ 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 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 /* RightVariablePaymentsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* RightVariablePaymentsList.swift */; }; + AA11A42123F15D7000D7962F /* RightVariablePaymentsListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* RightVariablePaymentsListModel.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; @@ -439,6 +441,8 @@ 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; 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 /* RightVariablePaymentsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightVariablePaymentsList.swift; sourceTree = ""; }; + AA11A42023F15D7000D7962F /* RightVariablePaymentsListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightVariablePaymentsListModel.swift; sourceTree = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; @@ -897,6 +901,8 @@ D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */, 01509D902327ECE600EF99AA /* CornerLabels.swift */, D224798823142BF2003FCCF9 /* ToggleMolecules */, + AA11A41E23F15D3100D7962F /* RightVariablePaymentsList.swift */, + AA11A42023F15D7000D7962F /* RightVariablePaymentsListModel.swift */, ); path = LeftRightViews; sourceTree = ""; @@ -1556,6 +1562,7 @@ DBC4391922442197001AB423 /* DashLine.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, + AA11A41F23F15D3100D7962F /* RightVariablePaymentsList.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, @@ -1617,6 +1624,7 @@ D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, 0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, + AA11A42123F15D7000D7962F /* RightVariablePaymentsListModel.swift in Sources */, 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, diff --git a/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift b/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift new file mode 100644 index 00000000..fe387ca2 --- /dev/null +++ b/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift @@ -0,0 +1,106 @@ +// +// RightVariablePaymentsList.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class RightVariablePaymentsList : TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + + let leftLabel = Label.commonLabelB2(true) + let rightImage = MFLoadImageView() + let containerView = ViewConstrainingView() + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + + let cellHeight: CGFloat = 65.0 + let leftPadding: CGFloat = 35.0 + let rightPadding: CGFloat = 54.0 + let spaceBetweenLabelAndImage: CGFloat = 40.0 + let imageWidth: CGFloat = 56.0 + let imageHeight: CGFloat = 16.0 + + //------------------------------------------------------ + // MARK: - Initialization + //-------------------------------------------------------- + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupView() + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + //----------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + containerView.updateView(size) + leftLabel.updateView(size) + rightImage.updateView(size) + } + + override open func setupView() { + super.setupView() + guard leftLabel.superview == nil else { + return + } + + containerView.translatesAutoresizingMaskIntoConstraints = false + contentView.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true + contentView.addSubview(containerView) + containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + containerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true + containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true + containerView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true + + containerView.addSubview(leftLabel) + containerView.addSubview(rightImage) + + leftLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor,constant: leftPadding).isActive = true + leftLabel.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true + leftLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true + + rightImage.leadingAnchor.constraint(equalTo: leftLabel.leadingAnchor,constant: spaceBetweenLabelAndImage).isActive = true + rightImage.centerYAnchor.constraint(equalTo: leftLabel.centerYAnchor).isActive = true + rightImage.widthAnchor.constraint(equalToConstant: imageWidth).isActive = true + rightImage.heightAnchor.constraint(equalToConstant: imageHeight).isActive = true + containerView.trailingAnchor.constraint(equalTo: rightImage.trailingAnchor,constant: rightPadding).isActive = true + } + + //---------------------------------------------------- + // MARK: - Molecule + //------------------------------------------------------ + + override open func reset() { + super.reset() + + leftLabel.reset() + rightImage.reset() + } + + open func setAsMolecule() { + setupView() + } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? RightVariablePaymentsListModel else { return} + leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) + rightImage.setWithModel(model.image, delegateObject, additionalData) + } +} diff --git a/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift b/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift new file mode 100644 index 00000000..e3c9e889 --- /dev/null +++ b/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift @@ -0,0 +1,73 @@ +// +// RightVariablePaymentsListModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class RightVariablePaymentsListModel: ContainerModel, ListItemModelProtocol { + + public var line: LineModel? + public var hideArrow: Bool? + public var backgroundColor: Color? + public var action: ActionModelProtocol? + + public static var identifier: String = "listRVImg" + public var image: ImageViewModel + public var leftLabel: LabelModel + + func setDefaults() { + if useHorizontalMargins == nil { + useHorizontalMargins = true + } + if useVerticalMargins == nil { + useVerticalMargins = true + } + if topMarginPadding == nil { + topMarginPadding = 24 + } + if bottomMarginPadding == nil { + bottomMarginPadding = 0 + } + } + + public init(image: ImageViewModel, leftLabel: LabelModel) { + self.image = image + self.leftLabel = leftLabel + super.init() + setDefaults() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case leftLabel + case image + case action + case hideArrow + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) + image = try typeContainer.decode(ImageViewModel.self, forKey: .image) + action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow) + 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(RightVariablePaymentsListModel.identifier, forKey: .moleculeName) + try container.encode(leftLabel, forKey: .leftLabel) + try container.encode(image, forKey: .image) + try container.encodeModelIfPresent(action, forKey: .action) + try container.encodeIfPresent(hideArrow, forKey: .hideArrow) + } + +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 8c1a36e3..4c384930 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -70,6 +70,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: RightVariablePaymentsList.self, viewModelClass: RightVariablePaymentsListModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: ListItemModel.self) From d683d420c8ee7eb19a37403340c36cbb22b5271f Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 11 Feb 2020 12:22:50 +0530 Subject: [PATCH 10/96] Code changes based on review: Modified class name according to Confluence Removed Initializers Removed extra spaces. --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++++----- ....swift => ListRightVariablePayments.swift} | 36 ++++++------------- ...t => ListRightVariablePaymentsModel.swift} | 13 ++----- .../OtherHandlers/MoleculeObjectMapping.swift | 2 +- 4 files changed, 22 insertions(+), 45 deletions(-) rename MVMCoreUI/Molecules/LeftRightViews/{RightVariablePaymentsList.swift => ListRightVariablePayments.swift} (78%) rename MVMCoreUI/Molecules/LeftRightViews/{RightVariablePaymentsListModel.swift => ListRightVariablePaymentsModel.swift} (83%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index aacab776..aa416225 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -123,8 +123,8 @@ 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 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 /* RightVariablePaymentsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* RightVariablePaymentsList.swift */; }; - AA11A42123F15D7000D7962F /* RightVariablePaymentsListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* RightVariablePaymentsListModel.swift */; }; + AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; + AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; @@ -441,8 +441,8 @@ 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; 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 /* RightVariablePaymentsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightVariablePaymentsList.swift; sourceTree = ""; }; - AA11A42023F15D7000D7962F /* RightVariablePaymentsListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightVariablePaymentsListModel.swift; 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 = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; @@ -901,8 +901,8 @@ D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */, 01509D902327ECE600EF99AA /* CornerLabels.swift */, D224798823142BF2003FCCF9 /* ToggleMolecules */, - AA11A41E23F15D3100D7962F /* RightVariablePaymentsList.swift */, - AA11A42023F15D7000D7962F /* RightVariablePaymentsListModel.swift */, + AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, + AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, ); path = LeftRightViews; sourceTree = ""; @@ -1562,7 +1562,7 @@ DBC4391922442197001AB423 /* DashLine.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, - AA11A41F23F15D3100D7962F /* RightVariablePaymentsList.swift in Sources */, + AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, @@ -1624,7 +1624,7 @@ D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, 0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, - AA11A42123F15D7000D7962F /* RightVariablePaymentsListModel.swift in Sources */, + AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, diff --git a/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift b/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePayments.swift similarity index 78% rename from MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift rename to MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePayments.swift index fe387ca2..5eebb1e1 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsList.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePayments.swift @@ -1,5 +1,5 @@ // -// RightVariablePaymentsList.swift +// ListRightVariablePayments.swift // MVMCoreUI // // Created by Lekshmi S on 10/02/20. @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class RightVariablePaymentsList : TableViewCell { +@objcMembers public class ListRightVariablePayments: TableViewCell { //----------------------------------------------------- // MARK: - Outlets @@ -16,7 +16,7 @@ import Foundation let leftLabel = Label.commonLabelB2(true) let rightImage = MFLoadImageView() - let containerView = ViewConstrainingView() + let containerView = Container() //------------------------------------------------------ // MARK: - Properties @@ -24,25 +24,11 @@ import Foundation let cellHeight: CGFloat = 65.0 let leftPadding: CGFloat = 35.0 - let rightPadding: CGFloat = 54.0 + let rightPadding: CGFloat = PaddingNine let spaceBetweenLabelAndImage: CGFloat = 40.0 let imageWidth: CGFloat = 56.0 let imageHeight: CGFloat = 16.0 - //------------------------------------------------------ - // MARK: - Initialization - //-------------------------------------------------------- - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupView() - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setupView() - } - //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- @@ -59,10 +45,11 @@ import Foundation guard leftLabel.superview == nil else { return } - containerView.translatesAutoresizingMaskIntoConstraints = false contentView.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true contentView.addSubview(containerView) + + //containerView constraints containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true containerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true @@ -71,11 +58,13 @@ import Foundation containerView.addSubview(leftLabel) containerView.addSubview(rightImage) + //leftLabel constraints leftLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor,constant: leftPadding).isActive = true leftLabel.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true leftLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true - rightImage.leadingAnchor.constraint(equalTo: leftLabel.leadingAnchor,constant: spaceBetweenLabelAndImage).isActive = true + //rightImage constraints + rightImage.leadingAnchor.constraint(greaterThanOrEqualTo: leftLabel.trailingAnchor,constant: spaceBetweenLabelAndImage).isActive = true rightImage.centerYAnchor.constraint(equalTo: leftLabel.centerYAnchor).isActive = true rightImage.widthAnchor.constraint(equalToConstant: imageWidth).isActive = true rightImage.heightAnchor.constraint(equalToConstant: imageHeight).isActive = true @@ -88,18 +77,13 @@ import Foundation override open func reset() { super.reset() - leftLabel.reset() rightImage.reset() } - open func setAsMolecule() { - setupView() - } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? RightVariablePaymentsListModel else { return} + guard let model = model as? ListRightVariablePaymentsModel else { return} leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightImage.setWithModel(model.image, delegateObject, additionalData) } diff --git a/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePaymentsModel.swift similarity index 83% rename from MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift rename to MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePaymentsModel.swift index e3c9e889..db4dabc4 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/RightVariablePaymentsListModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePaymentsModel.swift @@ -1,5 +1,5 @@ // -// RightVariablePaymentsListModel.swift +// ListRightVariablePaymentsModel.swift // MVMCoreUI // // Created by Lekshmi S on 10/02/20. @@ -8,13 +8,12 @@ import Foundation -public class RightVariablePaymentsListModel: ContainerModel, ListItemModelProtocol { +public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtocol { public var line: LineModel? public var hideArrow: Bool? public var backgroundColor: Color? public var action: ActionModelProtocol? - public static var identifier: String = "listRVImg" public var image: ImageViewModel public var leftLabel: LabelModel @@ -38,7 +37,6 @@ public class RightVariablePaymentsListModel: ContainerModel, ListItemModelProtoc self.image = image self.leftLabel = leftLabel super.init() - setDefaults() } private enum CodingKeys: String, CodingKey { @@ -46,7 +44,6 @@ public class RightVariablePaymentsListModel: ContainerModel, ListItemModelProtoc case leftLabel case image case action - case hideArrow } required public init(from decoder: Decoder) throws { @@ -54,20 +51,16 @@ public class RightVariablePaymentsListModel: ContainerModel, ListItemModelProtoc leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) image = try typeContainer.decode(ImageViewModel.self, forKey: .image) action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) - hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow) 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(RightVariablePaymentsListModel.identifier, forKey: .moleculeName) + try container.encode(ListRightVariablePaymentsModel.identifier, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) try container.encode(image, forKey: .image) try container.encodeModelIfPresent(action, forKey: .action) - try container.encodeIfPresent(hideArrow, forKey: .hideArrow) } - } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 4c384930..c3cf76be 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -70,7 +70,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: RightVariablePaymentsList.self, viewModelClass: RightVariablePaymentsListModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: ListItemModel.self) From 63201a8fa69c909c3fa4e6523577825388beea21 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Wed, 12 Feb 2020 15:11:41 +0530 Subject: [PATCH 11/96] 19042 - List - Left Variable - Checkbox - With Right Caret - All Text & Links story commit. Added Molecule class, Model class --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ ...heckboxWithRightCaretAllTextAndLinks.swift | 87 +++++++++++++++++++ ...oxWithRightCaretAllTextAndLinksModel.swift | 66 ++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 4 files changed, 162 insertions(+) create mode 100644 MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift create mode 100644 MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f97e81aa..b9fad525 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -123,6 +123,8 @@ 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 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 */; }; + AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */; }; + AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; @@ -439,6 +441,8 @@ 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; 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 = ""; }; + AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift; sourceTree = ""; }; + AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift; sourceTree = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; @@ -897,6 +901,8 @@ D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */, 01509D902327ECE600EF99AA /* CornerLabels.swift */, D224798823142BF2003FCCF9 /* ToggleMolecules */, + AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */, + AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */, ); path = LeftRightViews; sourceTree = ""; @@ -1582,6 +1588,7 @@ 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, + AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, @@ -1724,6 +1731,7 @@ D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */, + AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift in Sources */, 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */, 01EB369323609801006832FA /* HeaderModel.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift new file mode 100644 index 00000000..2b47e704 --- /dev/null +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift @@ -0,0 +1,87 @@ +// +// ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift +// MVMCoreUI +// +// Created by Lekshmi S on 11/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinks: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + + let checkbox = Checkbox(frame: .zero) + let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) + let containerView = Container() + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + + let cellHeight: CGFloat = 125.0 + let leftPadding: CGFloat = 35.0 + let rightPadding: CGFloat = 35.0 + let spaceBetweenCheckBoxAndEyebrowHedline: CGFloat = 16.0 + let checkBoxSize: CGFloat = 18.0 + + //----------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + containerView.updateView(size) + checkbox.updateView(size) + eyebrowHeadlineBodyLink.updateView(size) + } + + override open func setupView() { + super.setupView() + guard checkbox.superview == nil else { + return + } + containerView.translatesAutoresizingMaskIntoConstraints = false + contentView.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true + contentView.addSubview(containerView) + + //containerView constraints + containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + containerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true + containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true + containerView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true + + containerView.addSubview(checkbox) + containerView.addSubview(eyebrowHeadlineBodyLink) + + //checkBox constraints + checkbox.centerYAnchor.constraint(equalTo: eyebrowHeadlineBodyLink.centerYAnchor).isActive = true + checkbox.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: leftPadding).isActive = true + + //eyebrowHeadlineBodyLink constraints + eyebrowHeadlineBodyLink.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true + eyebrowHeadlineBodyLink.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true + eyebrowHeadlineBodyLink.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: spaceBetweenCheckBoxAndEyebrowHedline).isActive = true + eyebrowHeadlineBodyLink.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + } + + //---------------------------------------------------- + // MARK: - Molecule + //------------------------------------------------------ + + override open func reset() { + super.reset() + checkbox.reset() + eyebrowHeadlineBodyLink.reset() + } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel else { return} + checkbox.setWithModel(model.checkbox, delegateObject, additionalData) + eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + } +} diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift new file mode 100644 index 00000000..86925752 --- /dev/null +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift @@ -0,0 +1,66 @@ +// +// ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 11/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: ContainerModel, ListItemModelProtocol { + + public var line: LineModel? + public var hideArrow: Bool? + public var backgroundColor: Color? + public static var identifier: String = "listLVCB" + public var checkbox: CheckboxModel + var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + + func setDefaults() { + if useHorizontalMargins == nil { + useHorizontalMargins = true + } + if useVerticalMargins == nil { + useVerticalMargins = true + } + if topMarginPadding == nil { + topMarginPadding = 24 + } + if bottomMarginPadding == nil { + bottomMarginPadding = 0 + } + } + + init(checkbox: CheckboxModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { + self.checkbox = checkbox + self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + super.init() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case eyebrowHeadlineBodyLink + case checkbox + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) + checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox) + 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(EyebrowHeadlineBodyLinkModel.identifier, forKey: .moleculeName) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + try container.encode(checkbox, forKey: .checkbox) + } + +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 8c1a36e3..caffd59f 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -70,6 +70,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyToggle.self, viewModelClass: HeadlineBodyToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: ListItemModel.self) From 3dbbc1a876d4f604e9bab61b64e18867069fe0f2 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Wed, 12 Feb 2020 16:50:46 +0530 Subject: [PATCH 12/96] Code fix --- ...LeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift index 86925752..07efdf1e 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift @@ -57,7 +57,7 @@ public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: Contain public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(EyebrowHeadlineBodyLinkModel.identifier, forKey: .moleculeName) + try container.encode(ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.identifier, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) try container.encode(checkbox, forKey: .checkbox) From c9539814060ce0b2c17dff24c24f540b449e5bbc Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Thu, 13 Feb 2020 09:00:37 +0530 Subject: [PATCH 13/96] Removed container and added stackmodel --- MVMCoreUI.xcodeproj/project.pbxproj | 12 ++++- .../ListRightVariablePayments.swift | 49 +++++++------------ .../ListRightVariablePaymentsModel.swift | 13 +++-- 3 files changed, 35 insertions(+), 39 deletions(-) rename MVMCoreUI/Molecules/{LeftRightViews => DesignedComponents/List/RightVariable}/ListRightVariablePayments.swift (52%) rename MVMCoreUI/Molecules/{LeftRightViews => DesignedComponents/List/RightVariable}/ListRightVariablePaymentsModel.swift (86%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 79fb28b4..b209d013 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -781,6 +781,15 @@ name = "Recovered References"; sourceTree = ""; }; + AA4FC2A323F4F69600E251DB /* RightVariable */ = { + isa = PBXGroup; + children = ( + AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, + AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, + ); + path = RightVariable; + sourceTree = ""; + }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -909,8 +918,6 @@ D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */, 01509D902327ECE600EF99AA /* CornerLabels.swift */, D224798823142BF2003FCCF9 /* ToggleMolecules */, - AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, - AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, ); path = LeftRightViews; sourceTree = ""; @@ -964,6 +971,7 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( + AA4FC2A323F4F69600E251DB /* RightVariable */, D22B38EB23F4E0AE00490EF6 /* LeftVariable */, ); path = List; diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift similarity index 52% rename from MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePayments.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 5eebb1e1..851a2137 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -16,7 +16,7 @@ import Foundation let leftLabel = Label.commonLabelB2(true) let rightImage = MFLoadImageView() - let containerView = Container() + let stack = Stack(frame: .zero) //------------------------------------------------------ // MARK: - Properties @@ -35,9 +35,7 @@ import Foundation open override func updateView(_ size: CGFloat) { super.updateView(size) - containerView.updateView(size) - leftLabel.updateView(size) - rightImage.updateView(size) + stack.updateView(size) } override open func setupView() { @@ -45,30 +43,12 @@ import Foundation guard leftLabel.superview == nil else { return } - containerView.translatesAutoresizingMaskIntoConstraints = false - contentView.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true - contentView.addSubview(containerView) - - //containerView constraints - containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - containerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true - containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true - containerView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true - - containerView.addSubview(leftLabel) - containerView.addSubview(rightImage) - - //leftLabel constraints - leftLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor,constant: leftPadding).isActive = true - leftLabel.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true - leftLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true - - //rightImage constraints - rightImage.leadingAnchor.constraint(greaterThanOrEqualTo: leftLabel.trailingAnchor,constant: spaceBetweenLabelAndImage).isActive = true - rightImage.centerYAnchor.constraint(equalTo: leftLabel.centerYAnchor).isActive = true - rightImage.widthAnchor.constraint(equalToConstant: imageWidth).isActive = true - rightImage.heightAnchor.constraint(equalToConstant: imageHeight).isActive = true - containerView.trailingAnchor.constraint(equalTo: rightImage.trailingAnchor,constant: rightPadding).isActive = true + stack.translatesAutoresizingMaskIntoConstraints = false + stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] + contentView.addSubview(stack) + containerHelper.constrainView(stack) + leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) + rightImage.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) } //---------------------------------------------------- @@ -77,8 +57,7 @@ import Foundation override open func reset() { super.reset() - leftLabel.reset() - rightImage.reset() + stack.reset() } public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { @@ -86,5 +65,15 @@ import Foundation guard let model = model as? ListRightVariablePaymentsModel else { return} leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightImage.setWithModel(model.image, delegateObject, additionalData) + + // Create a stack model to use for the internal stack and set the alignment of label and image + let leftLabel = StackItemModel() + leftLabel.horizontalAlignment = .fill + let rightImage = StackItemModel() + rightImage.horizontalAlignment = .trailing + let stackModel = StackModel(molecules: [leftLabel,rightLabel]) + stackModel.axis = .horizontal + stack.model = stackModel + stack.restack() } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift similarity index 86% rename from MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePaymentsModel.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index db4dabc4..ef0693d0 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -11,7 +11,8 @@ import Foundation public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtocol { public var line: LineModel? - public var hideArrow: Bool? + public var style: String? = "standard" + public var hideArrow: Bool? = false public var backgroundColor: Color? public var action: ActionModelProtocol? public static var identifier: String = "listRVImg" @@ -25,11 +26,8 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc if useVerticalMargins == nil { useVerticalMargins = true } - if topMarginPadding == nil { - topMarginPadding = 24 - } - if bottomMarginPadding == nil { - bottomMarginPadding = 0 + if image.height == nil { + image.height = 16.0 } } @@ -37,6 +35,7 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc self.image = image self.leftLabel = leftLabel super.init() + setDefaults() } private enum CodingKeys: String, CodingKey { @@ -58,7 +57,7 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(ListRightVariablePaymentsModel.identifier, forKey: .moleculeName) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) try container.encode(image, forKey: .image) try container.encodeModelIfPresent(action, forKey: .action) From d0d8fa54cad223846be705ced3d055a13f4b1959 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Thu, 13 Feb 2020 12:12:12 +0530 Subject: [PATCH 14/96] Code fixes and removed unwanted code. --- .../ListRightVariablePayments.swift | 19 ++++++------------- .../ListRightVariablePaymentsModel.swift | 3 +++ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 851a2137..2fd75a66 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -15,20 +15,9 @@ import Foundation //------------------------------------------------------- let leftLabel = Label.commonLabelB2(true) - let rightImage = MFLoadImageView() + let rightImage = MFLoadImageView(pinnedEdges: .all) let stack = Stack(frame: .zero) - //------------------------------------------------------ - // MARK: - Properties - //------------------------------------------------------ - - let cellHeight: CGFloat = 65.0 - let leftPadding: CGFloat = 35.0 - let rightPadding: CGFloat = PaddingNine - let spaceBetweenLabelAndImage: CGFloat = 40.0 - let imageWidth: CGFloat = 56.0 - let imageHeight: CGFloat = 16.0 - //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- @@ -71,9 +60,13 @@ import Foundation leftLabel.horizontalAlignment = .fill let rightImage = StackItemModel() rightImage.horizontalAlignment = .trailing - let stackModel = StackModel(molecules: [leftLabel,rightLabel]) + let stackModel = StackModel(molecules: [leftLabel,rightImage]) stackModel.axis = .horizontal stack.model = stackModel stack.restack() } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 65 + } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index ef0693d0..08a6f3cb 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -29,6 +29,9 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc if image.height == nil { image.height = 16.0 } + if image.width == nil { + image.height = 56.0 + } } public init(image: ImageViewModel, leftLabel: LabelModel) { From 5b3e213ed61335b1ad2641d85a7da670faa44139 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Thu, 13 Feb 2020 12:59:11 +0530 Subject: [PATCH 15/96] Removed constraints and prioritylevel as per review comments. --- .../List/RightVariable/ListRightVariablePayments.swift | 4 +--- .../List/RightVariable/ListRightVariablePaymentsModel.swift | 6 ------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 2fd75a66..34928e24 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -36,8 +36,6 @@ import Foundation stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] contentView.addSubview(stack) containerHelper.constrainView(stack) - leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) - rightImage.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) } //---------------------------------------------------- @@ -57,7 +55,7 @@ import Foundation // Create a stack model to use for the internal stack and set the alignment of label and image let leftLabel = StackItemModel() - leftLabel.horizontalAlignment = .fill + leftLabel.horizontalAlignment = .leading let rightImage = StackItemModel() rightImage.horizontalAlignment = .trailing let stackModel = StackModel(molecules: [leftLabel,rightImage]) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 08a6f3cb..3478cda1 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -26,12 +26,6 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc if useVerticalMargins == nil { useVerticalMargins = true } - if image.height == nil { - image.height = 16.0 - } - if image.width == nil { - image.height = 56.0 - } } public init(image: ImageViewModel, leftLabel: LabelModel) { From ca39be5643dfee4331c417ac7f5a7d8d66af519e Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 13 Feb 2020 19:41:11 +0530 Subject: [PATCH 16/96] Code Fixes after comments. --- .../List/RightVariable/ListRightVariablePayments.swift | 2 +- .../List/RightVariable/ListRightVariablePaymentsModel.swift | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 34928e24..626e8d42 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -14,7 +14,7 @@ import Foundation // MARK: - Outlets //------------------------------------------------------- - let leftLabel = Label.commonLabelB2(true) + let leftLabel = Label.commonLabelB1(true) let rightImage = MFLoadImageView(pinnedEdges: .all) let stack = Stack(frame: .zero) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 3478cda1..97f8e1d2 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -40,6 +40,7 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc case leftLabel case image case action + case backgroundColor } required public init(from decoder: Decoder) throws { @@ -47,6 +48,7 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) image = try typeContainer.decode(ImageViewModel.self, forKey: .image) action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) setDefaults() } @@ -58,5 +60,7 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc try container.encode(leftLabel, forKey: .leftLabel) try container.encode(image, forKey: .image) try container.encodeModelIfPresent(action, forKey: .action) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + } } From 5b1b29c10d723d55b56602474828715fc31de44c Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 14 Feb 2020 10:17:54 +0530 Subject: [PATCH 17/96] Removed container and added stackmodel code changes. --- ...heckboxWithRightCaretAllTextAndLinks.swift | 56 ++++++------------- ...oxWithRightCaretAllTextAndLinksModel.swift | 15 ++++- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift index 2b47e704..c1f68e94 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift @@ -16,17 +16,7 @@ import Foundation let checkbox = Checkbox(frame: .zero) let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) - let containerView = Container() - - //------------------------------------------------------ - // MARK: - Properties - //------------------------------------------------------ - - let cellHeight: CGFloat = 125.0 - let leftPadding: CGFloat = 35.0 - let rightPadding: CGFloat = 35.0 - let spaceBetweenCheckBoxAndEyebrowHedline: CGFloat = 16.0 - let checkBoxSize: CGFloat = 18.0 + let stack = Stack(frame: .zero) //----------------------------------------------------- // MARK: - View Lifecycle @@ -34,9 +24,7 @@ import Foundation open override func updateView(_ size: CGFloat) { super.updateView(size) - containerView.updateView(size) - checkbox.updateView(size) - eyebrowHeadlineBodyLink.updateView(size) + stack.updateView(size) } override open func setupView() { @@ -44,28 +32,10 @@ import Foundation guard checkbox.superview == nil else { return } - containerView.translatesAutoresizingMaskIntoConstraints = false - contentView.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true - contentView.addSubview(containerView) - - //containerView constraints - containerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - containerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true - containerView.topAnchor.constraint(equalTo: topAnchor).isActive = true - containerView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true - - containerView.addSubview(checkbox) - containerView.addSubview(eyebrowHeadlineBodyLink) - - //checkBox constraints - checkbox.centerYAnchor.constraint(equalTo: eyebrowHeadlineBodyLink.centerYAnchor).isActive = true - checkbox.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: leftPadding).isActive = true - - //eyebrowHeadlineBodyLink constraints - eyebrowHeadlineBodyLink.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true - eyebrowHeadlineBodyLink.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true - eyebrowHeadlineBodyLink.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: spaceBetweenCheckBoxAndEyebrowHedline).isActive = true - eyebrowHeadlineBodyLink.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + stack.translatesAutoresizingMaskIntoConstraints = false + stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)] + contentView.addSubview(stack) + containerHelper.constrainView(stack) } //---------------------------------------------------- @@ -74,8 +44,7 @@ import Foundation override open func reset() { super.reset() - checkbox.reset() - eyebrowHeadlineBodyLink.reset() + stack.reset() } public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { @@ -83,5 +52,16 @@ import Foundation guard let model = model as? ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel else { return} checkbox.setWithModel(model.checkbox, delegateObject, additionalData) eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + + // Create a stack model to use for the internal stack and set the alignment of labels + let checkbox = StackItemModel() + checkbox.horizontalAlignment = .leading + let eyebrowHeadlineBodyLink = StackItemModel() + eyebrowHeadlineBodyLink.horizontalAlignment = .leading + eyebrowHeadlineBodyLink.spacing = 20 + let stackModel = StackModel(molecules: [checkbox,eyebrowHeadlineBodyLink]) + stackModel.axis = .horizontal + stack.model = stackModel + stack.restack() } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift index 07efdf1e..24979f78 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift @@ -11,10 +11,13 @@ import Foundation public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: ContainerModel, ListItemModelProtocol { public var line: LineModel? - public var hideArrow: Bool? + public var style: String? = "standard" + public var hideArrow: Bool? = false public var backgroundColor: Color? + public var action: ActionModelProtocol? public static var identifier: String = "listLVCB" public var checkbox: CheckboxModel + public var spacing: CGFloat = 16.0 var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel func setDefaults() { @@ -43,6 +46,8 @@ public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: Contain case backgroundColor case eyebrowHeadlineBodyLink case checkbox + case action + case spacing } required public init(from decoder: Decoder) throws { @@ -50,6 +55,10 @@ public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: Contain backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox) + action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { + self.spacing = spacing + } try super.init(from: decoder) setDefaults() } @@ -57,10 +66,12 @@ public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: Contain public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.identifier, forKey: .moleculeName) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) try container.encode(checkbox, forKey: .checkbox) + try container.encodeModelIfPresent(action, forKey: .action) + try container.encodeIfPresent(spacing, forKey: .spacing) } } From 23b2df3c825640d943ad9c1f6c3647a201152787 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 14 Feb 2020 12:35:43 +0530 Subject: [PATCH 18/96] Code commit - Conforming to ListItemModel and MoleculeModelProtocol based on review comments. --- .../ListRightVariablePayments.swift | 4 +-- .../ListRightVariablePaymentsModel.swift | 25 +------------------ 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 626e8d42..5f2870ec 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -54,9 +54,9 @@ import Foundation rightImage.setWithModel(model.image, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of label and image - let leftLabel = StackItemModel() + let leftLabel = StackItemModel(percent: 60) leftLabel.horizontalAlignment = .leading - let rightImage = StackItemModel() + let rightImage = StackItemModel(percent: 40) rightImage.horizontalAlignment = .trailing let stackModel = StackModel(molecules: [leftLabel,rightImage]) stackModel.axis = .horizontal diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 97f8e1d2..23545142 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -8,49 +8,29 @@ import Foundation -public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtocol { +public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtocol { - public var line: LineModel? - public var style: String? = "standard" - public var hideArrow: Bool? = false - public var backgroundColor: Color? - public var action: ActionModelProtocol? public static var identifier: String = "listRVImg" public var image: ImageViewModel public var leftLabel: LabelModel - func setDefaults() { - if useHorizontalMargins == nil { - useHorizontalMargins = true - } - if useVerticalMargins == nil { - useVerticalMargins = true - } - } - public init(image: ImageViewModel, leftLabel: LabelModel) { self.image = image self.leftLabel = leftLabel super.init() - setDefaults() } private enum CodingKeys: String, CodingKey { case moleculeName case leftLabel case image - case action - case backgroundColor } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) image = try typeContainer.decode(ImageViewModel.self, forKey: .image) - action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) - setDefaults() } public override func encode(to encoder: Encoder) throws { @@ -59,8 +39,5 @@ public class ListRightVariablePaymentsModel: ContainerModel, ListItemModelProtoc try container.encode(moleculeName, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) try container.encode(image, forKey: .image) - try container.encodeModelIfPresent(action, forKey: .action) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - } } From 69919f5beb90ecb056a0414713512c1914c63392 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 14 Feb 2020 14:05:54 +0530 Subject: [PATCH 19/96] Added percent for stack items. Removed conformance to ContainerModel and ListItemModelProtocol. --- ...heckboxWithRightCaretAllTextAndLinks.swift | 7 ++-- ...oxWithRightCaretAllTextAndLinksModel.swift | 35 +------------------ 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift index c1f68e94..c194cc50 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift @@ -54,11 +54,10 @@ import Foundation eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of labels - let checkbox = StackItemModel() + let checkbox = StackItemModel(percent: 10) checkbox.horizontalAlignment = .leading - let eyebrowHeadlineBodyLink = StackItemModel() - eyebrowHeadlineBodyLink.horizontalAlignment = .leading - eyebrowHeadlineBodyLink.spacing = 20 + let eyebrowHeadlineBodyLink = StackItemModel(percent: 90) + eyebrowHeadlineBodyLink.horizontalAlignment = .fill let stackModel = StackModel(molecules: [checkbox,eyebrowHeadlineBodyLink]) stackModel.axis = .horizontal stack.model = stackModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift index 24979f78..790e8598 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift @@ -8,33 +8,12 @@ import Foundation -public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: ContainerModel, ListItemModelProtocol { +public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { - public var line: LineModel? - public var style: String? = "standard" - public var hideArrow: Bool? = false - public var backgroundColor: Color? - public var action: ActionModelProtocol? public static var identifier: String = "listLVCB" public var checkbox: CheckboxModel - public var spacing: CGFloat = 16.0 var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel - func setDefaults() { - if useHorizontalMargins == nil { - useHorizontalMargins = true - } - if useVerticalMargins == nil { - useVerticalMargins = true - } - if topMarginPadding == nil { - topMarginPadding = 24 - } - if bottomMarginPadding == nil { - bottomMarginPadding = 0 - } - } - init(checkbox: CheckboxModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { self.checkbox = checkbox self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink @@ -43,35 +22,23 @@ public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: Contain private enum CodingKeys: String, CodingKey { case moleculeName - case backgroundColor case eyebrowHeadlineBodyLink case checkbox - case action - case spacing } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox) - action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) - if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { - self.spacing = spacing - } 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) try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) try container.encode(checkbox, forKey: .checkbox) - try container.encodeModelIfPresent(action, forKey: .action) - try container.encodeIfPresent(spacing, forKey: .spacing) } } From 6cbf4a53bc42073a56f141c94b42dde190963bc8 Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 14 Feb 2020 14:09:03 +0530 Subject: [PATCH 20/96] Restructured file group. --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++-- ...istLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift | 0 ...ftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename MVMCoreUI/Molecules/{LeftRightViews => DesignedComponents/List/LeftVariable}/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift (100%) rename MVMCoreUI/Molecules/{LeftRightViews => DesignedComponents/List/LeftVariable}/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift (100%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 455cb573..f31234f2 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -912,8 +912,6 @@ D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */, 01509D902327ECE600EF99AA /* CornerLabels.swift */, D224798823142BF2003FCCF9 /* ToggleMolecules */, - AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */, - AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */, ); path = LeftRightViews; sourceTree = ""; @@ -977,6 +975,8 @@ children = ( 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, + AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */, + AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */, ); path = LeftVariable; sourceTree = ""; diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift similarity index 100% rename from MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift diff --git a/MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift similarity index 100% rename from MVMCoreUI/Molecules/LeftRightViews/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift From 0d6322b69312171dac883de1baed58ea8d2dccae Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Fri, 14 Feb 2020 16:02:05 +0530 Subject: [PATCH 21/96] Removed percent for stackitems. --- .../List/RightVariable/ListRightVariablePayments.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 5f2870ec..626e8d42 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -54,9 +54,9 @@ import Foundation rightImage.setWithModel(model.image, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of label and image - let leftLabel = StackItemModel(percent: 60) + let leftLabel = StackItemModel() leftLabel.horizontalAlignment = .leading - let rightImage = StackItemModel(percent: 40) + let rightImage = StackItemModel() rightImage.horizontalAlignment = .trailing let stackModel = StackModel(molecules: [leftLabel,rightImage]) stackModel.axis = .horizontal From 21fc9c1802385206368ec37e9768d77403524e69 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Fri, 14 Feb 2020 17:46:56 +0530 Subject: [PATCH 22/96] Adding up the percentages for stacks. --- .../List/RightVariable/ListRightVariablePayments.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 626e8d42..e46cc469 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -37,16 +37,14 @@ import Foundation contentView.addSubview(stack) containerHelper.constrainView(stack) } - //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ - override open func reset() { super.reset() stack.reset() } - +   public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListRightVariablePaymentsModel else { return} @@ -54,9 +52,9 @@ import Foundation rightImage.setWithModel(model.image, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of label and image - let leftLabel = StackItemModel() + let leftLabel = StackItemModel(percent: 70) leftLabel.horizontalAlignment = .leading - let rightImage = StackItemModel() + let rightImage = StackItemModel(percent: 30) rightImage.horizontalAlignment = .trailing let stackModel = StackModel(molecules: [leftLabel,rightImage]) stackModel.axis = .horizontal From 5da415d0fc21accdc4c40738ed98dca4639029cb Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Fri, 14 Feb 2020 18:17:10 +0530 Subject: [PATCH 23/96] removed line break. --- ...tLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift index 790e8598..330901a6 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift @@ -40,5 +40,4 @@ public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: ListIte try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) try container.encode(checkbox, forKey: .checkbox) } - } From e431ea2de9690a6ae61ed90c9ec9c538cff6af0e Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 14 Feb 2020 15:56:36 -0500 Subject: [PATCH 24/96] fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atoms/Views/ImageViewModel.swift | 24 ++++- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 6 +- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 48 +++++++++ .../HeadlineBodyModel.swift | 1 + .../MVMCoreUIViewControllerMappingObject.m | 4 +- .../Templates/IsaacLandingTemplate.swift | 100 ++++++++++++++++++ 7 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 MVMCoreUI/Templates/IsaacLandingTemplate.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d114d2ae..6ac575a6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; + 01B5E6B023F5F276005B5839 /* IsaacLandingTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B5E6AF23F5F276005B5839 /* IsaacLandingTemplate.swift */; }; 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C851D223CF9E740021F976 /* LabelToggleModel.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; }; @@ -382,6 +383,7 @@ 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; + 01B5E6AF23F5F276005B5839 /* IsaacLandingTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IsaacLandingTemplate.swift; sourceTree = ""; }; 01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = ""; }; 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeModelProtocol.swift; sourceTree = ""; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; @@ -1068,6 +1070,7 @@ D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */, 014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */, D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */, + 01B5E6AF23F5F276005B5839 /* IsaacLandingTemplate.swift */, ); path = Templates; sourceTree = ""; @@ -1810,6 +1813,7 @@ D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */, 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, + 01B5E6B023F5F276005B5839 /* IsaacLandingTemplate.swift in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index ce46a930..f8443da5 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -11,11 +11,33 @@ import Foundation @objcMembers public class ImageViewModel: MoleculeModelProtocol { public static var identifier: String = "image" public var backgroundColor: Color? - + public var moleculeName: String? public var image: String public var accessibilityText: String? public var fallbackImage: String? public var imageFormat: String? public var width: CGFloat? public var height: CGFloat? + public var contentMode: ContentMode? + + public enum ContentMode : String, Codable { + case scaleToFill + case scaleAspectFit // contents scaled to fit with fixed aspect. remainder is transparent + case scaleAspectFill // contents scaled to fill with fixed aspect. some portion of content may be clipped. + case redraw // redraw on bounds change (calls -setNeedsDisplay) + case center // contents remain same size. positioned adjusted. + case top + case bottom + case left + case right + case topLeft + case topRight + case bottomLeft + case bottomRight + } + + public init(image: String) { + self.image = image + moleculeName = Self.identifier + } } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index 731b23da..a177f414 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -45,7 +45,11 @@ import Foundation enum AttributeTypeKey: String, CodingKey { case type } - + + public init(text: String) { + self.text = text + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 1c54b891..d46a5150 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -232,6 +232,54 @@ import UIKit imageView.animatedImage = nil loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage) } + setContentMode(imageModel) + } + + func setContentMode(_ model: ImageViewModel?) { + switch model?.contentMode { + case .scaleToFill: + imageView.contentMode = .scaleToFill + break + case .scaleAspectFit: + imageView.contentMode = .scaleAspectFit + break + case .scaleAspectFill: + imageView.contentMode = .scaleAspectFill + break + case .redraw: + imageView.contentMode = .redraw + break + case .center: + imageView.contentMode = .center + break + case .top: + imageView.contentMode = .top + break + case .bottom: + imageView.contentMode = .bottom + break + case .left: + imageView.contentMode = .left + break + case .right: + imageView.contentMode = .right + break + case .topLeft: + imageView.contentMode = .topLeft + break + case .topRight: + imageView.contentMode = .topRight + break + case .bottomLeft: + imageView.contentMode = .bottomLeft + break + case .bottomRight: + imageView.contentMode = .bottomRight + break + default: + break + } + } // MARK: - MVMCoreUIMoleculeViewProtocol functions diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 1fbe98e7..8d649995 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -18,5 +18,6 @@ import Foundation public init(headline: LabelModel) { self.headline = headline + moleculeName = Self.identifier } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index 7bdccc8e..fb29096c 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -22,8 +22,8 @@ @"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], @"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], - @"threeLayer" : - [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]] + @"threeLayer": [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]], + @"isaacLanding": [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[IsaacLandingTemplate class]] } mutableCopy]; }); return viewControllerMapping; diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift new file mode 100644 index 00000000..f6924c12 --- /dev/null +++ b/MVMCoreUI/Templates/IsaacLandingTemplate.swift @@ -0,0 +1,100 @@ +// +// IsaacLandingTemplate.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +open class IsaacLandingTemplate: MoleculeListTemplate { + + func parseTemplateJSON() throws { + + } + + @objc public override func parsePageJSON() throws { + guard let pageJSON = self.loadObject?.pageJSON else { return } + + var listItems: [MoleculeListItemModel] = [] + (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in + if let item = getListItem(itemJson) { + listItems.append(item) + } + } + + let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), + screenHeading: pageJSON.stringForkey(KeyScreenHeading), + molecules: listItems) + + + self.templateModel = template + } + + func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { + guard let type = moleculeJson.optionalStringForKey("type") else { + return nil + } + + if type == "rewards" { + return getRewardListItem(moleculeJson) + } + + let textcolor = moleculeJson.optionalStringForKey("textColor") + var stackItems: [MoleculeStackItemModel] = [] + + let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 + + + let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) + messageLabel.fontStyle = "B2" + messageLabel.textColor = textcolor + + let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) + headlineBodyModel.body = messageLabel + + if let linkMap = moleculeJson.optionalDictionaryForKey("link") { + do { + let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), + "action": linkMap] + let data = try JSONSerialization.data(withJSONObject: linkDict) + let decoder = JSONDecoder() + let linkModel = try decoder.decode(LinkModel.self, from: data) + linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) + let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, + link: linkModel) + stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) + } catch { + + } + } else { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + + if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { + let imageModel = ImageViewModel(image: imageurl) + imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 + imageModel.imageFormat = "jpeg" + imageModel.contentMode = .scaleAspectFit + stackItems.append(MoleculeStackItemModel(with: imageModel)) + } + + let stack = MoleculeStackModel(molecules: stackItems) + let listItem = MoleculeListItemModel(with: stack) + + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + return listItem + } + + func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { + return nil + } +} + From 87dcde33176eead722a6c6399f9496f6a6d14ff4 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 12:11:57 -0500 Subject: [PATCH 25/96] WIP --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 8 + .../Views/Label/LabelAttributeModel.swift | 8 +- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 1 + MVMCoreUI/BaseClasses/Button.swift | 7 +- MVMCoreUI/Molecules/FooterModel.swift | 2 + .../TwoButtonViewModel.swift | 5 + .../Items/MoleculeStackItemModel.swift | 2 + .../Templates/IsaacLandingTemplate.swift | 190 +++++++++++++----- 8 files changed, 171 insertions(+), 52 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index cfe8bb2f..5640996f 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -39,12 +39,20 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { init(with title: String, action: ActionModelProtocol) { self.title = title self.action = action + moleculeName = Self.identifier } init(secondaryButtonWith title: String, action: ActionModelProtocol) { self.title = title self.action = action style = .secondary + moleculeName = Self.identifier + } + + init(primaryButtonWith title: String, action: ActionModelProtocol) { + self.title = title + self.action = action + style = .primary } private enum CodingKeys: String, CodingKey { diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift index 22bb10d8..3c073b2f 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift @@ -28,7 +28,13 @@ import Foundation var type: String var location: Int var length: Int - + + init(_ type: String, _ location: Int, _ length: Int) { + self.type = type + self.location = location + self.length = length + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index a177f414..76597b44 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -48,6 +48,7 @@ import Foundation public init(text: String) { self.text = text + moleculeName = Self.identifier } required public init(from decoder: Decoder) throws { diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index a780151a..24378184 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -88,12 +88,13 @@ public typealias ButtonAction = (Button) -> () // MARK:- ModelMoleculeViewProtocol open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model - if let backgroundColor = model?.backgroundColor { - self.backgroundColor = backgroundColor.uiColor - } guard let model = model as? ButtonModelProtocol else { return } isEnabled = model.enabled + + if let backgroundColor = (model as? MoleculeModelProtocol)?.backgroundColor { + self.backgroundColor = backgroundColor.uiColor + } set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } diff --git a/MVMCoreUI/Molecules/FooterModel.swift b/MVMCoreUI/Molecules/FooterModel.swift index d61d1194..57a81f8b 100644 --- a/MVMCoreUI/Molecules/FooterModel.swift +++ b/MVMCoreUI/Molecules/FooterModel.swift @@ -12,6 +12,7 @@ import Foundation @objcMembers public class FooterModel: MoleculeContainerModel, MoleculeModelProtocol { public static var identifier: String = "footer" public var backgroundColor: Color? + public var moleculeName: String? private enum CodingKeys: String, CodingKey { case moleculeName @@ -37,6 +38,7 @@ import Foundation public override init(with moleculeModel: MoleculeModelProtocol) { super.init(with: moleculeModel) setDefaults() + moleculeName = Self.identifier } required public init(from decoder: Decoder) throws { diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 5938692b..70d3f743 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -10,6 +10,7 @@ import UIKit public class TwoButtonViewModel: MoleculeModelProtocol { public static var identifier: String = "twoButtonView" + public var moleculeName: String? public var backgroundColor: Color? public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? @@ -21,6 +22,10 @@ public class TwoButtonViewModel: MoleculeModelProtocol { case secondaryButton } + init() { + moleculeName = Self.identifier + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift index 4731ef34..2b23f405 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift @@ -13,6 +13,7 @@ import Foundation public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? + public var moleculeName: String? public var gone: Bool = false private enum CodingKeys: String, CodingKey { @@ -24,6 +25,7 @@ import Foundation public override init(with moleculeModel: MoleculeModelProtocol) { super.init(with: moleculeModel) + moleculeName = Self.identifier } required public init(from decoder: Decoder) throws { diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift index f6924c12..99c716d6 100644 --- a/MVMCoreUI/Templates/IsaacLandingTemplate.swift +++ b/MVMCoreUI/Templates/IsaacLandingTemplate.swift @@ -29,8 +29,59 @@ open class IsaacLandingTemplate: MoleculeListTemplate { screenHeading: pageJSON.stringForkey(KeyScreenHeading), molecules: listItems) - + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + template.footer = setFooter(pageJSON, template) + //print(template.toJSONString()) self.templateModel = template + + DispatchQueue.main.async { [weak self] in + self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) + } + } + + func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { + + let primaryButtonBGColor = pageJSON.optionalStringForKey("primaryButtonBGColor") ?? "#FFFFFF" + let primaryButtonTextColor = pageJSON.optionalStringForKey("primaryButtonTextColor") ?? "#000000" + + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + if let buttonMap = pageJSON.optionalDictionaryForKey("ButtonMap") { + let twoButtonModel = TwoButtonViewModel() + + if let primarybutton = buttonMap.optionalDictionaryForKey(KeyPrimaryButton) { + let buttonDict: [String : Any] = ["title": primarybutton.stringForkey(KeyTitle), + "action": primarybutton, + "moleculeName": "button"] + if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { + let decoder = JSONDecoder() + twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) + twoButtonModel.primaryButton?.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) + twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + } + } + if let secondaryButton = buttonMap.optionalDictionaryForKey(KeySecondaryButton) { + let buttonDict: [String : Any] = ["title": secondaryButton.stringForkey(KeyTitle), + "action": secondaryButton, + "moleculeName": "button"] + if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { + let decoder = JSONDecoder() + twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) + twoButtonModel.secondaryButton?.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) + } + } + + let footerStack = MoleculeStackModel(molecules: [MoleculeStackItemModel(with:LineModel(type: .standard)), + MoleculeStackItemModel(with: twoButtonModel)]) + footerStack.useHorizontalMargins = false + footerStack.spacing = PaddingFour + + let footer = FooterModel(with: footerStack) + footer.useHorizontalMargins = false + footer.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + return footer + } + return nil } func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { @@ -40,61 +91,104 @@ open class IsaacLandingTemplate: MoleculeListTemplate { if type == "rewards" { return getRewardListItem(moleculeJson) - } - - let textcolor = moleculeJson.optionalStringForKey("textColor") - var stackItems: [MoleculeStackItemModel] = [] - - let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 - - - let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) - messageLabel.fontStyle = "B2" - messageLabel.textColor = textcolor - - let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) - headlineBodyModel.body = messageLabel - - if let linkMap = moleculeJson.optionalDictionaryForKey("link") { - do { - let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), - "action": linkMap] - let data = try JSONSerialization.data(withJSONObject: linkDict) - let decoder = JSONDecoder() - let linkModel = try decoder.decode(LinkModel.self, from: data) - linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) - let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, - link: linkModel) - stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) - } catch { - - } } else { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + return getTitleImageListItem(moleculeJson, type) } + } - if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { - let imageModel = ImageViewModel(image: imageurl) - imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 - imageModel.imageFormat = "jpeg" - imageModel.contentMode = .scaleAspectFit - stackItems.append(MoleculeStackItemModel(with: imageModel)) - } + func getTitleImageListItem(_ moleculeJson: [AnyHashable: Any], _ type: String) -> MoleculeListItemModel? { + let textcolor = moleculeJson.optionalStringForKey("textColor") + var stackItems: [MoleculeStackItemModel] = [] - let stack = MoleculeStackModel(molecules: stackItems) - let listItem = MoleculeListItemModel(with: stack) + let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - return listItem + let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) + messageLabel.fontStyle = "B2" + messageLabel.textColor = textcolor + + let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) + headlineBodyModel.body = messageLabel + + if let linkMap = moleculeJson.optionalDictionaryForKey("link") { + do { + let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), + "action": linkMap] + let data = try JSONSerialization.data(withJSONObject: linkDict) + let decoder = JSONDecoder() + let linkModel = try decoder.decode(LinkModel.self, from: data) + linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) + let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, + link: linkModel) + stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) + } catch { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + } else { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + + if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { + let imageModel = ImageViewModel(image: imageurl) + imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 + imageModel.imageFormat = "jpeg" + imageModel.contentMode = .scaleAspectFit + stackItems.append(MoleculeStackItemModel(with: imageModel)) + } + + let stack = MoleculeStackModel(molecules: stackItems) + let listItem = MoleculeListItemModel(with: stack) + + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + return listItem } func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - return nil + + var stackItems: [MoleculeStackItemModel] = [] + + (moleculeJson.arrayForKey("rewards") as? [[AnyHashable: Any]])?.forEach { (rewardItem) in + let textcolor = rewardItem.optionalStringForKey("textColor") + + let titleLabel = LabelModel(text: rewardItem.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = 48 + + let messageLabel = LabelModel(text: rewardItem.stringForkey("message")) + messageLabel.fontName = "NHaasGroteskDSStd-75Bd" + messageLabel.textColor = textcolor + messageLabel.fontSize = 14 + + let titleStackItem = MoleculeStackItemModel(with: titleLabel) + let messageStackItem = MoleculeStackItemModel(with: messageLabel) + + let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) + itemStack.useVerticalMargins = false + itemStack.topMarginPadding = 0 + + itemStack.verticalAlignment = .leading + itemStack.axis = .vertical + itemStack.spacing = 0 + + stackItems.append(MoleculeStackItemModel(with: itemStack)) + } + + let stack = MoleculeStackModel(molecules: stackItems) + stack.axis = .horizontal + stack.spacing = 65 + stack.verticalAlignment = .leading + + let listItem = MoleculeListItemModel(with: stack) + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + + return listItem } } From 273b1317145fc83d7dcdf6c1890bc5e861b906a8 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Mon, 17 Feb 2020 22:50:43 +0530 Subject: [PATCH 26/96] Code commit - changes has to be done to model. --- MVMCoreUI/Atoms/Views/ImageViewModel.swift | 4 ++++ .../List/RightVariable/ListRightVariablePayments.swift | 5 +++-- .../RightVariable/ListRightVariablePaymentsModel.swift | 10 ++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index ce46a930..c6eb9668 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -18,4 +18,8 @@ import Foundation public var imageFormat: String? public var width: CGFloat? public var height: CGFloat? + + public init(image: String) { + self.image = image + } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index e46cc469..91703fd7 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -36,6 +36,7 @@ import Foundation stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] contentView.addSubview(stack) containerHelper.constrainView(stack) + } //---------------------------------------------------- // MARK: - Molecule @@ -52,9 +53,9 @@ import Foundation rightImage.setWithModel(model.image, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of label and image - let leftLabel = StackItemModel(percent: 70) + let leftLabel = StackItemModel() leftLabel.horizontalAlignment = .leading - let rightImage = StackItemModel(percent: 30) + let rightImage = StackItemModel() rightImage.horizontalAlignment = .trailing let stackModel = StackModel(molecules: [leftLabel,rightImage]) stackModel.axis = .horizontal diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 23545142..422cd193 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -15,11 +15,17 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco public var leftLabel: LabelModel public init(image: ImageViewModel, leftLabel: LabelModel) { - self.image = image self.leftLabel = leftLabel + self.image = image super.init() } + func createPayPalImage() -> ImageViewModel { + let image = ImageViewModel(image: "imagename_paypal") + image.width = 30.0 + return image + } + private enum CodingKeys: String, CodingKey { case moleculeName case leftLabel @@ -29,7 +35,7 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) - image = try typeContainer.decode(ImageViewModel.self, forKey: .image) + image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) ?? createPayPalImage() try super.init(from: decoder) } From 06fe32f37b9a118fcf34fcb821f66340d93e63e8 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 17 Feb 2020 12:21:32 -0500 Subject: [PATCH 27/96] changing pumpkin to orange for design update. --- MVMCoreUI/Categories/UIColor+Extension.swift | 177 ++++++++++++++++--- MVMCoreUI/Categories/UIColor+MFConvenience.h | 1 + MVMCoreUI/Categories/UIColor+MFConvenience.m | 5 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 2 +- 4 files changed, 162 insertions(+), 23 deletions(-) diff --git a/MVMCoreUI/Categories/UIColor+Extension.swift b/MVMCoreUI/Categories/UIColor+Extension.swift index 55a10c03..94bf780d 100644 --- a/MVMCoreUI/Categories/UIColor+Extension.swift +++ b/MVMCoreUI/Categories/UIColor+Extension.swift @@ -12,24 +12,52 @@ public typealias ColorHexTuple = (uiColor: UIColor, hex: String) extension UIColor { + //-------------------------------------------------- + // MARK: - Convenience Dictionary + //-------------------------------------------------- /// Dictionary to access brand approved colors by name. public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"), "white": (.mvmWhite, "#FFFFFF"), "red": (.mvmRed, "#D52B1E"), - "orange": (.mvmOrange, "#CC4D0F"), - "green": (.mvmGreen, "#008631"), - "blue": (.mvmBlue, "#007AB8"), - "blueGradient": (.mvmBlueGradient, "#007AB8"), + "pink": (.mvmPink, "#D90368"), + "pink33": (.mvmPink33, "#F2ABCD"), + "pink66": (.mvmPink66, "#E6589B"), + "pinkShade1": (.mvmPinkShade1, "#B31C63"), + "pinkShade2": (.mvmPinkShade2, "#830842"), + "purple": (.mvmPurple, "#8C00AC"), + "purple33": (.mvmPurple33, "#D9ABE4"), + "purple66": (.mvmPurple66, "#B356C8"), + "purpleShade1": (.mvmPurpleShade1, "#6C177F"), + "purpleShade2": (.mvmPurpleShade2, "#4A0E58"), + "green": (.mvmGreen, "#008330"), + "green33": (.mvmGreen33, "#ABE4BF"), + "green66": (.mvmGreen66, "#57C880"), + "greenShade1": (.mvmGreenShade1, "#178437"), + "greenShade2": (.mvmGreenShade2, "#0F5B25"), + "orange": (.mvmOrange, "#ED7000"), + "orange66": (.mvmOrange66, "#F3A157"), + "orange33": (.mvmOrange33, "#F9D0AB"), + "orangeShade1": (.mvmOrangeShade1, "#CB5F00"), + "orangeShade2": (.mvmOrangeShade2, "#984700"), + "orangeAA": (.mvmOrangeAA, "#CC4D0F"), + "blue": (.mvmBlue, "#0077B4"), + "blue33": (.mvmBlue33, "#57B1DF"), + "blue66": (.mvmBlue66, "#57B1DF"), + "blueShade1": (.mvmBlueShade1, "#136598"), + "blueShade2": (.mvmBlueShade2, "#0B4467"), "yellow": (.mvmYellow, "#FFBC3D"), + "yellow33": (.mvmYellow33, "#FFE9BF"), + "yellow66": (.mvmYellow66, "#FFD37F"), + "yellowShade1": (.mvmYellowShade1, "#CC9630"), + "yellowShade2": (.mvmYellowShade2, "#997126"), "coolGray1": (.mvmCoolGray1, "#F6F6F6"), "coolGray3": (.mvmCoolGray3, "#D8DADA"), "coolGray6": (.mvmCoolGray6, "#747676"), "coolGray10": (.mvmCoolGray10, "#333333"), - "vzupGold": (.vzupGold, "#B89B56"), - "vzupYellow1": (.vzupYellow1, "#F9D542"), - "vzupYellow2": (.vzupYellow2, "#F4CA53"), - "vzupYellow3": (.vzupYellow3, "#CC9B2D")] + "upGold1": (.vzupGold1, "#F9D542"), + "upGold2": (.vzupGold2, "#F4CA53"), + "upGold3": (.vzupGold3, "#CC9B2D")] //-------------------------------------------------- // MARK: - Brand @@ -41,24 +69,134 @@ extension UIColor { /// HEX: #FFFFFF public static let mvmWhite = UIColor.white + //-------------------------------------------------- + // MARK: - Red + //-------------------------------------------------- + /// HEX: #D52B1E public static let mvmRed = UIColor.color8Bits(red: 213, green: 43, blue: 30) + //-------------------------------------------------- + // MARK: - Pink + //-------------------------------------------------- + + /// HEX: #D90368 + public static let mvmPink = UIColor.color8Bits(red: 217, green: 3, blue: 104) + + /// HEX: #F2ABCD + public static let mvmPink33 = UIColor.color8Bits(red: 242, green: 171, blue: 205) + + /// HEX: #E6589B + public static let mvmPink66 = UIColor.color8Bits(red: 230, green: 88, blue: 155) + + /// HEX: #B31C63 + public static let mvmPinkShade1 = UIColor.color8Bits(red: 179, green: 28, blue: 99) + + /// HEX: #830842 + public static let mvmPinkShade2 = UIColor.color8Bits(red: 131, green: 8, blue: 66) + + //-------------------------------------------------- + // MARK: - Purple + //-------------------------------------------------- + + /// HEX: #8C00AC + public static let mvmPurple = UIColor.color8Bits(red: 140, green: 0, blue: 172) + + /// HEX: #D9ABE4 + public static let mvmPurple33 = UIColor.color8Bits(red: 217, green: 171, blue: 228) + + /// HEX: #B356C8 + public static let mvmPurple66 = UIColor.color8Bits(red: 179, green: 86, blue: 200) + + /// HEX: #6C177F + public static let mvmPurpleShade1 = UIColor.color8Bits(red: 108, green: 23, blue: 127) + + /// HEX: #4A0E58 + public static let mvmPurpleShade2 = UIColor.color8Bits(red: 74, green: 14, blue: 88) + + //-------------------------------------------------- + // MARK: - Orange + //-------------------------------------------------- + + /// HEX: #ED7000 + public static let mvmOrange = UIColor.color8Bits(red: 237, green: 112, blue: 0) + /// HEX: #CC4D0F - public static let mvmOrange = UIColor.color8Bits(red: 204, green: 77, blue: 15) + public static let mvmOrangeAA = UIColor.color8Bits(red: 204, green: 77, blue: 15) - /// HEX: #008631 - public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 49) + /// HEX: #F9D0AB + public static let mvmOrange33 = UIColor.color8Bits(red: 249, green: 208, blue: 171) - /// HEX: #007AB8 - public static let mvmBlue = UIColor.color8Bits(red: 0, green: 122, blue: 184) + /// HEX: #F3A157 + public static let mvmOrange66 = UIColor.color8Bits(red: 243, green: 161, blue: 87) - /// HEX: #007AB8 - public static let mvmBlueGradient = UIColor.color8Bits(red: 0, green: 122, blue: 184) + /// HEX: #CB5F00 + public static let mvmOrangeShade1 = UIColor.color8Bits(red: 203, green: 95, blue: 0) + + /// HEX: #984700 + public static let mvmOrangeShade2 = UIColor.color8Bits(red: 152, green: 71, blue: 0) + + //-------------------------------------------------- + // MARK: - Green + //-------------------------------------------------- + + /// HEX: #008330 + public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 48) + + /// HEX: #ABE4BF + public static let mvmGreen33 = UIColor.color8Bits(red: 171, green: 228, blue: 191) + + /// HEX: #57C880 + public static let mvmGreen66 = UIColor.color8Bits(red: 87, green: 200, blue: 128) + + /// HEX: #178437 + public static let mvmGreenShade1 = UIColor.color8Bits(red: 23, green: 132, blue: 55) + + /// HEX: #0F5B25 + public static let mvmGreenShade2 = UIColor.color8Bits(red: 15, green: 91, blue: 37) + + //-------------------------------------------------- + // MARK: - Blue + //-------------------------------------------------- + + /// HEX: #0077B4 + public static let mvmBlue = UIColor.color8Bits(red: 0, green: 119, blue: 180) + + /// HEX: #57B1DF + public static let mvmBlue33 = UIColor.color8Bits(red: 87, green: 177, blue: 223) + + /// HEX: #57B1DF + public static let mvmBlue66 = UIColor.color8Bits(red: 87, green: 177, blue: 223) + + /// HEX: #136598 + public static let mvmBlueShade1 = UIColor.color8Bits(red: 19, green: 101, blue: 152) + + /// HEX: #0B4467 + public static let mvmBlueShade2 = UIColor.color8Bits(red: 11, green: 68, blue: 103) + + //-------------------------------------------------- + // MARK: - Yellow + //-------------------------------------------------- /// HEX: #FFBC3D public static let mvmYellow = UIColor.color8Bits(red: 255, green: 188, blue: 61) + /// HEX: #FFE9BF + public static let mvmYellow33 = UIColor.color8Bits(red: 255, green: 233, blue: 191) + + /// HEX: #FFD37F + public static let mvmYellow66 = UIColor.color8Bits(red: 255, green: 211, blue: 127) + + /// HEX: #CC9630 + public static let mvmYellowShade1 = UIColor.color8Bits(red: 204, green: 150, blue: 48) + + /// HEX: #997126 + public static let mvmYellowShade2 = UIColor.color8Bits(red: 153, green: 113, blue: 38) + + //-------------------------------------------------- + // MARK: - Gray + //-------------------------------------------------- + /// HEX: #F6F6F6 public static let mvmCoolGray1 = UIColor.grayscale(rgb: 246) @@ -75,17 +213,14 @@ extension UIColor { // MARK: - VZ UP Brand //-------------------------------------------------- - /// HEX: #B89B56 - public static let vzupGold = UIColor.color8Bits(red: 184, green: 155, blue: 68) - /// HEX: #F9D542 - public static let vzupYellow1 = UIColor.color8Bits(red: 249, green: 213, blue: 66) + public static let vzupGold1 = UIColor.color8Bits(red: 249, green: 213, blue: 66) /// HEX: #F4CA53 - public static let vzupYellow2 = UIColor.color8Bits(red: 244, green: 202, blue: 83) + public static let vzupGold2 = UIColor.color8Bits(red: 244, green: 202, blue: 83) /// HEX: #CC9B2D - public static let vzupYellow3 = UIColor.color8Bits(red: 204, green: 155, blue: 45) + public static let vzupGold3 = UIColor.color8Bits(red: 204, green: 155, blue: 45) //-------------------------------------------------- // MARK: - Functions diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.h b/MVMCoreUI/Categories/UIColor+MFConvenience.h index 4a51a13b..c3c78c7a 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.h +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.h @@ -21,6 +21,7 @@ + (nonnull UIColor *)mfLightSilver; + (nonnull UIColor *)mfDarkSilver; + (nonnull UIColor *)mfTomatoRed; ++ (nonnull UIColor *)mvmOrange; + (nonnull UIColor *)mfPumpkinColor; + (nonnull UIColor *)mfShamrock; + (nonnull UIColor *)mfCerulean; diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.m b/MVMCoreUI/Categories/UIColor+MFConvenience.m index e56d89bc..6ff8f70f 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.m +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.m @@ -37,7 +37,6 @@ return [UIColor mfColor8bitsWithRed:198 green:197 blue:197 alpha:1.0]; } - + (nonnull UIColor *)mfPrimaryButtonHighlightBlackColor { return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.0]; } @@ -54,6 +53,10 @@ return [UIColor mfColor8bitsWithRed:204 green:77 blue:15 alpha:1.0]; } ++ (nonnull UIColor *)mvmOrange { + return [UIColor mfColor8bitsWithRed:237 green:112 blue:0 alpha:1.0]; +} + + (nonnull UIColor *)mfShamrock { return [UIColor mfColor8bitsWithRed:0 green:134 blue:49 alpha:1.0]; } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index 947e6ffc..d0a027b3 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -108,7 +108,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; - (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type { if ([type isEqualToString:ValueTypeError]) { - return [UIColor mfPumpkinColor]; + return [UIColor mvmOrange]; } else { return [UIColor mfShamrock]; } From cf4832bca7984053da7e029de9857e57444d6d90 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 13:39:13 -0500 Subject: [PATCH 28/96] fixes --- MVMCoreUI/Templates/IsaacLandingTemplate.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift index 99c716d6..0001c744 100644 --- a/MVMCoreUI/Templates/IsaacLandingTemplate.swift +++ b/MVMCoreUI/Templates/IsaacLandingTemplate.swift @@ -168,19 +168,19 @@ open class IsaacLandingTemplate: MoleculeListTemplate { let messageStackItem = MoleculeStackItemModel(with: messageLabel) let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) - itemStack.useVerticalMargins = false - itemStack.topMarginPadding = 0 - - itemStack.verticalAlignment = .leading - itemStack.axis = .vertical + itemStack.verticalAlignment = .top itemStack.spacing = 0 - stackItems.append(MoleculeStackItemModel(with: itemStack)) + let horizontalStack = MoleculeStackItemModel(with: itemStack) + horizontalStack.verticalAlignment = .top + stackItems.append(horizontalStack) } + stackItems.first?.percent = 35 + stackItems.last?.percent = 65 let stack = MoleculeStackModel(molecules: stackItems) stack.axis = .horizontal - stack.spacing = 65 + stack.horizontalAlignment = .leading stack.verticalAlignment = .leading let listItem = MoleculeListItemModel(with: stack) From 6de4fc486445b1f0c66557ee520698c458e1fcbe Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 14:19:17 -0500 Subject: [PATCH 29/96] fill color --- MVMCoreUI/BaseClasses/Button.swift | 9 ++++----- MVMCoreUI/Templates/IsaacLandingTemplate.swift | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index 24378184..60e0ab1a 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -88,13 +88,12 @@ public typealias ButtonAction = (Button) -> () // MARK:- ModelMoleculeViewProtocol open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model - - guard let model = model as? ButtonModelProtocol else { return } - isEnabled = model.enabled - - if let backgroundColor = (model as? MoleculeModelProtocol)?.backgroundColor { + if let backgroundColor = model?.backgroundColor { self.backgroundColor = backgroundColor.uiColor } + + guard let model = model as? ButtonModelProtocol else { return } + isEnabled = model.enabled set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift index 0001c744..c3d9e9cb 100644 --- a/MVMCoreUI/Templates/IsaacLandingTemplate.swift +++ b/MVMCoreUI/Templates/IsaacLandingTemplate.swift @@ -55,7 +55,7 @@ open class IsaacLandingTemplate: MoleculeListTemplate { if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { let decoder = JSONDecoder() twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.primaryButton?.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) + twoButtonModel.primaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) } } @@ -66,7 +66,7 @@ open class IsaacLandingTemplate: MoleculeListTemplate { if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { let decoder = JSONDecoder() twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.secondaryButton?.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + twoButtonModel.secondaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) } } From 438661dfe1fe1edf4a4ca4cbbc4f9927021fca9a Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 15:05:02 -0500 Subject: [PATCH 30/96] moleculeName --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 6 ++---- MVMCoreUI/Atoms/Views/ImageViewModel.swift | 2 -- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 4 ---- MVMCoreUI/Molecules/FooterModel.swift | 2 -- .../HorizontalCombinationViews/TwoButtonViewModel.swift | 5 +---- MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift | 4 +--- .../VerticalCombinationViews/HeadlineBodyModel.swift | 2 -- 7 files changed, 4 insertions(+), 21 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 5640996f..2f5e0042 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -20,7 +20,6 @@ public enum ButtonSize: String, Codable { public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public static var identifier: String = "button" - public var moleculeName: String? public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol @@ -39,14 +38,14 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { init(with title: String, action: ActionModelProtocol) { self.title = title self.action = action - moleculeName = Self.identifier + //moleculeName = Self.identifier } init(secondaryButtonWith title: String, action: ActionModelProtocol) { self.title = title self.action = action style = .secondary - moleculeName = Self.identifier + //moleculeName = Self.identifier } init(primaryButtonWith title: String, action: ActionModelProtocol) { @@ -75,7 +74,6 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index f8443da5..497b0c86 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -11,7 +11,6 @@ import Foundation @objcMembers public class ImageViewModel: MoleculeModelProtocol { public static var identifier: String = "image" public var backgroundColor: Color? - public var moleculeName: String? public var image: String public var accessibilityText: String? public var fallbackImage: String? @@ -38,6 +37,5 @@ import Foundation public init(image: String) { self.image = image - moleculeName = Self.identifier } } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index 76597b44..d7fb4fa3 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -11,9 +11,7 @@ import Foundation @objcMembers public class LabelModel: MoleculeModelProtocol { public static var identifier: String = "label" - public var moleculeName: String? public var backgroundColor: Color? - public var text: String public var accessibilityText: String? public var textColor: String? @@ -48,12 +46,10 @@ import Foundation public init(text: String) { self.text = text - moleculeName = Self.identifier } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) text = try typeContainer.decode(String.self, forKey: .text) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor) diff --git a/MVMCoreUI/Molecules/FooterModel.swift b/MVMCoreUI/Molecules/FooterModel.swift index 57a81f8b..d61d1194 100644 --- a/MVMCoreUI/Molecules/FooterModel.swift +++ b/MVMCoreUI/Molecules/FooterModel.swift @@ -12,7 +12,6 @@ import Foundation @objcMembers public class FooterModel: MoleculeContainerModel, MoleculeModelProtocol { public static var identifier: String = "footer" public var backgroundColor: Color? - public var moleculeName: String? private enum CodingKeys: String, CodingKey { case moleculeName @@ -38,7 +37,6 @@ import Foundation public override init(with moleculeModel: MoleculeModelProtocol) { super.init(with: moleculeModel) setDefaults() - moleculeName = Self.identifier } required public init(from decoder: Decoder) throws { diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 70d3f743..4ddb1575 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -10,7 +10,6 @@ import UIKit public class TwoButtonViewModel: MoleculeModelProtocol { public static var identifier: String = "twoButtonView" - public var moleculeName: String? public var backgroundColor: Color? public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? @@ -22,9 +21,7 @@ public class TwoButtonViewModel: MoleculeModelProtocol { case secondaryButton } - init() { - moleculeName = Self.identifier - } + init() { } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift index 2b23f405..dc01fd11 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift @@ -13,7 +13,6 @@ import Foundation public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? - public var moleculeName: String? public var gone: Bool = false private enum CodingKeys: String, CodingKey { @@ -25,9 +24,8 @@ import Foundation public override init(with moleculeModel: MoleculeModelProtocol) { super.init(with: moleculeModel) - moleculeName = Self.identifier } - + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 8d649995..fd5be23a 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -10,7 +10,6 @@ import Foundation @objcMembers public class HeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "headlineBody" - public var moleculeName: String? public var headline: LabelModel? public var body: LabelModel? public var style: String? @@ -18,6 +17,5 @@ import Foundation public init(headline: LabelModel) { self.headline = headline - moleculeName = Self.identifier } } From 79eceb693ebdfa7421228f56216db207b288caa4 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 15:06:33 -0500 Subject: [PATCH 31/96] moleculeName --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 2f5e0042..f02eaf5c 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -38,14 +38,12 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { init(with title: String, action: ActionModelProtocol) { self.title = title self.action = action - //moleculeName = Self.identifier } init(secondaryButtonWith title: String, action: ActionModelProtocol) { self.title = title self.action = action style = .secondary - //moleculeName = Self.identifier } init(primaryButtonWith title: String, action: ActionModelProtocol) { From 347928a9b68b12e3c93e0870b21cdecd5ac8c9de Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 16:48:42 -0500 Subject: [PATCH 32/96] remove files --- MVMCoreUI.xcodeproj/project.pbxproj | 4 - .../MVMCoreUIViewControllerMappingObject.m | 3 +- .../Templates/IsaacLandingTemplate.swift | 194 ------------------ 3 files changed, 1 insertion(+), 200 deletions(-) delete mode 100644 MVMCoreUI/Templates/IsaacLandingTemplate.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 6ac575a6..d114d2ae 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -50,7 +50,6 @@ 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; - 01B5E6B023F5F276005B5839 /* IsaacLandingTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B5E6AF23F5F276005B5839 /* IsaacLandingTemplate.swift */; }; 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C851D223CF9E740021F976 /* LabelToggleModel.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; }; @@ -383,7 +382,6 @@ 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; - 01B5E6AF23F5F276005B5839 /* IsaacLandingTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IsaacLandingTemplate.swift; sourceTree = ""; }; 01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = ""; }; 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeModelProtocol.swift; sourceTree = ""; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; @@ -1070,7 +1068,6 @@ D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */, 014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */, D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */, - 01B5E6AF23F5F276005B5839 /* IsaacLandingTemplate.swift */, ); path = Templates; sourceTree = ""; @@ -1813,7 +1810,6 @@ D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */, 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, - 01B5E6B023F5F276005B5839 /* IsaacLandingTemplate.swift in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */, diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index fb29096c..5b9592cc 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -22,8 +22,7 @@ @"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], @"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], - @"threeLayer": [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]], - @"isaacLanding": [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[IsaacLandingTemplate class]] + @"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]] } mutableCopy]; }); return viewControllerMapping; diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift deleted file mode 100644 index c3d9e9cb..00000000 --- a/MVMCoreUI/Templates/IsaacLandingTemplate.swift +++ /dev/null @@ -1,194 +0,0 @@ -// -// IsaacLandingTemplate.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 2/13/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - - -open class IsaacLandingTemplate: MoleculeListTemplate { - - func parseTemplateJSON() throws { - - } - - @objc public override func parsePageJSON() throws { - guard let pageJSON = self.loadObject?.pageJSON else { return } - - var listItems: [MoleculeListItemModel] = [] - (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in - if let item = getListItem(itemJson) { - listItems.append(item) - } - } - - let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), - screenHeading: pageJSON.stringForkey(KeyScreenHeading), - molecules: listItems) - - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - template.footer = setFooter(pageJSON, template) - //print(template.toJSONString()) - self.templateModel = template - - DispatchQueue.main.async { [weak self] in - self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) - } - } - - func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { - - let primaryButtonBGColor = pageJSON.optionalStringForKey("primaryButtonBGColor") ?? "#FFFFFF" - let primaryButtonTextColor = pageJSON.optionalStringForKey("primaryButtonTextColor") ?? "#000000" - - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - if let buttonMap = pageJSON.optionalDictionaryForKey("ButtonMap") { - let twoButtonModel = TwoButtonViewModel() - - if let primarybutton = buttonMap.optionalDictionaryForKey(KeyPrimaryButton) { - let buttonDict: [String : Any] = ["title": primarybutton.stringForkey(KeyTitle), - "action": primarybutton, - "moleculeName": "button"] - if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { - let decoder = JSONDecoder() - twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.primaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) - twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) - } - } - if let secondaryButton = buttonMap.optionalDictionaryForKey(KeySecondaryButton) { - let buttonDict: [String : Any] = ["title": secondaryButton.stringForkey(KeyTitle), - "action": secondaryButton, - "moleculeName": "button"] - if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { - let decoder = JSONDecoder() - twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.secondaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) - twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) - } - } - - let footerStack = MoleculeStackModel(molecules: [MoleculeStackItemModel(with:LineModel(type: .standard)), - MoleculeStackItemModel(with: twoButtonModel)]) - footerStack.useHorizontalMargins = false - footerStack.spacing = PaddingFour - - let footer = FooterModel(with: footerStack) - footer.useHorizontalMargins = false - footer.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - return footer - } - return nil - } - - func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - guard let type = moleculeJson.optionalStringForKey("type") else { - return nil - } - - if type == "rewards" { - return getRewardListItem(moleculeJson) - } else { - return getTitleImageListItem(moleculeJson, type) - } - } - - func getTitleImageListItem(_ moleculeJson: [AnyHashable: Any], _ type: String) -> MoleculeListItemModel? { - let textcolor = moleculeJson.optionalStringForKey("textColor") - var stackItems: [MoleculeStackItemModel] = [] - - let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 - - let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) - messageLabel.fontStyle = "B2" - messageLabel.textColor = textcolor - - let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) - headlineBodyModel.body = messageLabel - - if let linkMap = moleculeJson.optionalDictionaryForKey("link") { - do { - let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), - "action": linkMap] - let data = try JSONSerialization.data(withJSONObject: linkDict) - let decoder = JSONDecoder() - let linkModel = try decoder.decode(LinkModel.self, from: data) - linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) - let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, - link: linkModel) - stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) - } catch { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) - } - } else { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) - } - - if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { - let imageModel = ImageViewModel(image: imageurl) - imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 - imageModel.imageFormat = "jpeg" - imageModel.contentMode = .scaleAspectFit - stackItems.append(MoleculeStackItemModel(with: imageModel)) - } - - let stack = MoleculeStackModel(molecules: stackItems) - let listItem = MoleculeListItemModel(with: stack) - - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - return listItem - } - - func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - - var stackItems: [MoleculeStackItemModel] = [] - - (moleculeJson.arrayForKey("rewards") as? [[AnyHashable: Any]])?.forEach { (rewardItem) in - let textcolor = rewardItem.optionalStringForKey("textColor") - - let titleLabel = LabelModel(text: rewardItem.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = 48 - - let messageLabel = LabelModel(text: rewardItem.stringForkey("message")) - messageLabel.fontName = "NHaasGroteskDSStd-75Bd" - messageLabel.textColor = textcolor - messageLabel.fontSize = 14 - - let titleStackItem = MoleculeStackItemModel(with: titleLabel) - let messageStackItem = MoleculeStackItemModel(with: messageLabel) - - let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) - itemStack.verticalAlignment = .top - itemStack.spacing = 0 - - let horizontalStack = MoleculeStackItemModel(with: itemStack) - horizontalStack.verticalAlignment = .top - stackItems.append(horizontalStack) - } - - stackItems.first?.percent = 35 - stackItems.last?.percent = 65 - let stack = MoleculeStackModel(molecules: stackItems) - stack.axis = .horizontal - stack.horizontalAlignment = .leading - stack.verticalAlignment = .leading - - let listItem = MoleculeListItemModel(with: stack) - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - - return listItem - } -} - From 68bf45f58310e40b2f96c9bd2a5984fffe5dbff7 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 17:35:20 -0500 Subject: [PATCH 33/96] content mode --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atoms/Views/ImageViewModel.swift | 18 +--- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 48 +-------- .../Categories/UIContentMode+Extension.swift | 98 +++++++++++++++++++ .../TwoButtonViewModel.swift | 5 +- 5 files changed, 109 insertions(+), 64 deletions(-) create mode 100644 MVMCoreUI/Categories/UIContentMode+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d114d2ae..03743382 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 012A88F123985E0100FE3DA1 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88F023985E0100FE3DA1 /* Color.swift */; }; 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; }; 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; }; + 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */; }; 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */; }; 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72223C501E2006F3E93 /* ContainerModel.swift */; }; 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */; }; @@ -359,6 +360,7 @@ 012A88F023985E0100FE3DA1 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = ""; }; 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = ""; }; + 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIContentMode+Extension.swift"; sourceTree = ""; }; 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = ""; }; 014AA72223C501E2006F3E93 /* ContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModel.swift; sourceTree = ""; }; 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModelProtocol.swift; sourceTree = ""; }; @@ -1142,6 +1144,7 @@ D29DF11021E6805F003B2FB9 /* Categories */ = { isa = PBXGroup; children = ( + 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */, D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */, D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */, D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */, @@ -1801,6 +1804,7 @@ 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, + 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index 497b0c86..97f31ad2 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -17,23 +17,7 @@ import Foundation public var imageFormat: String? public var width: CGFloat? public var height: CGFloat? - public var contentMode: ContentMode? - - public enum ContentMode : String, Codable { - case scaleToFill - case scaleAspectFit // contents scaled to fit with fixed aspect. remainder is transparent - case scaleAspectFill // contents scaled to fill with fixed aspect. some portion of content may be clipped. - case redraw // redraw on bounds change (calls -setNeedsDisplay) - case center // contents remain same size. positioned adjusted. - case top - case bottom - case left - case right - case topLeft - case topRight - case bottomLeft - case bottomRight - } + public var contentMode: UIView.ContentMode? public init(image: String) { self.image = image diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index d46a5150..5e8cedc8 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -232,54 +232,10 @@ import UIKit imageView.animatedImage = nil loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage) } - setContentMode(imageModel) - } - func setContentMode(_ model: ImageViewModel?) { - switch model?.contentMode { - case .scaleToFill: - imageView.contentMode = .scaleToFill - break - case .scaleAspectFit: - imageView.contentMode = .scaleAspectFit - break - case .scaleAspectFill: - imageView.contentMode = .scaleAspectFill - break - case .redraw: - imageView.contentMode = .redraw - break - case .center: - imageView.contentMode = .center - break - case .top: - imageView.contentMode = .top - break - case .bottom: - imageView.contentMode = .bottom - break - case .left: - imageView.contentMode = .left - break - case .right: - imageView.contentMode = .right - break - case .topLeft: - imageView.contentMode = .topLeft - break - case .topRight: - imageView.contentMode = .topRight - break - case .bottomLeft: - imageView.contentMode = .bottomLeft - break - case .bottomRight: - imageView.contentMode = .bottomRight - break - default: - break + if let contentMode = imageModel.contentMode { + imageView.contentMode = contentMode } - } // MARK: - MVMCoreUIMoleculeViewProtocol functions diff --git a/MVMCoreUI/Categories/UIContentMode+Extension.swift b/MVMCoreUI/Categories/UIContentMode+Extension.swift new file mode 100644 index 00000000..19cf523b --- /dev/null +++ b/MVMCoreUI/Categories/UIContentMode+Extension.swift @@ -0,0 +1,98 @@ +// +// UIContentMode+Extension.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/17/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +enum ContentModeError: Error { + case notAContentMode +} + +extension UIView.ContentMode: RawRepresentable { + + init?(rawValue: String) { + switch rawValue { + case "scaleToFill": + self = .scaleToFill + case "scaleAspectFit": + self = .scaleAspectFit + case "scaleAspectFill": + self = .scaleAspectFill + case "redraw": + self = .redraw + case "center": + self = .center + case "top": + self = .top + case "bottom": + self = .bottom + case "left": + self = .left + case "right": + self = .right + case "topLeft": + self = .topLeft + case "topRight": + self = .topRight + case "bottomLeft": + self = .bottomLeft + case "bottomRight": + self = .bottomRight + default: + return nil + } + } + + var rawValueString: String { + switch self { + case .scaleToFill: + return "scaleToFill" + case .scaleAspectFit: + return "scaleAspectFit" + case .scaleAspectFill: + return "scaleAspectFill" + case .redraw: + return "redraw" + case .center: + return "center" + case .top: + return "top" + case .bottom: + return "bottom" + case .left: + return "left" + case .right: + return "right" + case .topLeft: + return "topLeft" + case .topRight: + return "topRight" + case .bottomLeft: + return "bottomLeft" + case .bottomRight: + return "bottomRight" + @unknown default: + return "" + } + } +} + +extension UIView.ContentMode: Codable { + public init(from decoder: Decoder) throws { + let typeContainer = try decoder.singleValueContainer() + let string = try typeContainer.decode(String.self) + guard let mode = UIView.ContentMode(rawValue: string) else { + throw ContentModeError.notAContentMode + } + self = mode + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(rawValueString) + } +} diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 4ddb1575..5d608003 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -21,7 +21,10 @@ public class TwoButtonViewModel: MoleculeModelProtocol { case secondaryButton } - init() { } + init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { + self.primaryButton = primaryButton + self.secondaryButton = secondaryButton + } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) From 3e14e395421d48ade87845b8d32842dd22e8684d Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 17:37:46 -0500 Subject: [PATCH 34/96] public --- .../HorizontalCombinationViews/TwoButtonViewModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 5d608003..057203e9 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -21,7 +21,7 @@ public class TwoButtonViewModel: MoleculeModelProtocol { case secondaryButton } - init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { + public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { self.primaryButton = primaryButton self.secondaryButton = secondaryButton } From 9211d6c86d7c771d1f79453b147d264ca0d3d98e Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 17:44:12 -0500 Subject: [PATCH 35/96] public --- MVMCoreUI/CustomPrimitives/Color.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/CustomPrimitives/Color.swift b/MVMCoreUI/CustomPrimitives/Color.swift index a34fbd45..165fa8ad 100644 --- a/MVMCoreUI/CustomPrimitives/Color.swift +++ b/MVMCoreUI/CustomPrimitives/Color.swift @@ -49,7 +49,7 @@ public final class Color: Codable { // MARK: - Class Initializers //-------------------------------------------------- - init(uiColor: UIColor) { + public init(uiColor: UIColor) { self.uiColor = uiColor hex = UIColor.hexString(for: uiColor) ?? "" determineRGBA() From d8acbec04615cb80f00d8215420f44630336e09f Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 19:07:23 -0500 Subject: [PATCH 36/96] fixes --- .../MFViewController+Model.swift | 4 - MVMCoreUI/BaseControllers/MFViewController.h | 1 + MVMCoreUI/BaseControllers/MFViewController.m | 4 + .../TwoButtonViewModel.swift | 4 +- .../OtherHandlers/IsaacLandingTemplate.swift | 212 ++++++++++++++++++ .../Templates/IsaacLandingTemplate.swift | 192 ++++++++++++++++ .../Templates/MoleculeListTemplate.swift | 4 +- .../Templates/MoleculeStackTemplate.swift | 4 +- MVMCoreUI/Templates/ThreeLayerTemplate.swift | 5 +- 9 files changed, 418 insertions(+), 12 deletions(-) create mode 100644 MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift create mode 100644 MVMCoreUI/Templates/IsaacLandingTemplate.swift diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/BaseControllers/MFViewController+Model.swift index 1ddbd4ab..e70e68f6 100644 --- a/MVMCoreUI/BaseControllers/MFViewController+Model.swift +++ b/MVMCoreUI/BaseControllers/MFViewController+Model.swift @@ -37,7 +37,3 @@ extension MFViewController: MoleculeDelegateProtocol { @objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { } } - -public extension MFViewController { - @objc func parsePageJSON() throws { } -} diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/BaseControllers/MFViewController.h index cd96a07f..ee38cf2b 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.h +++ b/MVMCoreUI/BaseControllers/MFViewController.h @@ -277,6 +277,7 @@ // subclass to set up intro animations - (void)setupIntroAnimations; +- (void)parsePageJSONAndReturnError:(NSError * _Nullable * _Nullable)error; @end diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 09700268..af2db33c 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -112,6 +112,10 @@ return [MFViewController verifyRequiredModulesLoadedForLoadObject:loadObject error:error]; } +- (void)parsePageJSONAndReturnError:(NSError * _Nullable * _Nullable)error { + +} + // Sets the screen to use the screen heading. // it is required in device flow, where we are showing greeting name as screen heading, // device details screen heading needs to be updated/refreshed again, if user has changed device nick name diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 057203e9..d4cba24c 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -22,8 +22,8 @@ public class TwoButtonViewModel: MoleculeModelProtocol { } public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { - self.primaryButton = primaryButton - self.secondaryButton = secondaryButton + self.primaryButton = primaryButton + self.secondaryButton = secondaryButton } required public init(from decoder: Decoder) throws { diff --git a/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift b/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift new file mode 100644 index 00000000..154cfdfd --- /dev/null +++ b/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift @@ -0,0 +1,212 @@ +// +// IsaacLandingTemplate.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +import MVMCoreUI +import MVMCore + +open class IsaacLandingTemplate: MoleculeListTemplate { + + open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + guard let pageJSON = self.loadObject?.pageJSON else { return } + + var listItems: [MoleculeListItemModel] = [] + (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in + if let item = getListItem(itemJson) { + listItems.append(item) + } + } + + let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), + screenHeading: pageJSON.stringForkey(KeyScreenHeading), + molecules: listItems) + + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + template.footer = setFooter(pageJSON, template) + self.templateModel = template + + DispatchQueue.main.async { [weak self] in + self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) + } + } +// public func parseTemplateJSON() throws { +// guard let pageJSON = self.loadObject?.pageJSON else { return } +// +// var listItems: [MoleculeListItemModel] = [] +// (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in +// if let item = getListItem(itemJson) { +// listItems.append(item) +// } +// } +// +// let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), +// screenHeading: pageJSON.stringForkey(KeyScreenHeading), +// molecules: listItems) +// +// let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" +// template.footer = setFooter(pageJSON, template) +// self.templateModel = template +// +// DispatchQueue.main.async { [weak self] in +// self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) +// } +// } + + func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { + + let primaryButtonBGColor = pageJSON.optionalStringForKey("primaryButtonBGColor") ?? "#FFFFFF" + let primaryButtonTextColor = pageJSON.optionalStringForKey("primaryButtonTextColor") ?? "#000000" + + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + if let buttonMap = pageJSON.optionalDictionaryForKey("ButtonMap") { + let twoButtonModel = TwoButtonViewModel(nil, nil) + + if let primarybutton = buttonMap.optionalDictionaryForKey(KeyPrimaryButton) { + let buttonDict: [String : Any] = ["title": primarybutton.stringForkey(KeyTitle), + "action": primarybutton, + "moleculeName": "button"] + if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { + let decoder = JSONDecoder() + twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) + twoButtonModel.primaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) + twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + } + } + if let secondaryButton = buttonMap.optionalDictionaryForKey(KeySecondaryButton) { + let buttonDict: [String : Any] = ["title": secondaryButton.stringForkey(KeyTitle), + "action": secondaryButton, + "moleculeName": "button"] + if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { + let decoder = JSONDecoder() + twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) + twoButtonModel.secondaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) + } + } + + let footerStack = MoleculeStackModel(molecules: [MoleculeStackItemModel(with:LineModel(type: .standard)), + MoleculeStackItemModel(with: twoButtonModel)]) + footerStack.useHorizontalMargins = false + footerStack.spacing = PaddingFour + + let footer = FooterModel(with: footerStack) + footer.useHorizontalMargins = false + footer.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + return footer + } + return nil + } + + func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { + guard let type = moleculeJson.optionalStringForKey("type") else { + return nil + } + + if type == "rewards" { + return getRewardListItem(moleculeJson) + } else { + return getTitleImageListItem(moleculeJson, type) + } + } + + func getTitleImageListItem(_ moleculeJson: [AnyHashable: Any], _ type: String) -> MoleculeListItemModel? { + let textcolor = moleculeJson.optionalStringForKey("textColor") + var stackItems: [MoleculeStackItemModel] = [] + + let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 + + let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) + messageLabel.fontStyle = "B2" + messageLabel.textColor = textcolor + + let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) + headlineBodyModel.body = messageLabel + + if let linkMap = moleculeJson.optionalDictionaryForKey("link") { + do { + let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), + "action": linkMap] + let data = try JSONSerialization.data(withJSONObject: linkDict) + let decoder = JSONDecoder() + let linkModel = try decoder.decode(LinkModel.self, from: data) + linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) + let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, + link: linkModel) + stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) + } catch { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + } else { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + + if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { + let imageModel = ImageViewModel(image: imageurl) + imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 + imageModel.imageFormat = "jpeg" + imageModel.contentMode = .scaleAspectFit + stackItems.append(MoleculeStackItemModel(with: imageModel)) + } + + let stack = MoleculeStackModel(molecules: stackItems) + let listItem = MoleculeListItemModel(with: stack) + + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + return listItem + } + + func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { + + var stackItems: [MoleculeStackItemModel] = [] + + (moleculeJson.arrayForKey("rewards") as? [[AnyHashable: Any]])?.forEach { (rewardItem) in + let textcolor = rewardItem.optionalStringForKey("textColor") + + let titleLabel = LabelModel(text: rewardItem.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = 48 + + let messageLabel = LabelModel(text: rewardItem.stringForkey("message")) + messageLabel.fontName = "NHaasGroteskDSStd-75Bd" + messageLabel.textColor = textcolor + messageLabel.fontSize = 14 + + let titleStackItem = MoleculeStackItemModel(with: titleLabel) + let messageStackItem = MoleculeStackItemModel(with: messageLabel) + + let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) + itemStack.verticalAlignment = .top + itemStack.spacing = 0 + + let horizontalStack = MoleculeStackItemModel(with: itemStack) + horizontalStack.verticalAlignment = .top + stackItems.append(horizontalStack) + } + + stackItems.first?.percent = 35 + stackItems.last?.percent = 65 + let stack = MoleculeStackModel(molecules: stackItems) + stack.axis = .horizontal + stack.horizontalAlignment = .leading + stack.verticalAlignment = .leading + + let listItem = MoleculeListItemModel(with: stack) + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + + return listItem + } +} + diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift new file mode 100644 index 00000000..909c9600 --- /dev/null +++ b/MVMCoreUI/Templates/IsaacLandingTemplate.swift @@ -0,0 +1,192 @@ + +// IsaacLandingTemplate.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +import MVMCoreUI +import MVMCore + +open class IsaacLandingTemplate: MoleculeListTemplate { + + open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + guard let pageJSON = self.loadObject?.pageJSON else { return } + + var listItems: [MoleculeListItemModel] = [] + (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in + if let item = getListItem(itemJson) { + listItems.append(item) + } + } + + let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), + screenHeading: pageJSON.stringForkey(KeyScreenHeading), + molecules: listItems) + + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + template.footer = setFooter(pageJSON, template) + self.templateModel = template + + DispatchQueue.main.async { [weak self] in + self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) + } + } + + + func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { + + let primaryButtonBGColor = pageJSON.optionalStringForKey("primaryButtonBGColor") ?? "#FFFFFF" + let primaryButtonTextColor = pageJSON.optionalStringForKey("primaryButtonTextColor") ?? "#000000" + + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + if let buttonMap = pageJSON.optionalDictionaryForKey("ButtonMap") { + let twoButtonModel = TwoButtonViewModel(nil, nil) + + if let primarybutton = buttonMap.optionalDictionaryForKey(KeyPrimaryButton) { + let buttonDict: [String : Any] = ["title": primarybutton.stringForkey(KeyTitle), + "action": primarybutton, + "moleculeName": "button"] + if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { + let decoder = JSONDecoder() + twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) + twoButtonModel.primaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) + twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + } + } + if let secondaryButton = buttonMap.optionalDictionaryForKey(KeySecondaryButton) { + let buttonDict: [String : Any] = ["title": secondaryButton.stringForkey(KeyTitle), + "action": secondaryButton, + "moleculeName": "button"] + if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { + let decoder = JSONDecoder() + twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) + twoButtonModel.secondaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) + twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) + } + } + + let footerStack = MoleculeStackModel(molecules: [MoleculeStackItemModel(with:LineModel(type: .standard)), + MoleculeStackItemModel(with: twoButtonModel)]) + footerStack.useHorizontalMargins = false + footerStack.spacing = PaddingFour + + let footer = FooterModel(with: footerStack) + footer.useHorizontalMargins = false + footer.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + return footer + } + return nil + } + + func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { + guard let type = moleculeJson.optionalStringForKey("type") else { + return nil + } + + if type == "rewards" { + return getRewardListItem(moleculeJson) + } else { + return getTitleImageListItem(moleculeJson, type) + } + } + + func getTitleImageListItem(_ moleculeJson: [AnyHashable: Any], _ type: String) -> MoleculeListItemModel? { + let textcolor = moleculeJson.optionalStringForKey("textColor") + var stackItems: [MoleculeStackItemModel] = [] + + let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 + + let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) + messageLabel.fontStyle = "B2" + messageLabel.textColor = textcolor + + let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) + headlineBodyModel.body = messageLabel + + if let linkMap = moleculeJson.optionalDictionaryForKey("link") { + do { + let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), + "action": linkMap] + let data = try JSONSerialization.data(withJSONObject: linkDict) + let decoder = JSONDecoder() + let linkModel = try decoder.decode(LinkModel.self, from: data) + linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) + let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, + link: linkModel) + stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) + } catch { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + } else { + stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) + } + + if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { + let imageModel = ImageViewModel(image: imageurl) + imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 + imageModel.imageFormat = "jpeg" + imageModel.contentMode = .scaleAspectFit + stackItems.append(MoleculeStackItemModel(with: imageModel)) + } + + let stack = MoleculeStackModel(molecules: stackItems) + let listItem = MoleculeListItemModel(with: stack) + + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + return listItem + } + + func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { + + var stackItems: [MoleculeStackItemModel] = [] + + (moleculeJson.arrayForKey("rewards") as? [[AnyHashable: Any]])?.forEach { (rewardItem) in + let textcolor = rewardItem.optionalStringForKey("textColor") + + let titleLabel = LabelModel(text: rewardItem.stringForkey(KeyTitle)) + titleLabel.fontName = "NHaasGroteskDSStd-75Bd" + titleLabel.textColor = textcolor + titleLabel.fontSize = 48 + + let messageLabel = LabelModel(text: rewardItem.stringForkey("message")) + messageLabel.fontName = "NHaasGroteskDSStd-75Bd" + messageLabel.textColor = textcolor + messageLabel.fontSize = 14 + + let titleStackItem = MoleculeStackItemModel(with: titleLabel) + let messageStackItem = MoleculeStackItemModel(with: messageLabel) + + let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) + itemStack.verticalAlignment = .top + itemStack.spacing = 0 + + let horizontalStack = MoleculeStackItemModel(with: itemStack) + horizontalStack.verticalAlignment = .top + stackItems.append(horizontalStack) + } + + stackItems.first?.percent = 35 + stackItems.last?.percent = 65 + let stack = MoleculeStackModel(molecules: stackItems) + stack.axis = .horizontal + stack.horizontalAlignment = .leading + stack.verticalAlignment = .leading + + let listItem = MoleculeListItemModel(with: stack) + let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" + listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) + listItem.line = LineModel(type: .none) + + return listItem + } +} + + diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 01d0a5e6..291a6a27 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -23,8 +23,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Computed Properties //-------------------------------------------------- - @objc public override func parsePageJSON() throws { - try parseTemplateJSON() + open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + try? parseTemplateJSON() } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 03d21c6b..b3fb4c3a 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -12,8 +12,8 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? - public override func parsePageJSON() throws { - try parseTemplateJSON() + open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + try? parseTemplateJSON() } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 785d1055..8d4f7169 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -11,8 +11,9 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { public var templateModel: ThreeLayerPageTemplateModel? - @objc public override func parsePageJSON() throws { - try parseTemplateJSON() + + open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + try? parseTemplateJSON() } override open func viewDidLoad() { From a2700e81b4e612d0c5012ad6fb1c5d33d5788147 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 21:54:47 -0500 Subject: [PATCH 37/96] remove file --- .../OtherHandlers/IsaacLandingTemplate.swift | 52 ++--- .../Templates/IsaacLandingTemplate.swift | 192 ------------------ 2 files changed, 15 insertions(+), 229 deletions(-) delete mode 100644 MVMCoreUI/Templates/IsaacLandingTemplate.swift diff --git a/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift b/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift index 154cfdfd..8068cdc4 100644 --- a/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift +++ b/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift @@ -15,47 +15,25 @@ open class IsaacLandingTemplate: MoleculeListTemplate { open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { guard let pageJSON = self.loadObject?.pageJSON else { return } - var listItems: [MoleculeListItemModel] = [] - (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in - if let item = getListItem(itemJson) { - listItems.append(item) - } - } + var listItems: [MoleculeListItemModel] = [] + (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in + if let item = getListItem(itemJson) { + listItems.append(item) + } + } - let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), - screenHeading: pageJSON.stringForkey(KeyScreenHeading), - molecules: listItems) + let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), + screenHeading: pageJSON.stringForkey(KeyScreenHeading), + molecules: listItems) - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - template.footer = setFooter(pageJSON, template) - self.templateModel = template + let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" + template.footer = setFooter(pageJSON, template) + self.templateModel = template - DispatchQueue.main.async { [weak self] in - self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) - } + DispatchQueue.main.async { [weak self] in + self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) + } } -// public func parseTemplateJSON() throws { -// guard let pageJSON = self.loadObject?.pageJSON else { return } -// -// var listItems: [MoleculeListItemModel] = [] -// (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in -// if let item = getListItem(itemJson) { -// listItems.append(item) -// } -// } -// -// let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), -// screenHeading: pageJSON.stringForkey(KeyScreenHeading), -// molecules: listItems) -// -// let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" -// template.footer = setFooter(pageJSON, template) -// self.templateModel = template -// -// DispatchQueue.main.async { [weak self] in -// self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) -// } -// } func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { diff --git a/MVMCoreUI/Templates/IsaacLandingTemplate.swift b/MVMCoreUI/Templates/IsaacLandingTemplate.swift deleted file mode 100644 index 909c9600..00000000 --- a/MVMCoreUI/Templates/IsaacLandingTemplate.swift +++ /dev/null @@ -1,192 +0,0 @@ - -// IsaacLandingTemplate.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 2/13/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation -import MVMCoreUI -import MVMCore - -open class IsaacLandingTemplate: MoleculeListTemplate { - - open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { - guard let pageJSON = self.loadObject?.pageJSON else { return } - - var listItems: [MoleculeListItemModel] = [] - (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in - if let item = getListItem(itemJson) { - listItems.append(item) - } - } - - let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), - screenHeading: pageJSON.stringForkey(KeyScreenHeading), - molecules: listItems) - - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - template.footer = setFooter(pageJSON, template) - self.templateModel = template - - DispatchQueue.main.async { [weak self] in - self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) - } - } - - - func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { - - let primaryButtonBGColor = pageJSON.optionalStringForKey("primaryButtonBGColor") ?? "#FFFFFF" - let primaryButtonTextColor = pageJSON.optionalStringForKey("primaryButtonTextColor") ?? "#000000" - - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - if let buttonMap = pageJSON.optionalDictionaryForKey("ButtonMap") { - let twoButtonModel = TwoButtonViewModel(nil, nil) - - if let primarybutton = buttonMap.optionalDictionaryForKey(KeyPrimaryButton) { - let buttonDict: [String : Any] = ["title": primarybutton.stringForkey(KeyTitle), - "action": primarybutton, - "moleculeName": "button"] - if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { - let decoder = JSONDecoder() - twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.primaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) - twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) - } - } - if let secondaryButton = buttonMap.optionalDictionaryForKey(KeySecondaryButton) { - let buttonDict: [String : Any] = ["title": secondaryButton.stringForkey(KeyTitle), - "action": secondaryButton, - "moleculeName": "button"] - if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { - let decoder = JSONDecoder() - twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.secondaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) - twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) - } - } - - let footerStack = MoleculeStackModel(molecules: [MoleculeStackItemModel(with:LineModel(type: .standard)), - MoleculeStackItemModel(with: twoButtonModel)]) - footerStack.useHorizontalMargins = false - footerStack.spacing = PaddingFour - - let footer = FooterModel(with: footerStack) - footer.useHorizontalMargins = false - footer.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - return footer - } - return nil - } - - func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - guard let type = moleculeJson.optionalStringForKey("type") else { - return nil - } - - if type == "rewards" { - return getRewardListItem(moleculeJson) - } else { - return getTitleImageListItem(moleculeJson, type) - } - } - - func getTitleImageListItem(_ moleculeJson: [AnyHashable: Any], _ type: String) -> MoleculeListItemModel? { - let textcolor = moleculeJson.optionalStringForKey("textColor") - var stackItems: [MoleculeStackItemModel] = [] - - let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 - - let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) - messageLabel.fontStyle = "B2" - messageLabel.textColor = textcolor - - let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) - headlineBodyModel.body = messageLabel - - if let linkMap = moleculeJson.optionalDictionaryForKey("link") { - do { - let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), - "action": linkMap] - let data = try JSONSerialization.data(withJSONObject: linkDict) - let decoder = JSONDecoder() - let linkModel = try decoder.decode(LinkModel.self, from: data) - linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) - let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, - link: linkModel) - stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) - } catch { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) - } - } else { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) - } - - if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { - let imageModel = ImageViewModel(image: imageurl) - imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 - imageModel.imageFormat = "jpeg" - imageModel.contentMode = .scaleAspectFit - stackItems.append(MoleculeStackItemModel(with: imageModel)) - } - - let stack = MoleculeStackModel(molecules: stackItems) - let listItem = MoleculeListItemModel(with: stack) - - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - return listItem - } - - func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - - var stackItems: [MoleculeStackItemModel] = [] - - (moleculeJson.arrayForKey("rewards") as? [[AnyHashable: Any]])?.forEach { (rewardItem) in - let textcolor = rewardItem.optionalStringForKey("textColor") - - let titleLabel = LabelModel(text: rewardItem.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = 48 - - let messageLabel = LabelModel(text: rewardItem.stringForkey("message")) - messageLabel.fontName = "NHaasGroteskDSStd-75Bd" - messageLabel.textColor = textcolor - messageLabel.fontSize = 14 - - let titleStackItem = MoleculeStackItemModel(with: titleLabel) - let messageStackItem = MoleculeStackItemModel(with: messageLabel) - - let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) - itemStack.verticalAlignment = .top - itemStack.spacing = 0 - - let horizontalStack = MoleculeStackItemModel(with: itemStack) - horizontalStack.verticalAlignment = .top - stackItems.append(horizontalStack) - } - - stackItems.first?.percent = 35 - stackItems.last?.percent = 65 - let stack = MoleculeStackModel(molecules: stackItems) - stack.axis = .horizontal - stack.horizontalAlignment = .leading - stack.verticalAlignment = .leading - - let listItem = MoleculeListItemModel(with: stack) - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - - return listItem - } -} - - From e2860efaf6d6ab41789bbd209f4f24bccdb44eb4 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 Feb 2020 22:28:09 -0500 Subject: [PATCH 38/96] fixes --- MVMCoreUI/BaseControllers/MFViewController.h | 2 +- MVMCoreUI/BaseControllers/MFViewController.m | 6 +++--- MVMCoreUI/Templates/MoleculeListTemplate.swift | 2 +- MVMCoreUI/Templates/MoleculeStackTemplate.swift | 2 +- MVMCoreUI/Templates/ThreeLayerTemplate.swift | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/BaseControllers/MFViewController.h index ee38cf2b..11afe915 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.h +++ b/MVMCoreUI/BaseControllers/MFViewController.h @@ -277,7 +277,7 @@ // subclass to set up intro animations - (void)setupIntroAnimations; -- (void)parsePageJSONAndReturnError:(NSError * _Nullable * _Nullable)error; +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error; @end diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index af2db33c..f663193f 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -98,7 +98,7 @@ self.loadObject = loadObject; NSError *parseError = nil; - [self parsePageJSONAndReturnError:&parseError]; + [self parsePageJSON:&parseError]; if (parseError) { if (error) { MVMCoreErrorObject *errorObject = [MVMCoreErrorObject createErrorObjectForNSError:parseError location:[[MVMCoreLoadHandler sharedGlobal] errorLocationForRequest:loadObject]]; @@ -112,7 +112,7 @@ return [MFViewController verifyRequiredModulesLoadedForLoadObject:loadObject error:error]; } -- (void)parsePageJSONAndReturnError:(NSError * _Nullable * _Nullable)error { +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error { } @@ -265,7 +265,7 @@ - (BOOL)newPageLoaded:(nonnull NSDictionary *)page { self.loadObject.pageJSON = page; NSError *parseError = nil; - [self parsePageJSONAndReturnError:&parseError]; + [self parsePageJSON:&parseError]; return YES; } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 291a6a27..cbe0458c 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -23,7 +23,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Computed Properties //-------------------------------------------------- - open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + open override func parsePageJSON(_ error: NSErrorPointer) { try? parseTemplateJSON() } diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index b3fb4c3a..8bf0b4cd 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -12,7 +12,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? - open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + open override func parsePageJSON(_ error: NSErrorPointer) { try? parseTemplateJSON() } diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 8d4f7169..72498289 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -12,7 +12,7 @@ import UIKit public var templateModel: ThreeLayerPageTemplateModel? - open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { + open override func parsePageJSON(_ error: NSErrorPointer) { try? parseTemplateJSON() } From c43a3da712da4eeeed48e77f4c2547f722b6a459 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Tue, 18 Feb 2020 16:06:30 +0530 Subject: [PATCH 39/96] Code commit after adding a createPayPal function. --- .../List/RightVariable/ListRightVariablePayments.swift | 3 +-- .../List/RightVariable/ListRightVariablePaymentsModel.swift | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 91703fd7..046bc331 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -36,7 +36,6 @@ import Foundation stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] contentView.addSubview(stack) containerHelper.constrainView(stack) - } //---------------------------------------------------- // MARK: - Molecule @@ -45,7 +44,7 @@ import Foundation super.reset() stack.reset() } -   + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListRightVariablePaymentsModel else { return} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 422cd193..681f2078 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -20,7 +20,7 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco super.init() } - func createPayPalImage() -> ImageViewModel { + static func createPayPalImage() -> ImageViewModel { let image = ImageViewModel(image: "imagename_paypal") image.width = 30.0 return image @@ -35,7 +35,7 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) - image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) ?? createPayPalImage() + image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) ?? ListRightVariablePaymentsModel.createPayPalImage() try super.init(from: decoder) } From 72d0a24061f02ee27403f852d883c867823ba35e Mon Sep 17 00:00:00 2001 From: Lekshmi S Date: Tue, 18 Feb 2020 16:50:03 +0530 Subject: [PATCH 40/96] Modified code as image is optional. --- .../List/RightVariable/ListRightVariablePaymentsModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 681f2078..63719ec1 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -11,7 +11,7 @@ import Foundation public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listRVImg" - public var image: ImageViewModel + public var image: ImageViewModel? public var leftLabel: LabelModel public init(image: ImageViewModel, leftLabel: LabelModel) { @@ -44,6 +44,6 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) - try container.encode(image, forKey: .image) + try container.encodeIfPresent(image, forKey: .image) } } From a7ebc798d2227bcc328265734dc4d9af871fd35c Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Tue, 18 Feb 2020 19:01:08 +0530 Subject: [PATCH 41/96] Removing hardcoded constraints replacing with multiplier --- .../ListRVWheel.swift | 36 ++++++++----------- .../ListRVWheelModel.swift | 3 +- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift index a4f18df6..485a5464 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift @@ -12,11 +12,6 @@ import Foundation let wheel = GraphView(frame: .zero) let leftLabel = Label(frame: .zero) let rightLabel = Label(frame: .zero) - let leftLabelWidthConstant : CGFloat = 151.0 - let rightLabelWidthConstant : CGFloat = 84.0 - let wheelTrailingConstant : CGFloat = -72.0 - let rightLabelLeadingAnchorConstant : CGFloat = 8.0 - //------------------------------------------------- // MARK: - View Cycle //------------------------------------------------- @@ -41,33 +36,31 @@ import Foundation NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) contentView.translatesAutoresizingMaskIntoConstraints = false - //------------------------------------------------- - // MARK: - Constraining - //------------------------------------------------- + //------------------------------------------------- + // MARK: - Constraining + //------------------------------------------------- self.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ leftLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), leftLabel.topAnchor.constraint(equalTo: contentView.topAnchor), leftLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - leftLabel.widthAnchor.constraint(lessThanOrEqualToConstant: leftLabelWidthConstant) - ]) - - let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) - rightLabelTrailing.priority = .defaultHigh - NSLayoutConstraint.activate([ - rightLabelTrailing, - rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo : wheel.trailingAnchor, constant: rightLabelLeadingAnchorConstant), - rightLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - rightLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - rightLabel.widthAnchor.constraint(lessThanOrEqualToConstant: rightLabelWidthConstant) + leftLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.3) ]) NSLayoutConstraint.activate([ - wheel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant:wheelTrailingConstant), wheel.topAnchor.constraint(equalTo: contentView.topAnchor), wheel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) + + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) + rightLabelTrailing.priority = UILayoutPriority(900) + NSLayoutConstraint.activate([ + rightLabelTrailing, + rightLabel.leadingAnchor.constraint(equalTo: wheel.trailingAnchor), + rightLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.30), + rightLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + rightLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) } - //------------------------------------------------- // MARK: - MVMCoreUIMoleculeViewProtocol //------------------------------------------------- @@ -88,7 +81,6 @@ import Foundation rightLabel.reset() wheel.reset() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 43 } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift index 5d8a041a..9b8a95f4 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift @@ -7,7 +7,8 @@ // import Foundation -public class ListRVWheelModel:ListItemModelProtocol { +public class ListRVWheelModel:ListItemModelProtocol,MoleculeModelProtocol { + public var backgroundColor: Color? public var line: LineModel? public var hideArrow: Bool? From c97c3fe7341ff3aa25acb3dbf5d2524711d83d6f Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Tue, 18 Feb 2020 19:22:17 +0530 Subject: [PATCH 42/96] Code changes and cleaning --- .../VerticalCombinationViews/ListRVWheel.swift | 4 ++-- .../VerticalCombinationViews/ListRVWheelModel.swift | 12 +----------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift index 485a5464..47c77ed8 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift @@ -51,12 +51,12 @@ import Foundation wheel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) - let rightLabelTrailing = rightLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) + let rightLabelTrailing = rightLabel.trailingAnchor.constraint(greaterThanOrEqualTo: contentView.trailingAnchor) rightLabelTrailing.priority = UILayoutPriority(900) NSLayoutConstraint.activate([ rightLabelTrailing, rightLabel.leadingAnchor.constraint(equalTo: wheel.trailingAnchor), - rightLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.30), + rightLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.32), rightLabel.topAnchor.constraint(equalTo: contentView.topAnchor), rightLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift index 9b8a95f4..a4c5f028 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift @@ -7,18 +7,8 @@ // import Foundation -public class ListRVWheelModel:ListItemModelProtocol,MoleculeModelProtocol { - +public class ListRVWheelModel:MoleculeModelProtocol { public var backgroundColor: Color? - public var line: LineModel? - public var hideArrow: Bool? - public var horizontalAlignment: UIStackView.Alignment? - public var verticalAlignment: UIStackView.Alignment? - public var useHorizontalMargins: Bool? - public var useVerticalMargins: Bool? - public var topMarginPadding: CGFloat? - public var bottomMarginPadding: CGFloat? - public static var identifier: String = "listRVWheel" public var leftLabel: LabelModel? public var rightLabel: LabelModel? From a29b4b17a0d6b2769fd0238a21e679a084b36007 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Tue, 18 Feb 2020 09:48:58 -0500 Subject: [PATCH 43/96] add toggle for server s7 params --- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 5e8cedc8..fa7d369e 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -273,7 +273,9 @@ import UIKit } // MARK: - load functions - public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { + public func loadImage(withName imageName: String?, format: String? = nil, width: NSNumber? = nil, height: NSNumber? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, completionHandler: MVMCoreGetImageBlock? = nil) { + + let completionBlock = completionHandler ?? defaultCompletionBlock() MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in self.currentImageName = imageName self.currentImageWidth = width?.cgfloat() @@ -295,15 +297,15 @@ import UIKit if layoutWillChange { self?.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self!) } - completionHandler(image,data,isFallbackImage) + completionBlock(image,data,isFallbackImage) })} 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, 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, 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, completionHandler: finishedLoadingBlock) + MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, completionHandler: finishedLoadingBlock) } }) } @@ -333,6 +335,8 @@ import UIKit }) } + // Note: Exposed for objective-c interfaces. + public func loadImage(withName imageName: String?) { loadImage(withName: imageName, format: nil, width: nil, height: nil, customFallbackImage: nil, completionHandler: defaultCompletionBlock()) } @@ -368,4 +372,8 @@ import UIKit public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) { loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock()) } + + public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { + loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, allowServerParameters: false, completionHandler: completionHandler) + } } From ff0758106ef6cde410c7f5d104acd5e2331e9d95 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 18 Feb 2020 12:31:55 -0500 Subject: [PATCH 44/96] init --- .../Atoms/Views/Label/LabelAttributeActionModel.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift index 2ebcb4b4..135fee45 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift @@ -8,12 +8,17 @@ import UIKit -class LabelAttributeActionModel: LabelAttributeModel { +open class LabelAttributeActionModel: LabelAttributeModel { override public class var identifier: String { return "action" } var action: ActionModelProtocol + public init(_ location: Int, _ length: Int, action: ActionModelProtocol) { + self.action = action + super.init(Self.identifier, location, length) + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) From db8a27ec2fc44bffa209d66bf699d5c31d1b1d6a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 18 Feb 2020 14:29:35 -0500 Subject: [PATCH 45/96] update to label attributes --- .../Atoms/Views/Label/LabelAttributeActionModel.swift | 10 +++++----- MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift index 135fee45..503f00d8 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift @@ -16,7 +16,11 @@ open class LabelAttributeActionModel: LabelAttributeModel { public init(_ location: Int, _ length: Int, action: ActionModelProtocol) { self.action = action - super.init(Self.identifier, location, length) + super.init(location, length) + } + + private enum CodingKeys: String, CodingKey { + case action } required public init(from decoder: Decoder) throws { @@ -30,8 +34,4 @@ open class LabelAttributeActionModel: LabelAttributeModel { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeModel(action, forKey: .action) } - - private enum CodingKeys: String, CodingKey { - case action - } } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift index 3c073b2f..437ec0cc 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift @@ -25,12 +25,14 @@ import Foundation return "" } - var type: String + var type: String { + get { return Self.identifier } + } + var location: Int var length: Int - init(_ type: String, _ location: Int, _ length: Int) { - self.type = type + init(_ location: Int, _ length: Int) { self.location = location self.length = length } @@ -51,7 +53,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - type = try typeContainer.decode(String.self, forKey: .type) location = try typeContainer.decode(Int.self, forKey: .location) length = try typeContainer.decode(Int.self, forKey: .length) } From a620dd2401d3e03cabf646271972ec71cf44f6f0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 18 Feb 2020 14:59:17 -0500 Subject: [PATCH 46/96] some fixes for catching and remove file --- MVMCoreUI/BaseControllers/MFViewController.h | 4 +- .../TwoButtonViewModel.swift | 4 +- .../OtherHandlers/IsaacLandingTemplate.swift | 190 ------------------ .../Templates/MoleculeListTemplate.swift | 6 +- .../Templates/MoleculeStackTemplate.swift | 6 +- MVMCoreUI/Templates/ThreeLayerTemplate.swift | 6 +- 6 files changed, 20 insertions(+), 196 deletions(-) delete mode 100644 MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/BaseControllers/MFViewController.h index 11afe915..38ced354 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.h +++ b/MVMCoreUI/BaseControllers/MFViewController.h @@ -96,6 +96,9 @@ // This view controller should subclass this function and check the load to make sure it has all the needed data. Fills the error object if there are any errors. Returns if we should finish the load or not. - (BOOL)shouldFinishProcessingLoad:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error; +/// Called in newDataBuildScreen. Can override to parse the json into a model object. +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error; + // Sets the screen to use the screen heading. // it is required in device flow, where we are showing greeting name as screen heading, // device details screen heading needs to be updated/refreshed again, if user has changed device nick name @@ -277,7 +280,6 @@ // subclass to set up intro animations - (void)setupIntroAnimations; -- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error; @end diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index d4cba24c..057203e9 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -22,8 +22,8 @@ public class TwoButtonViewModel: MoleculeModelProtocol { } public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { - self.primaryButton = primaryButton - self.secondaryButton = secondaryButton + self.primaryButton = primaryButton + self.secondaryButton = secondaryButton } required public init(from decoder: Decoder) throws { diff --git a/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift b/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift deleted file mode 100644 index 8068cdc4..00000000 --- a/MVMCoreUI/OtherHandlers/IsaacLandingTemplate.swift +++ /dev/null @@ -1,190 +0,0 @@ -// -// IsaacLandingTemplate.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 2/13/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation -import MVMCoreUI -import MVMCore - -open class IsaacLandingTemplate: MoleculeListTemplate { - - open override func parsePageJSONAndReturnError(_ error: NSErrorPointer) { - guard let pageJSON = self.loadObject?.pageJSON else { return } - - var listItems: [MoleculeListItemModel] = [] - (pageJSON.arrayForKey("items") as? [[AnyHashable: Any]])?.forEach { (itemJson) in - if let item = getListItem(itemJson) { - listItems.append(item) - } - } - - let template = ListPageTemplateModel(pageType: pageJSON.stringForkey(KeyPageType), - screenHeading: pageJSON.stringForkey(KeyScreenHeading), - molecules: listItems) - - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - template.footer = setFooter(pageJSON, template) - self.templateModel = template - - DispatchQueue.main.async { [weak self] in - self?.view.backgroundColor = UIColor.mfGet(forHex: backgroudColorString) - } - } - - func setFooter(_ pageJSON: [AnyHashable: Any], _ template: ListPageTemplateModel) -> FooterModel? { - - let primaryButtonBGColor = pageJSON.optionalStringForKey("primaryButtonBGColor") ?? "#FFFFFF" - let primaryButtonTextColor = pageJSON.optionalStringForKey("primaryButtonTextColor") ?? "#000000" - - let backgroudColorString = pageJSON.optionalStringForKey("backgroundColor") ?? "#000000" - if let buttonMap = pageJSON.optionalDictionaryForKey("ButtonMap") { - let twoButtonModel = TwoButtonViewModel(nil, nil) - - if let primarybutton = buttonMap.optionalDictionaryForKey(KeyPrimaryButton) { - let buttonDict: [String : Any] = ["title": primarybutton.stringForkey(KeyTitle), - "action": primarybutton, - "moleculeName": "button"] - if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { - let decoder = JSONDecoder() - twoButtonModel.primaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.primaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonBGColor)) - twoButtonModel.primaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) - } - } - if let secondaryButton = buttonMap.optionalDictionaryForKey(KeySecondaryButton) { - let buttonDict: [String : Any] = ["title": secondaryButton.stringForkey(KeyTitle), - "action": secondaryButton, - "moleculeName": "button"] - if let data = try? JSONSerialization.data(withJSONObject: buttonDict) { - let decoder = JSONDecoder() - twoButtonModel.secondaryButton = try? decoder.decode(ButtonModel.self, from: data) - twoButtonModel.secondaryButton?.fillColor = Color(uiColor: UIColor.mfGet(forHex: primaryButtonTextColor)) - twoButtonModel.secondaryButton?.textColor = Color(uiColor: UIColor.mfGet(forHex:primaryButtonBGColor)) - } - } - - let footerStack = MoleculeStackModel(molecules: [MoleculeStackItemModel(with:LineModel(type: .standard)), - MoleculeStackItemModel(with: twoButtonModel)]) - footerStack.useHorizontalMargins = false - footerStack.spacing = PaddingFour - - let footer = FooterModel(with: footerStack) - footer.useHorizontalMargins = false - footer.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - return footer - } - return nil - } - - func getListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - guard let type = moleculeJson.optionalStringForKey("type") else { - return nil - } - - if type == "rewards" { - return getRewardListItem(moleculeJson) - } else { - return getTitleImageListItem(moleculeJson, type) - } - } - - func getTitleImageListItem(_ moleculeJson: [AnyHashable: Any], _ type: String) -> MoleculeListItemModel? { - let textcolor = moleculeJson.optionalStringForKey("textColor") - var stackItems: [MoleculeStackItemModel] = [] - - let titleLabel = LabelModel(text: moleculeJson.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = (type == "topHeader") ? 70.0 : 25.0 - - let messageLabel = LabelModel(text: moleculeJson.stringForkey("message")) - messageLabel.fontStyle = "B2" - messageLabel.textColor = textcolor - - let headlineBodyModel = HeadlineBodyModel(headline: titleLabel) - headlineBodyModel.body = messageLabel - - if let linkMap = moleculeJson.optionalDictionaryForKey("link") { - do { - let linkDict: [String : Any] = ["title": linkMap.stringForkey(KeyTitle), - "action": linkMap] - let data = try JSONSerialization.data(withJSONObject: linkDict) - let decoder = JSONDecoder() - let linkModel = try decoder.decode(LinkModel.self, from: data) - linkModel.textColor = Color(uiColor: UIColor.mfGet(forHex: textcolor ?? "#FFFFFF")) - let headlineBodyLinkModel = HeadlineBodyLinkModel(headlineBody: headlineBodyModel, - link: linkModel) - stackItems.append(MoleculeStackItemModel(with: headlineBodyLinkModel)) - } catch { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) - } - } else { - stackItems.append(MoleculeStackItemModel(with: headlineBodyModel)) - } - - if let imageurl = moleculeJson.optionalStringForKey("imageUrl") { - let imageModel = ImageViewModel(image: imageurl) - imageModel.height = moleculeJson.optionalCGFloatForKey("imageHeight") ?? 300 - imageModel.imageFormat = "jpeg" - imageModel.contentMode = .scaleAspectFit - stackItems.append(MoleculeStackItemModel(with: imageModel)) - } - - let stack = MoleculeStackModel(molecules: stackItems) - let listItem = MoleculeListItemModel(with: stack) - - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - return listItem - } - - func getRewardListItem(_ moleculeJson: [AnyHashable: Any]) -> MoleculeListItemModel? { - - var stackItems: [MoleculeStackItemModel] = [] - - (moleculeJson.arrayForKey("rewards") as? [[AnyHashable: Any]])?.forEach { (rewardItem) in - let textcolor = rewardItem.optionalStringForKey("textColor") - - let titleLabel = LabelModel(text: rewardItem.stringForkey(KeyTitle)) - titleLabel.fontName = "NHaasGroteskDSStd-75Bd" - titleLabel.textColor = textcolor - titleLabel.fontSize = 48 - - let messageLabel = LabelModel(text: rewardItem.stringForkey("message")) - messageLabel.fontName = "NHaasGroteskDSStd-75Bd" - messageLabel.textColor = textcolor - messageLabel.fontSize = 14 - - let titleStackItem = MoleculeStackItemModel(with: titleLabel) - let messageStackItem = MoleculeStackItemModel(with: messageLabel) - - let itemStack = MoleculeStackModel(molecules: [titleStackItem, messageStackItem]) - itemStack.verticalAlignment = .top - itemStack.spacing = 0 - - let horizontalStack = MoleculeStackItemModel(with: itemStack) - horizontalStack.verticalAlignment = .top - stackItems.append(horizontalStack) - } - - stackItems.first?.percent = 35 - stackItems.last?.percent = 65 - let stack = MoleculeStackModel(molecules: stackItems) - stack.axis = .horizontal - stack.horizontalAlignment = .leading - stack.verticalAlignment = .leading - - let listItem = MoleculeListItemModel(with: stack) - let backgroudColorString = moleculeJson.optionalStringForKey("backgroundColor") ?? "#000000" - listItem.backgroundColor = Color(uiColor: UIColor.mfGet(forHex: backgroudColorString)) - listItem.line = LineModel(type: .none) - - return listItem - } -} - diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index cbe0458c..9741f110 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -24,7 +24,11 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- open override func parsePageJSON(_ error: NSErrorPointer) { - try? parseTemplateJSON() + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 8bf0b4cd..ef7a470d 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -13,7 +13,11 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? open override func parsePageJSON(_ error: NSErrorPointer) { - try? parseTemplateJSON() + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 72498289..eb822279 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -13,7 +13,11 @@ import UIKit public var templateModel: ThreeLayerPageTemplateModel? open override func parsePageJSON(_ error: NSErrorPointer) { - try? parseTemplateJSON() + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } override open func viewDidLoad() { From 633eb4ec21d7c29352640a9f3f86ec310f83aefa Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 18 Feb 2020 15:19:28 -0500 Subject: [PATCH 47/96] adding a new action type. updated action map flow. --- MVMCoreUI/Atoms/Buttons/Link.swift | 4 +++ MVMCoreUI/Atoms/Buttons/LinkModel.swift | 26 ++++++++++++++++++- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 2 +- MVMCoreUI/BaseClasses/Button.swift | 9 +++++-- .../MoleculeModelProtocol.swift | 2 +- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link.swift index b4c00c94..5dbbed16 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link.swift @@ -36,6 +36,10 @@ import UIKit context?.strokePath() } + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? LinkModel else { return } diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index f4fab34c..a3dc940c 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -9,20 +9,37 @@ import UIKit public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { - public static var identifier: String = "link" + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public class var identifier: String { + return "link" + } + public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol public var enabled = true public var textColor = Color(uiColor: .mvmBlack) public var disabledColor = Color(uiColor: .mvmCoolGray6) + public var moleculeName: String? + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- public init(title: String, action: ActionModelProtocol) { self.title = title self.action = action } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case title case action @@ -31,11 +48,17 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { case disabledColor } + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } @@ -54,6 +77,7 @@ public 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(moleculeName, forKey: .moleculeName) try container.encode(textColor, forKey: .textColor) try container.encode(disabledColor, forKey: .disabledColor) } diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 5e8cedc8..0f2f65d0 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -301,7 +301,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, 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: false, 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, completionHandler: finishedLoadingBlock) } diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index 60e0ab1a..c0ff0e81 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -12,6 +12,7 @@ public typealias ButtonAction = (Button) -> () //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- + open var model: MoleculeModelProtocol? open var actionModel: ActionModelProtocol? @@ -67,7 +68,7 @@ public typealias ButtonAction = (Button) -> () addTarget(self, action: #selector(callActionBlock(_:)), for: event) } - @objc private func callActionBlock(_ sender: Button) { + @objc func callActionBlock(_ sender: Button) { buttonAction?(self) } @@ -88,11 +89,13 @@ public typealias ButtonAction = (Button) -> () // MARK:- ModelMoleculeViewProtocol open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model + if let backgroundColor = model?.backgroundColor { self.backgroundColor = backgroundColor.uiColor } guard let model = model as? ButtonModelProtocol else { return } + isEnabled = model.enabled set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } @@ -113,7 +116,7 @@ public typealias ButtonAction = (Button) -> () // MARK: - MVMCoreViewProtocol extension Button: MVMCoreViewProtocol { - open func updateView(_ size: CGFloat) {} + open func updateView(_ size: CGFloat) { } /// Will be called only once. open func setupView() { @@ -126,6 +129,7 @@ extension Button: MVMCoreViewProtocol { // MARK: - MVMCoreUIMoleculeViewProtocol extension Button: MVMCoreUIMoleculeViewProtocol { + open func reset() { backgroundColor = .clear } @@ -133,6 +137,7 @@ extension Button: MVMCoreUIMoleculeViewProtocol { // MARK: AppleGuidelinesProtocol extension Button: AppleGuidelinesProtocol { + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return Self.acceptablyOutsideBounds(point: point, bounds: bounds) } diff --git a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift index 1ec0d13c..cec7b90a 100644 --- a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift @@ -3,7 +3,7 @@ import Foundation public protocol MoleculeModelProtocol: Model { var moleculeName: String? { get } - var backgroundColor: Color? { get set} + var backgroundColor: Color? { get set } } public extension MoleculeModelProtocol { From 29f89154f89c68db06d11144366d46ad0013366b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 18 Feb 2020 16:55:56 -0500 Subject: [PATCH 48/96] small model fix for images --- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index fa7d369e..156e187d 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -210,6 +210,9 @@ import UIKit } public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + self.delegateObject = delegateObject + // TODO: Temporary, should be moved to init once we have type erasure ready. + setAsMolecule() guard let imageModel = model as? ImageViewModel else { return } From fa0ec8ab4527a19774815df03911abe4b9150f2d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 19 Feb 2020 09:40:17 -0500 Subject: [PATCH 49/96] minor fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 2 +- .../List/RightVariable/ListRightVariablePayments.swift | 3 ++- .../List/RightVariable/ListRightVariablePaymentsModel.swift | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 698242f9..281a0672 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -789,8 +789,8 @@ AA4FC2A323F4F69600E251DB /* RightVariable */ = { isa = PBXGroup; children = ( - AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, + AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, ); path = RightVariable; sourceTree = ""; diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 046bc331..42f0b7da 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -37,6 +37,7 @@ import Foundation contentView.addSubview(stack) containerHelper.constrainView(stack) } + //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ @@ -47,7 +48,7 @@ import Foundation public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListRightVariablePaymentsModel else { return} + guard let model = model as? ListRightVariablePaymentsModel else { return } leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightImage.setWithModel(model.image, delegateObject, additionalData) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 63719ec1..681f2078 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -11,7 +11,7 @@ import Foundation public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listRVImg" - public var image: ImageViewModel? + public var image: ImageViewModel public var leftLabel: LabelModel public init(image: ImageViewModel, leftLabel: LabelModel) { @@ -44,6 +44,6 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) - try container.encodeIfPresent(image, forKey: .image) + try container.encode(image, forKey: .image) } } From cbe01463d9a50905de0b618f3246c29f547f7b66 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 19 Feb 2020 11:26:24 -0500 Subject: [PATCH 50/96] moleculeName --- .../Atoms/TextFields/BaseDropdownEntryFieldModel.swift | 2 +- MVMCoreUI/Atoms/TextFields/TextFieldModel.swift | 2 +- MVMCoreUI/Atoms/Views/CaretViewModel.swift | 2 ++ MVMCoreUI/Atoms/Views/CheckboxModel.swift | 2 ++ MVMCoreUI/Atoms/Views/DashLineModel.swift | 2 ++ MVMCoreUI/Atoms/Views/ImageViewModel.swift | 1 + MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift | 5 +++++ MVMCoreUI/Atoms/Views/MultiProgressModel.swift | 2 ++ MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift | 2 ++ .../HorizontalCombinationViews/ImageHeadlineBodyModel.swift | 1 + MVMCoreUI/Molecules/Items/StackItemModel.swift | 1 + .../LeftRightViews/ActionDetailWithImageModel.swift | 1 + .../ToggleMolecules/HeadlineBodyLinkToggleModel.swift | 1 + .../ToggleMolecules/HeadlineBodyToggleModel.swift | 1 + .../LeftRightViews/ToggleMolecules/LabelToggleModel.swift | 6 ++++++ MVMCoreUI/Molecules/ScrollerModel.swift | 1 + .../EyebrowHeadlineBodyLinkModel.swift | 2 +- .../VerticalCombinationViews/HeadlineBodyButtonModel.swift | 1 + .../VerticalCombinationViews/HeadlineBodyLinkModel.swift | 1 + .../VerticalCombinationViews/HeadlineBodyModel.swift | 1 + 20 files changed, 34 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift index e6e7cb24..496625dc 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift @@ -37,9 +37,9 @@ } public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(caretView, forKey: .caretView) } } diff --git a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift index 6caa70b0..e26995d6 100644 --- a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift @@ -12,7 +12,7 @@ import UIKit public static var identifier: String = "textField" public var backgroundColor: Color? - public var moleculeName: String + public var moleculeName: String? = TextFieldModel.identifier public var editable: Bool? public var disabled: Bool? public var errorMsg: String? diff --git a/MVMCoreUI/Atoms/Views/CaretViewModel.swift b/MVMCoreUI/Atoms/Views/CaretViewModel.swift index 58291984..cf90496f 100644 --- a/MVMCoreUI/Atoms/Views/CaretViewModel.swift +++ b/MVMCoreUI/Atoms/Views/CaretViewModel.swift @@ -18,6 +18,7 @@ import Foundation public var lineWidth: CGFloat? private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case strokeColor case isHidden @@ -38,6 +39,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(strokeColor, forKey: .strokeColor) try container.encodeIfPresent(isHidden, forKey: .isHidden) try container.encodeIfPresent(isOpaque, forKey: .isOpaque) diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index aa5dedb4..de79c6c6 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -39,6 +39,7 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case groupName case value case fieldKey @@ -85,6 +86,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(value, forKey: .value) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) diff --git a/MVMCoreUI/Atoms/Views/DashLineModel.swift b/MVMCoreUI/Atoms/Views/DashLineModel.swift index 1346b5c2..7f5ac992 100644 --- a/MVMCoreUI/Atoms/Views/DashLineModel.swift +++ b/MVMCoreUI/Atoms/Views/DashLineModel.swift @@ -20,6 +20,7 @@ import Foundation } private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case dashColor case isHidden @@ -36,6 +37,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(dashColor, forKey: .dashColor) try container.encodeIfPresent(isHidden, forKey: .isHidden) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index 97f31ad2..d23289bf 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -11,6 +11,7 @@ import Foundation @objcMembers public class ImageViewModel: MoleculeModelProtocol { public static var identifier: String = "image" public var backgroundColor: Color? + public var moleculeName: String? = ImageViewModel.identifier public var image: String public var accessibilityText: String? public var fallbackImage: String? diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift index 325611ec..d7ee1553 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift @@ -10,7 +10,12 @@ import UIKit @objcMembers public class LeftRightLabelModel: MoleculeModelProtocol { public static var identifier: String = "leftRightLabelView" + public var moleculeName: String? = LeftRightLabelModel.identifier public var backgroundColor: Color? public var leftText: LabelModel public var rightText: LabelModel? + + init(_ leftText: LabelModel) { + self.leftText = leftText + } } diff --git a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift index 6dd05b0b..4033fd28 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift @@ -26,6 +26,7 @@ import Foundation public var roundedRect: Bool? private enum CodingKeys: String, CodingKey { + case moleculeName case progressList case thickness case roundedRect @@ -46,6 +47,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(progressList, forKey: .progressList) try container.encodeIfPresent(thickness, forKey: .thickness) try container.encodeIfPresent(roundedRect, forKey: .roundedRect) diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift index 42acd2f0..af6100ac 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift @@ -11,6 +11,7 @@ import Foundation @objcMembers public class DoughnutChartModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChart" + public var moleculeName: String? = DoughnutChartModel.identifier public var title: LabelModel? public var subtitle: LabelModel? public var sections: [DoughnutChartItemModel] @@ -24,6 +25,7 @@ import Foundation @objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChartItem" + public var moleculeName: String? = DoughnutChartItemModel.identifier public var label: LabelModel @Percent public var percent: CGFloat public var color: Color diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index 4966ce58..7f3d52dc 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -10,6 +10,7 @@ import Foundation public struct ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" + public var moleculeName: String? = ImageHeadlineBodyModel.identifier public var backgroundColor: Color? public var image: ImageViewModel public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index 2058353c..b7d1a269 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -10,6 +10,7 @@ import Foundation @objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol { public static var identifier: String = "simpleStackItem" + public var moleculeName: String? = StackItemModel.identifier public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? diff --git a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index a397c1a1..9dbf53c0 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -10,6 +10,7 @@ import Foundation public struct ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" + public var moleculeName: String? = ActionDetailWithImageModel.identifier public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel public var image: ImageViewModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index 5ce04f9c..aad8ec06 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -9,6 +9,7 @@ import Foundation public struct HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" + public var moleculeName: String? = HeadlineBodyLinkToggleModel.identifier public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index dd7c2b1c..bb3391a6 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -11,6 +11,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" + public var moleculeName: String? = HeadlineBodyToggleModel.identifier open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift index 7ed5857e..526ac6b9 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift @@ -10,7 +10,13 @@ import Foundation public class LabelToggleModel: MoleculeModelProtocol { public static var identifier: String = "labelToggle" + public var moleculeName: String? = LabelToggleModel.identifier public var backgroundColor: Color? public var label: LabelModel public var toggle: ToggleModel + + init(_ label: LabelModel, _ toggle: ToggleModel) { + self.label = label + self.toggle = toggle + } } diff --git a/MVMCoreUI/Molecules/ScrollerModel.swift b/MVMCoreUI/Molecules/ScrollerModel.swift index f92fe13b..91dc2e1c 100644 --- a/MVMCoreUI/Molecules/ScrollerModel.swift +++ b/MVMCoreUI/Molecules/ScrollerModel.swift @@ -10,5 +10,6 @@ import UIKit public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol { public static var identifier: String = "scroller" + public var moleculeName: String? = ScrollerModel.identifier public var backgroundColor: Color? } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index e9341535..81a38111 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -11,7 +11,7 @@ import Foundation struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { static var identifier: String = "eyebrowHeadlineBodyLink" var backgroundColor: Color? - + var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier public var eyeBrow: LabelModel? public var headline: LabelModel? public var body: LabelModel? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 74e85ea9..ec97fda0 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -10,6 +10,7 @@ import Foundation public struct HeadlineBodyButtonModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyButton" + public var moleculeName: String? = HeadlineBodyButtonModel.identifier public var backgroundColor: Color? public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index 9eae8e03..27f0d670 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -10,6 +10,7 @@ import Foundation public struct HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" + public var moleculeName: String? = HeadlineBodyLinkModel.identifier public var headlineBody: HeadlineBodyModel public var link: LinkModel public var backgroundColor: Color? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index fd5be23a..d7a08091 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -10,6 +10,7 @@ import Foundation @objcMembers public class HeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "headlineBody" + public var moleculeName: String? = HeadlineBodyModel.identifier public var headline: LabelModel? public var body: LabelModel? public var style: String? From 23fa0c5badf8f03228ee0ab034d19045f2595d89 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 19 Feb 2020 12:36:28 -0500 Subject: [PATCH 51/96] reverting --- MVMCoreUI/Atoms/Buttons/LinkModel.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index a3dc940c..28fc8596 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -13,9 +13,7 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- - public class var identifier: String { - return "link" - } + public static var identifier: String = "link" public var backgroundColor: Color? public var title: String @@ -23,7 +21,6 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public var enabled = true public var textColor = Color(uiColor: .mvmBlack) public var disabledColor = Color(uiColor: .mvmCoolGray6) - public var moleculeName: String? //-------------------------------------------------- // MARK: - Initializer @@ -54,7 +51,6 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) From 08cf275ba4d0c0a8b1b82708ef6fd0ea2f1dcbf5 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 19 Feb 2020 13:59:28 -0500 Subject: [PATCH 52/96] space --- MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift index af6100ac..1e5c7dce 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift @@ -11,7 +11,7 @@ import Foundation @objcMembers public class DoughnutChartModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChart" - public var moleculeName: String? = DoughnutChartModel.identifier + public var moleculeName: String? = DoughnutChartModel.identifier public var title: LabelModel? public var subtitle: LabelModel? public var sections: [DoughnutChartItemModel] From b5ac3b0b763efe79c0053616bf37b10a7bfa5769 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 19 Feb 2020 14:09:34 -0500 Subject: [PATCH 53/96] fixes --- MVMCoreUI/Molecules/Items/CarouselItemModel.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift index f2c88e9b..9fc218a7 100644 --- a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift @@ -14,7 +14,6 @@ import Foundation public var backgroundColor: Color? public var peakingUI: Bool? public var peakingArrowColor: Color? - public var moleculeName: String? private enum CodingKeys: String, CodingKey { case moleculeName @@ -25,7 +24,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI) peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor) From f38b577321743965583ab9cfeb8d48047f4c996d Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 19 Feb 2020 14:26:52 -0500 Subject: [PATCH 54/96] add missing moleculeName --- MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift | 2 ++ MVMCoreUI/Atoms/Buttons/LinkModel.swift | 2 ++ MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift | 2 -- MVMCoreUI/Atoms/Views/CircleProgressModel.swift | 2 ++ MVMCoreUI/Atoms/Views/ToggleModel.swift | 1 - MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift | 2 ++ MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift | 2 ++ .../Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift | 1 + MVMCoreUI/Organisms/CarouselModel.swift | 2 +- MVMCoreUI/Organisms/StackModel.swift | 1 + 10 files changed, 13 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift index defe6816..4b28fc8c 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift @@ -30,6 +30,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { case enabledColor case disabledColor case enabled + case moleculeName } required public init(from decoder: Decoder) throws { @@ -50,6 +51,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index f4fab34c..1092289f 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -29,6 +29,7 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { case enabled case textColor case disabledColor + case moleculeName } required public init(from decoder: Decoder) throws { @@ -56,5 +57,6 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { try container.encode(enabled, forKey: .enabled) try container.encode(textColor, forKey: .textColor) try container.encode(disabledColor, forKey: .disabledColor) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 1030fb8c..e4a794bc 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -19,7 +19,6 @@ import Foundation } public var backgroundColor: Color? - public var moleculeName: String? public var title: String? public var feedback: String? public var errorMessage: String = "" @@ -54,7 +53,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift index c4f55bef..9a1908f8 100644 --- a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -48,6 +48,7 @@ public class CircleProgressModel: MoleculeModelProtocol { case duration case colors case backgroundColor + case moleculeName } required public init(from decoder: Decoder) throws { @@ -78,6 +79,7 @@ public class CircleProgressModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(style, forKey: .style) try container.encode(size, forKey: .size) try container.encode(diameter, forKey: .diameter) diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index 9cd96f45..aafacec8 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -10,7 +10,6 @@ import UIKit public class ToggleModel: MoleculeModelProtocol { public static var identifier: String = "toggle" - public var moleculeName: String? public var backgroundColor: Color? public var state: Bool = true public var action: ActionModelProtocol? diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift index f45c771d..8b69c590 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -22,6 +22,7 @@ public class TabsModel: MoleculeModelProtocol { case backgroundColor case selectedColor case selectedIndex + case moleculeName } public init(with tabs: [LabelModel]) { @@ -42,6 +43,7 @@ public class TabsModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) try container.encode(backgroundColor, forKey: .backgroundColor) try container.encode(selectedColor, forKey: .selectedColor) diff --git a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift index f4b67216..bb3e6f17 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift @@ -28,6 +28,7 @@ public class CornerLabelsModel: MoleculeModelProtocol { case bottomLeftLabel case bottomRightLabel case molecule + case moleculeName } required public init(from decoder: Decoder) throws { @@ -48,5 +49,6 @@ public class CornerLabelsModel: MoleculeModelProtocol { try container.encodeIfPresent(topRightLabel, forKey: .topRightLabel) try container.encodeIfPresent(bottomLeftLabel, forKey: .bottomLeftLabel) try container.encodeIfPresent(bottomRightLabel, forKey: .bottomRightLabel) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift index caa00021..c66f27b8 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift @@ -38,5 +38,6 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(string, forKey: .string) try container.encodeModel(molecule, forKey: .molecule) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Organisms/CarouselModel.swift b/MVMCoreUI/Organisms/CarouselModel.swift index e43e6caa..79693135 100644 --- a/MVMCoreUI/Organisms/CarouselModel.swift +++ b/MVMCoreUI/Organisms/CarouselModel.swift @@ -53,7 +53,7 @@ import UIKit public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(moleculeName, forKey: .moleculeName) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(molecules, forKey: .molecules) try container.encode(spacing, forKey: .spacing) diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index 741946c5..8d670efb 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -45,5 +45,6 @@ import Foundation try container.encodeIfPresent(molecules, forKey: .molecules) try container.encodeIfPresent(axis.rawValueString, forKey: .axis) try container.encodeIfPresent(spacing, forKey: .spacing) + try container.encode(moleculeName, forKey: .moleculeName) } } From 5c42c4bf28d5206aa52848b183b48fe7e90be470 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 19 Feb 2020 14:45:51 -0500 Subject: [PATCH 55/96] remove typo --- MVMCoreUI/Atoms/Buttons/LinkModel.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index 590cdbf7..a4fe6cf2 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -43,7 +43,6 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { case enabled case textColor case disabledColor - case moleculeName } //-------------------------------------------------- @@ -74,9 +73,7 @@ public 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(moleculeName, forKey: .moleculeName) try container.encode(textColor, forKey: .textColor) try container.encode(disabledColor, forKey: .disabledColor) - try container.encode(moleculeName, forKey: .moleculeName) } } From 6b1a02c369518e4e9739b6ec0a1b563f0f7f4d0e Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 19 Feb 2020 14:48:31 -0500 Subject: [PATCH 56/96] fix typo --- MVMCoreUI/Atoms/Buttons/LinkModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index a4fe6cf2..7094a038 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -70,6 +70,7 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(title, forKey: .title) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabled) From 50d1d1a13a9af6b67fb50b5cc12171b765fb2d62 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 19 Feb 2020 17:12:50 -0500 Subject: [PATCH 57/96] Fixes to allow bundle improvements --- MVMCoreUI/Atoms/Views/ImageViewModel.swift | 14 +++++++++++++- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 6 +++--- .../RightVariable/ListRightVariablePayments.swift | 2 +- .../ListRightVariablePaymentsModel.swift | 7 +++++-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index 97f31ad2..02140bf9 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -18,8 +18,20 @@ import Foundation public var width: CGFloat? public var height: CGFloat? public var contentMode: UIView.ContentMode? - + public var localBundle: Bundle? + public init(image: String) { self.image = image } + + private enum CodingKeys: String, CodingKey { + case backgroundColor + case image + case accessibilityText + case fallbackImage + case imageFormat + case width + case height + case contentMode + } } diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 156e187d..0079d1a6 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -233,7 +233,7 @@ import UIKit if shouldLoadImage(withName: imageModel.image, width: width, height: height) { imageView.image = nil imageView.animatedImage = nil - loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage) + loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage, localBundle: imageModel.localBundle) } if let contentMode = imageModel.contentMode { @@ -276,7 +276,7 @@ import UIKit } // MARK: - load functions - public func loadImage(withName imageName: String?, format: String? = nil, width: NSNumber? = nil, height: NSNumber? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, completionHandler: MVMCoreGetImageBlock? = nil) { + public func loadImage(withName imageName: String?, format: String? = nil, width: NSNumber? = nil, height: NSNumber? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) { let completionBlock = completionHandler ?? defaultCompletionBlock() MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in @@ -308,7 +308,7 @@ import UIKit // 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) } 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, completionHandler: finishedLoadingBlock) + 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) } }) } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 42f0b7da..2bfbc321 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -56,7 +56,7 @@ import Foundation let leftLabel = StackItemModel() leftLabel.horizontalAlignment = .leading let rightImage = StackItemModel() - rightImage.horizontalAlignment = .trailing + rightImage.horizontalAlignment = .fill let stackModel = StackModel(molecules: [leftLabel,rightImage]) stackModel.axis = .horizontal stack.model = stackModel diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index 681f2078..a8c6ff80 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -21,8 +21,11 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco } static func createPayPalImage() -> ImageViewModel { - let image = ImageViewModel(image: "imagename_paypal") - image.width = 30.0 + let image = ImageViewModel(image: "imageName_PayPal_logo") + image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI() + image.width = 70.0 + image.height = 18.0 + image.contentMode = .scaleAspectFit return image } From 6563a14ff72c7d97a72a27f4ce6ca68f3bacbdf2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 19 Feb 2020 17:19:36 -0500 Subject: [PATCH 58/96] moleculeName coddle --- MVMCoreUI/Atoms/Views/ImageViewModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index 00694c69..0f585119 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -26,6 +26,7 @@ import Foundation } private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case image case accessibilityText From 0947ba93ef13dcfa7d33efd356fe9ae464e0e00c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 19 Feb 2020 17:31:47 -0500 Subject: [PATCH 59/96] paypal image --- .../Contents.json | 23 ++++++++++++++++++ .../paypal_horiz_logo.jpeg | Bin 0 -> 1826 bytes .../paypal_horiz_logo@2x.jpeg | Bin 0 -> 3418 bytes .../paypal_horiz_logo@3x.jpeg | Bin 0 -> 4606 bytes 4 files changed, 23 insertions(+) create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@2x.jpeg create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json new file mode 100644 index 00000000..b4c381b8 --- /dev/null +++ b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo@2x.jpeg", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo@3x.jpeg", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..95113ebf4001cf2eed20fbe23530dea3d1e475a9 GIT binary patch literal 1826 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 literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..cbd78652ce3bdb9fb3e62b4b4522b2f40b1556a2 GIT binary patch literal 4606 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 literal 0 HcmV?d00001 From 80935685595cb33427332a173782e7158c82930f Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 20 Feb 2020 13:42:17 +0530 Subject: [PATCH 60/96] Review comment fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 2 +- MVMCoreUI/Atoms/Views/CircleProgressModel.swift | 4 ++-- .../Molecules/VerticalCombinationViews/ListRVWheelModel.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 4aefcfd3..4c449f92 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -890,8 +890,8 @@ C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */, D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */, 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, - C7F8012023E8303200396FBD /* ListRVWheel.swift */, C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, + C7F8012023E8303200396FBD /* ListRVWheel.swift */, ); path = VerticalCombinationViews; sourceTree = ""; diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift index f159f1e3..fd57a04c 100644 --- a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -55,9 +55,11 @@ public class CircleProgressModel: MoleculeModelProtocol { if let style = try typeContainer.decodeIfPresent(GraphStyle.self, forKey: .style) { self.style = style } + updateStyle() if let size = try typeContainer.decodeIfPresent(GraphSize.self, forKey: .size) { self.size = size } + updateSize() if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) { self.diameter = diameter } @@ -74,8 +76,6 @@ public class CircleProgressModel: MoleculeModelProtocol { self.colors = colors } backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - updateSize() - updateStyle() } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift index a4c5f028..ec856bb1 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift @@ -35,6 +35,6 @@ public class ListRVWheelModel:MoleculeModelProtocol { try container.encode(ListRVWheelModel.identifier, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) try container.encode(rightLabel, forKey: .rightLabel) - try container.encodeIfPresent(wheel, forKey: .wheel) + try container.encode(wheel, forKey: .wheel) } } From dc3178815c1cb7886fdc07281275f301e0338750 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 20 Feb 2020 14:08:47 +0530 Subject: [PATCH 61/96] Renaming of molecule file, class and model --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++++++++-------- ...istLeftVariableCheckboxAllTextAndLinks.swift} | 4 ++-- ...ftVariableCheckboxAllTextAndLinksModel.swift} | 4 ++-- .../OtherHandlers/MoleculeObjectMapping.swift | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) rename MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/{ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift => ListLeftVariableCheckboxAllTextAndLinks.swift} (93%) rename MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/{ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift => ListLeftVariableCheckboxAllTextAndLinksModel.swift} (89%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f31234f2..47d783ce 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -127,8 +127,8 @@ 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 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 */; }; - AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */; }; - AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */; }; + AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; + AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; @@ -451,8 +451,8 @@ 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; 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 = ""; }; - AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift; sourceTree = ""; }; - AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift; sourceTree = ""; }; + AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; + AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; @@ -975,8 +975,8 @@ children = ( 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, - AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift */, - AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift */, + AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift */, + AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, ); path = LeftVariable; sourceTree = ""; @@ -1645,7 +1645,7 @@ 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, - AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift in Sources */, + AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, @@ -1792,7 +1792,7 @@ D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */, - AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift in Sources */, + AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */, 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */, 01EB369323609801006832FA /* HeaderModel.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift similarity index 93% rename from MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift index c194cc50..d68c9d1f 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift @@ -1,5 +1,5 @@ // -// ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.swift +// ListLeftVariableCheckboxAllTextAndLinks.swift // MVMCoreUI // // Created by Lekshmi S on 11/02/20. @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinks: TableViewCell { +@objcMembers public class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { //----------------------------------------------------- // MARK: - Outlets diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift similarity index 89% rename from MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift index 330901a6..80ab9506 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -1,5 +1,5 @@ // -// ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.swift +// ListLeftVariableCheckboxAllTextAndLinksModel.swift // MVMCoreUI // // Created by Lekshmi S on 11/02/20. @@ -8,7 +8,7 @@ import Foundation -public class ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { +public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listLVCB" public var checkbox: CheckboxModel diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 049183a4..4b4ee536 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -72,7 +72,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxWithRightCaretAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self) From 576ce2ff56150d710da0844f37de8eace8e1fd0a Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 20 Feb 2020 14:41:01 +0530 Subject: [PATCH 62/96] renamed model --- ...stLeftVariableCheckboxAllTextAndLinks.swift | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift index d68c9d1f..d83e8389 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift @@ -10,18 +10,10 @@ import Foundation @objcMembers public class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { - //----------------------------------------------------- - // MARK: - Outlets - //------------------------------------------------------- - let checkbox = Checkbox(frame: .zero) let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) let stack = Stack(frame: .zero) - - //----------------------------------------------------- - // MARK: - View Lifecycle - //------------------------------------------------------- - + open override func updateView(_ size: CGFloat) { super.updateView(size) stack.updateView(size) @@ -38,10 +30,6 @@ import Foundation containerHelper.constrainView(stack) } - //---------------------------------------------------- - // MARK: - Molecule - //------------------------------------------------------ - override open func reset() { super.reset() stack.reset() @@ -49,10 +37,10 @@ import Foundation public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - guard let model = model as? ListLeftVariableCheckboxWithRightCaretAllTextAndLinksModel else { return} + guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return} checkbox.setWithModel(model.checkbox, delegateObject, additionalData) eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) - + // Create a stack model to use for the internal stack and set the alignment of labels let checkbox = StackItemModel(percent: 10) checkbox.horizontalAlignment = .leading From 4803e20363d118392c263937ac8e8497d885ddf3 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 20 Feb 2020 14:52:57 +0530 Subject: [PATCH 63/96] Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/ListLeftVar_Checkbox-_Right_Caret # Conflicts: # MVMCoreUI.xcodeproj/project.pbxproj # MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift --- MVMCoreUI.xcodeproj/project.pbxproj | 28 ++- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 8 +- MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift | 2 + MVMCoreUI/Atoms/Buttons/Link.swift | 4 + MVMCoreUI/Atoms/Buttons/LinkModel.swift | 20 ++ .../BaseDropdownEntryFieldModel.swift | 2 +- .../Atoms/TextFields/EntryFieldModel.swift | 4 +- .../Atoms/TextFields/TextFieldModel.swift | 2 +- MVMCoreUI/Atoms/Views/CaretViewModel.swift | 2 + MVMCoreUI/Atoms/Views/CheckboxModel.swift | 2 + .../Atoms/Views/CircleProgressModel.swift | 2 + MVMCoreUI/Atoms/Views/DashLineModel.swift | 2 + MVMCoreUI/Atoms/Views/ImageViewModel.swift | 20 +- .../Label/LabelAttributeActionModel.swift | 15 +- .../Views/Label/LabelAttributeModel.swift | 13 +- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 9 +- .../Atoms/Views/LeftRightLabelModel.swift | 5 + MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 25 ++- .../Atoms/Views/MultiProgressModel.swift | 2 + MVMCoreUI/Atoms/Views/ToggleModel.swift | 1 - MVMCoreUI/BaseClasses/Button.swift | 11 +- .../MFViewController+Model.swift | 4 - MVMCoreUI/BaseControllers/MFViewController.h | 3 + MVMCoreUI/BaseControllers/MFViewController.m | 8 +- MVMCoreUI/Categories/UIColor+Extension.swift | 177 +++++++++++++++--- MVMCoreUI/Categories/UIColor+MFConvenience.h | 1 + MVMCoreUI/Categories/UIColor+MFConvenience.m | 5 +- .../Categories/UIContentMode+Extension.swift | 98 ++++++++++ MVMCoreUI/CustomPrimitives/Color.swift | 2 +- .../MoleculeModelProtocol.swift | 2 +- .../ListRightVariablePayments.swift | 69 +++++++ .../ListRightVariablePaymentsModel.swift | 52 +++++ .../Doughnut/DoughnutChartModel.swift | 2 + .../ImageHeadlineBodyModel.swift | 1 + .../TabsModel.swift | 2 + .../TwoButtonViewModel.swift | 5 + .../Molecules/Items/CarouselItemModel.swift | 2 - .../Items/MoleculeStackItemModel.swift | 2 +- .../Molecules/Items/StackItemModel.swift | 1 + .../ActionDetailWithImageModel.swift | 1 + .../LeftRightViews/CornerLabelsModel.swift | 2 + .../HeadlineBodyLinkToggleModel.swift | 1 + .../HeadlineBodyToggleModel.swift | 1 + .../ToggleMolecules/LabelToggleModel.swift | 6 + MVMCoreUI/Molecules/ScrollerModel.swift | 1 + .../EyebrowHeadlineBodyLinkModel.swift | 2 +- .../HeadlineBodyButtonModel.swift | 1 + .../HeadlineBodyLinkModel.swift | 1 + .../HeadlineBodyModel.swift | 2 +- .../StringAndMoleculeModel.swift | 1 + MVMCoreUI/Organisms/CarouselModel.swift | 2 +- MVMCoreUI/Organisms/StackModel.swift | 1 + .../MVMCoreUIViewControllerMappingObject.m | 3 +- .../OtherHandlers/MoleculeObjectMapping.swift | 2 +- .../Contents.json | 23 +++ .../paypal_horiz_logo.jpeg | Bin 0 -> 1826 bytes .../paypal_horiz_logo@2x.jpeg | Bin 0 -> 3418 bytes .../paypal_horiz_logo@3x.jpeg | Bin 0 -> 4606 bytes .../Templates/MoleculeListTemplate.swift | 8 +- .../Templates/MoleculeStackTemplate.swift | 8 +- MVMCoreUI/Templates/ThreeLayerTemplate.swift | 9 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 2 +- 62 files changed, 609 insertions(+), 83 deletions(-) create mode 100644 MVMCoreUI/Categories/UIContentMode+Extension.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@2x.jpeg create mode 100644 MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 47d783ce..281a0672 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 012A88F123985E0100FE3DA1 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88F023985E0100FE3DA1 /* Color.swift */; }; 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; }; 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; }; + 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */; }; 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */; }; 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72223C501E2006F3E93 /* ContainerModel.swift */; }; 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */; }; @@ -127,8 +128,8 @@ 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 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 */; }; - AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; - AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; + AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; + AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */; }; @@ -361,6 +362,7 @@ 012A88F023985E0100FE3DA1 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = ""; }; 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = ""; }; + 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIContentMode+Extension.swift"; sourceTree = ""; }; 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = ""; }; 014AA72223C501E2006F3E93 /* ContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModel.swift; sourceTree = ""; }; 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerModelProtocol.swift; sourceTree = ""; }; @@ -451,8 +453,8 @@ 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; 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 = ""; }; - AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; - AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; 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 = ""; }; C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; C695A67E23C9830600BFB94E /* UnOrderedListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnOrderedListModel.swift; sourceTree = ""; }; @@ -784,6 +786,15 @@ name = "Recovered References"; sourceTree = ""; }; + AA4FC2A323F4F69600E251DB /* RightVariable */ = { + isa = PBXGroup; + children = ( + AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, + AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, + ); + path = RightVariable; + sourceTree = ""; + }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -965,6 +976,7 @@ D22B38EA23F4E08B00490EF6 /* List */ = { isa = PBXGroup; children = ( + AA4FC2A323F4F69600E251DB /* RightVariable */, D22B38EB23F4E0AE00490EF6 /* LeftVariable */, ); path = List; @@ -975,8 +987,6 @@ children = ( 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, - AA29DC9A23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift */, - AA29DC9C23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, ); path = LeftVariable; sourceTree = ""; @@ -1148,6 +1158,7 @@ D29DF11021E6805F003B2FB9 /* Categories */ = { isa = PBXGroup; children = ( + 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */, D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */, D29DF11321E6805F003B2FB9 /* UIColor+MFConvenience.m */, D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */, @@ -1619,6 +1630,7 @@ DBC4391922442197001AB423 /* DashLine.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, + AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, @@ -1645,7 +1657,6 @@ 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, - AA29DC9D23F2ACAC00A52198 /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, @@ -1681,6 +1692,7 @@ D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, 0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, + AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, @@ -1792,7 +1804,6 @@ D28A839323CE828900DFE4FC /* HeadlineBodyCaretLinkImageModel.swift in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */, - AA29DC9B23F2AA3800A52198 /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */, 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */, 01EB369323609801006832FA /* HeaderModel.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, @@ -1809,6 +1820,7 @@ 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, + 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index cfe8bb2f..f02eaf5c 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -20,7 +20,6 @@ public enum ButtonSize: String, Codable { public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public static var identifier: String = "button" - public var moleculeName: String? public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol @@ -46,6 +45,12 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { self.action = action style = .secondary } + + init(primaryButtonWith title: String, action: ActionModelProtocol) { + self.title = title + self.action = action + style = .primary + } private enum CodingKeys: String, CodingKey { case moleculeName @@ -67,7 +72,6 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) diff --git a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift index defe6816..4b28fc8c 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift @@ -30,6 +30,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { case enabledColor case disabledColor case enabled + case moleculeName } required public init(from decoder: Decoder) throws { @@ -50,6 +51,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link.swift index b4c00c94..5dbbed16 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link.swift @@ -36,6 +36,10 @@ import UIKit context?.strokePath() } + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? LinkModel else { return } diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index f4fab34c..7094a038 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -9,7 +9,12 @@ import UIKit public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "link" + public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol @@ -17,12 +22,21 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public var textColor = Color(uiColor: .mvmBlack) public var disabledColor = Color(uiColor: .mvmCoolGray6) + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(title: String, action: ActionModelProtocol) { self.title = title self.action = action } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case title case action @@ -31,11 +45,16 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { case disabledColor } + //-------------------------------------------------- + // 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) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } @@ -51,6 +70,7 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(title, forKey: .title) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabled) diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift index e6e7cb24..496625dc 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift @@ -37,9 +37,9 @@ } public override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(caretView, forKey: .caretView) } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 5f60081e..e4a794bc 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -19,7 +19,6 @@ import Foundation } public var backgroundColor: Color? - public var moleculeName: String? public var title: String? public var feedback: String? public var errorMessage: String = "" @@ -37,7 +36,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor - case title + case title = "label" case isEnabled case feedback case errorMessage = "errorMsg" @@ -54,7 +53,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) diff --git a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift index 6caa70b0..e26995d6 100644 --- a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift @@ -12,7 +12,7 @@ import UIKit public static var identifier: String = "textField" public var backgroundColor: Color? - public var moleculeName: String + public var moleculeName: String? = TextFieldModel.identifier public var editable: Bool? public var disabled: Bool? public var errorMsg: String? diff --git a/MVMCoreUI/Atoms/Views/CaretViewModel.swift b/MVMCoreUI/Atoms/Views/CaretViewModel.swift index 58291984..cf90496f 100644 --- a/MVMCoreUI/Atoms/Views/CaretViewModel.swift +++ b/MVMCoreUI/Atoms/Views/CaretViewModel.swift @@ -18,6 +18,7 @@ import Foundation public var lineWidth: CGFloat? private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case strokeColor case isHidden @@ -38,6 +39,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(strokeColor, forKey: .strokeColor) try container.encodeIfPresent(isHidden, forKey: .isHidden) try container.encodeIfPresent(isOpaque, forKey: .isOpaque) diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index aa5dedb4..de79c6c6 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -39,6 +39,7 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case groupName case value case fieldKey @@ -85,6 +86,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(value, forKey: .value) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift index c4f55bef..9a1908f8 100644 --- a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -48,6 +48,7 @@ public class CircleProgressModel: MoleculeModelProtocol { case duration case colors case backgroundColor + case moleculeName } required public init(from decoder: Decoder) throws { @@ -78,6 +79,7 @@ public class CircleProgressModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(style, forKey: .style) try container.encode(size, forKey: .size) try container.encode(diameter, forKey: .diameter) diff --git a/MVMCoreUI/Atoms/Views/DashLineModel.swift b/MVMCoreUI/Atoms/Views/DashLineModel.swift index 1346b5c2..7f5ac992 100644 --- a/MVMCoreUI/Atoms/Views/DashLineModel.swift +++ b/MVMCoreUI/Atoms/Views/DashLineModel.swift @@ -20,6 +20,7 @@ import Foundation } private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case dashColor case isHidden @@ -36,6 +37,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(dashColor, forKey: .dashColor) try container.encodeIfPresent(isHidden, forKey: .isHidden) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index ce46a930..0f585119 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -11,11 +11,29 @@ import Foundation @objcMembers public class ImageViewModel: MoleculeModelProtocol { public static var identifier: String = "image" public var backgroundColor: Color? - + public var moleculeName: String? = ImageViewModel.identifier public var image: String public var accessibilityText: String? public var fallbackImage: String? public var imageFormat: String? public var width: CGFloat? public var height: CGFloat? + public var contentMode: UIView.ContentMode? + public var localBundle: Bundle? + + public init(image: String) { + self.image = image + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case image + case accessibilityText + case fallbackImage + case imageFormat + case width + case height + case contentMode + } } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift index 2ebcb4b4..503f00d8 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeActionModel.swift @@ -8,12 +8,21 @@ import UIKit -class LabelAttributeActionModel: LabelAttributeModel { +open class LabelAttributeActionModel: LabelAttributeModel { override public class var identifier: String { return "action" } var action: ActionModelProtocol + public init(_ location: Int, _ length: Int, action: ActionModelProtocol) { + self.action = action + super.init(location, length) + } + + private enum CodingKeys: String, CodingKey { + case action + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) @@ -25,8 +34,4 @@ class LabelAttributeActionModel: LabelAttributeModel { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeModel(action, forKey: .action) } - - private enum CodingKeys: String, CodingKey { - case action - } } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift index 22bb10d8..437ec0cc 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelAttributeModel.swift @@ -25,10 +25,18 @@ import Foundation return "" } - var type: String + var type: String { + get { return Self.identifier } + } + var location: Int var length: Int - + + init(_ location: Int, _ length: Int) { + self.location = location + self.length = length + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -45,7 +53,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - type = try typeContainer.decode(String.self, forKey: .type) location = try typeContainer.decode(Int.self, forKey: .location) length = try typeContainer.decode(Int.self, forKey: .length) } diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index 731b23da..d7fb4fa3 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -11,9 +11,7 @@ import Foundation @objcMembers public class LabelModel: MoleculeModelProtocol { public static var identifier: String = "label" - public var moleculeName: String? public var backgroundColor: Color? - public var text: String public var accessibilityText: String? public var textColor: String? @@ -45,10 +43,13 @@ import Foundation enum AttributeTypeKey: String, CodingKey { case type } - + + public init(text: String) { + self.text = text + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) text = try typeContainer.decode(String.self, forKey: .text) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) textColor = try typeContainer.decodeIfPresent(String.self, forKey: .textColor) diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift index 325611ec..d7ee1553 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift @@ -10,7 +10,12 @@ import UIKit @objcMembers public class LeftRightLabelModel: MoleculeModelProtocol { public static var identifier: String = "leftRightLabelView" + public var moleculeName: String? = LeftRightLabelModel.identifier public var backgroundColor: Color? public var leftText: LabelModel public var rightText: LabelModel? + + init(_ leftText: LabelModel) { + self.leftText = leftText + } } diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 1c54b891..0079d1a6 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -210,6 +210,9 @@ import UIKit } public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + self.delegateObject = delegateObject + // TODO: Temporary, should be moved to init once we have type erasure ready. + setAsMolecule() guard let imageModel = model as? ImageViewModel else { return } @@ -230,7 +233,11 @@ import UIKit if shouldLoadImage(withName: imageModel.image, width: width, height: height) { imageView.image = nil imageView.animatedImage = nil - loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage) + loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage, localBundle: imageModel.localBundle) + } + + if let contentMode = imageModel.contentMode { + imageView.contentMode = contentMode } } @@ -269,7 +276,9 @@ import UIKit } // MARK: - load functions - public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { + public func loadImage(withName imageName: String?, format: String? = nil, width: NSNumber? = nil, height: NSNumber? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) { + + let completionBlock = completionHandler ?? defaultCompletionBlock() MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in self.currentImageName = imageName self.currentImageWidth = width?.cgfloat() @@ -291,15 +300,15 @@ import UIKit if layoutWillChange { self?.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self!) } - completionHandler(image,data,isFallbackImage) + completionBlock(image,data,isFallbackImage) })} 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, 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, 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, completionHandler: finishedLoadingBlock) + 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) } }) } @@ -329,6 +338,8 @@ import UIKit }) } + // Note: Exposed for objective-c interfaces. + public func loadImage(withName imageName: String?) { loadImage(withName: imageName, format: nil, width: nil, height: nil, customFallbackImage: nil, completionHandler: defaultCompletionBlock()) } @@ -364,4 +375,8 @@ import UIKit public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) { loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock()) } + + public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { + loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, allowServerParameters: false, completionHandler: completionHandler) + } } diff --git a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift index 6dd05b0b..4033fd28 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift @@ -26,6 +26,7 @@ import Foundation public var roundedRect: Bool? private enum CodingKeys: String, CodingKey { + case moleculeName case progressList case thickness case roundedRect @@ -46,6 +47,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(progressList, forKey: .progressList) try container.encodeIfPresent(thickness, forKey: .thickness) try container.encodeIfPresent(roundedRect, forKey: .roundedRect) diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index 9cd96f45..aafacec8 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -10,7 +10,6 @@ import UIKit public class ToggleModel: MoleculeModelProtocol { public static var identifier: String = "toggle" - public var moleculeName: String? public var backgroundColor: Color? public var state: Bool = true public var action: ActionModelProtocol? diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index a780151a..c0ff0e81 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -12,6 +12,7 @@ public typealias ButtonAction = (Button) -> () //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- + open var model: MoleculeModelProtocol? open var actionModel: ActionModelProtocol? @@ -67,7 +68,7 @@ public typealias ButtonAction = (Button) -> () addTarget(self, action: #selector(callActionBlock(_:)), for: event) } - @objc private func callActionBlock(_ sender: Button) { + @objc func callActionBlock(_ sender: Button) { buttonAction?(self) } @@ -88,11 +89,13 @@ public typealias ButtonAction = (Button) -> () // MARK:- ModelMoleculeViewProtocol open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model + if let backgroundColor = model?.backgroundColor { self.backgroundColor = backgroundColor.uiColor } - + guard let model = model as? ButtonModelProtocol else { return } + isEnabled = model.enabled set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } @@ -113,7 +116,7 @@ public typealias ButtonAction = (Button) -> () // MARK: - MVMCoreViewProtocol extension Button: MVMCoreViewProtocol { - open func updateView(_ size: CGFloat) {} + open func updateView(_ size: CGFloat) { } /// Will be called only once. open func setupView() { @@ -126,6 +129,7 @@ extension Button: MVMCoreViewProtocol { // MARK: - MVMCoreUIMoleculeViewProtocol extension Button: MVMCoreUIMoleculeViewProtocol { + open func reset() { backgroundColor = .clear } @@ -133,6 +137,7 @@ extension Button: MVMCoreUIMoleculeViewProtocol { // MARK: AppleGuidelinesProtocol extension Button: AppleGuidelinesProtocol { + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return Self.acceptablyOutsideBounds(point: point, bounds: bounds) } diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/BaseControllers/MFViewController+Model.swift index 1ddbd4ab..e70e68f6 100644 --- a/MVMCoreUI/BaseControllers/MFViewController+Model.swift +++ b/MVMCoreUI/BaseControllers/MFViewController+Model.swift @@ -37,7 +37,3 @@ extension MFViewController: MoleculeDelegateProtocol { @objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { } } - -public extension MFViewController { - @objc func parsePageJSON() throws { } -} diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/BaseControllers/MFViewController.h index cd96a07f..38ced354 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.h +++ b/MVMCoreUI/BaseControllers/MFViewController.h @@ -96,6 +96,9 @@ // This view controller should subclass this function and check the load to make sure it has all the needed data. Fills the error object if there are any errors. Returns if we should finish the load or not. - (BOOL)shouldFinishProcessingLoad:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error; +/// Called in newDataBuildScreen. Can override to parse the json into a model object. +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error; + // Sets the screen to use the screen heading. // it is required in device flow, where we are showing greeting name as screen heading, // device details screen heading needs to be updated/refreshed again, if user has changed device nick name diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 09700268..f663193f 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -98,7 +98,7 @@ self.loadObject = loadObject; NSError *parseError = nil; - [self parsePageJSONAndReturnError:&parseError]; + [self parsePageJSON:&parseError]; if (parseError) { if (error) { MVMCoreErrorObject *errorObject = [MVMCoreErrorObject createErrorObjectForNSError:parseError location:[[MVMCoreLoadHandler sharedGlobal] errorLocationForRequest:loadObject]]; @@ -112,6 +112,10 @@ return [MFViewController verifyRequiredModulesLoadedForLoadObject:loadObject error:error]; } +- (void)parsePageJSON:(NSError * _Nullable * _Nullable)error { + +} + // Sets the screen to use the screen heading. // it is required in device flow, where we are showing greeting name as screen heading, // device details screen heading needs to be updated/refreshed again, if user has changed device nick name @@ -261,7 +265,7 @@ - (BOOL)newPageLoaded:(nonnull NSDictionary *)page { self.loadObject.pageJSON = page; NSError *parseError = nil; - [self parsePageJSONAndReturnError:&parseError]; + [self parsePageJSON:&parseError]; return YES; } diff --git a/MVMCoreUI/Categories/UIColor+Extension.swift b/MVMCoreUI/Categories/UIColor+Extension.swift index 55a10c03..94bf780d 100644 --- a/MVMCoreUI/Categories/UIColor+Extension.swift +++ b/MVMCoreUI/Categories/UIColor+Extension.swift @@ -12,24 +12,52 @@ public typealias ColorHexTuple = (uiColor: UIColor, hex: String) extension UIColor { + //-------------------------------------------------- + // MARK: - Convenience Dictionary + //-------------------------------------------------- /// Dictionary to access brand approved colors by name. public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"), "white": (.mvmWhite, "#FFFFFF"), "red": (.mvmRed, "#D52B1E"), - "orange": (.mvmOrange, "#CC4D0F"), - "green": (.mvmGreen, "#008631"), - "blue": (.mvmBlue, "#007AB8"), - "blueGradient": (.mvmBlueGradient, "#007AB8"), + "pink": (.mvmPink, "#D90368"), + "pink33": (.mvmPink33, "#F2ABCD"), + "pink66": (.mvmPink66, "#E6589B"), + "pinkShade1": (.mvmPinkShade1, "#B31C63"), + "pinkShade2": (.mvmPinkShade2, "#830842"), + "purple": (.mvmPurple, "#8C00AC"), + "purple33": (.mvmPurple33, "#D9ABE4"), + "purple66": (.mvmPurple66, "#B356C8"), + "purpleShade1": (.mvmPurpleShade1, "#6C177F"), + "purpleShade2": (.mvmPurpleShade2, "#4A0E58"), + "green": (.mvmGreen, "#008330"), + "green33": (.mvmGreen33, "#ABE4BF"), + "green66": (.mvmGreen66, "#57C880"), + "greenShade1": (.mvmGreenShade1, "#178437"), + "greenShade2": (.mvmGreenShade2, "#0F5B25"), + "orange": (.mvmOrange, "#ED7000"), + "orange66": (.mvmOrange66, "#F3A157"), + "orange33": (.mvmOrange33, "#F9D0AB"), + "orangeShade1": (.mvmOrangeShade1, "#CB5F00"), + "orangeShade2": (.mvmOrangeShade2, "#984700"), + "orangeAA": (.mvmOrangeAA, "#CC4D0F"), + "blue": (.mvmBlue, "#0077B4"), + "blue33": (.mvmBlue33, "#57B1DF"), + "blue66": (.mvmBlue66, "#57B1DF"), + "blueShade1": (.mvmBlueShade1, "#136598"), + "blueShade2": (.mvmBlueShade2, "#0B4467"), "yellow": (.mvmYellow, "#FFBC3D"), + "yellow33": (.mvmYellow33, "#FFE9BF"), + "yellow66": (.mvmYellow66, "#FFD37F"), + "yellowShade1": (.mvmYellowShade1, "#CC9630"), + "yellowShade2": (.mvmYellowShade2, "#997126"), "coolGray1": (.mvmCoolGray1, "#F6F6F6"), "coolGray3": (.mvmCoolGray3, "#D8DADA"), "coolGray6": (.mvmCoolGray6, "#747676"), "coolGray10": (.mvmCoolGray10, "#333333"), - "vzupGold": (.vzupGold, "#B89B56"), - "vzupYellow1": (.vzupYellow1, "#F9D542"), - "vzupYellow2": (.vzupYellow2, "#F4CA53"), - "vzupYellow3": (.vzupYellow3, "#CC9B2D")] + "upGold1": (.vzupGold1, "#F9D542"), + "upGold2": (.vzupGold2, "#F4CA53"), + "upGold3": (.vzupGold3, "#CC9B2D")] //-------------------------------------------------- // MARK: - Brand @@ -41,24 +69,134 @@ extension UIColor { /// HEX: #FFFFFF public static let mvmWhite = UIColor.white + //-------------------------------------------------- + // MARK: - Red + //-------------------------------------------------- + /// HEX: #D52B1E public static let mvmRed = UIColor.color8Bits(red: 213, green: 43, blue: 30) + //-------------------------------------------------- + // MARK: - Pink + //-------------------------------------------------- + + /// HEX: #D90368 + public static let mvmPink = UIColor.color8Bits(red: 217, green: 3, blue: 104) + + /// HEX: #F2ABCD + public static let mvmPink33 = UIColor.color8Bits(red: 242, green: 171, blue: 205) + + /// HEX: #E6589B + public static let mvmPink66 = UIColor.color8Bits(red: 230, green: 88, blue: 155) + + /// HEX: #B31C63 + public static let mvmPinkShade1 = UIColor.color8Bits(red: 179, green: 28, blue: 99) + + /// HEX: #830842 + public static let mvmPinkShade2 = UIColor.color8Bits(red: 131, green: 8, blue: 66) + + //-------------------------------------------------- + // MARK: - Purple + //-------------------------------------------------- + + /// HEX: #8C00AC + public static let mvmPurple = UIColor.color8Bits(red: 140, green: 0, blue: 172) + + /// HEX: #D9ABE4 + public static let mvmPurple33 = UIColor.color8Bits(red: 217, green: 171, blue: 228) + + /// HEX: #B356C8 + public static let mvmPurple66 = UIColor.color8Bits(red: 179, green: 86, blue: 200) + + /// HEX: #6C177F + public static let mvmPurpleShade1 = UIColor.color8Bits(red: 108, green: 23, blue: 127) + + /// HEX: #4A0E58 + public static let mvmPurpleShade2 = UIColor.color8Bits(red: 74, green: 14, blue: 88) + + //-------------------------------------------------- + // MARK: - Orange + //-------------------------------------------------- + + /// HEX: #ED7000 + public static let mvmOrange = UIColor.color8Bits(red: 237, green: 112, blue: 0) + /// HEX: #CC4D0F - public static let mvmOrange = UIColor.color8Bits(red: 204, green: 77, blue: 15) + public static let mvmOrangeAA = UIColor.color8Bits(red: 204, green: 77, blue: 15) - /// HEX: #008631 - public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 49) + /// HEX: #F9D0AB + public static let mvmOrange33 = UIColor.color8Bits(red: 249, green: 208, blue: 171) - /// HEX: #007AB8 - public static let mvmBlue = UIColor.color8Bits(red: 0, green: 122, blue: 184) + /// HEX: #F3A157 + public static let mvmOrange66 = UIColor.color8Bits(red: 243, green: 161, blue: 87) - /// HEX: #007AB8 - public static let mvmBlueGradient = UIColor.color8Bits(red: 0, green: 122, blue: 184) + /// HEX: #CB5F00 + public static let mvmOrangeShade1 = UIColor.color8Bits(red: 203, green: 95, blue: 0) + + /// HEX: #984700 + public static let mvmOrangeShade2 = UIColor.color8Bits(red: 152, green: 71, blue: 0) + + //-------------------------------------------------- + // MARK: - Green + //-------------------------------------------------- + + /// HEX: #008330 + public static let mvmGreen = UIColor.color8Bits(red: 0, green: 134, blue: 48) + + /// HEX: #ABE4BF + public static let mvmGreen33 = UIColor.color8Bits(red: 171, green: 228, blue: 191) + + /// HEX: #57C880 + public static let mvmGreen66 = UIColor.color8Bits(red: 87, green: 200, blue: 128) + + /// HEX: #178437 + public static let mvmGreenShade1 = UIColor.color8Bits(red: 23, green: 132, blue: 55) + + /// HEX: #0F5B25 + public static let mvmGreenShade2 = UIColor.color8Bits(red: 15, green: 91, blue: 37) + + //-------------------------------------------------- + // MARK: - Blue + //-------------------------------------------------- + + /// HEX: #0077B4 + public static let mvmBlue = UIColor.color8Bits(red: 0, green: 119, blue: 180) + + /// HEX: #57B1DF + public static let mvmBlue33 = UIColor.color8Bits(red: 87, green: 177, blue: 223) + + /// HEX: #57B1DF + public static let mvmBlue66 = UIColor.color8Bits(red: 87, green: 177, blue: 223) + + /// HEX: #136598 + public static let mvmBlueShade1 = UIColor.color8Bits(red: 19, green: 101, blue: 152) + + /// HEX: #0B4467 + public static let mvmBlueShade2 = UIColor.color8Bits(red: 11, green: 68, blue: 103) + + //-------------------------------------------------- + // MARK: - Yellow + //-------------------------------------------------- /// HEX: #FFBC3D public static let mvmYellow = UIColor.color8Bits(red: 255, green: 188, blue: 61) + /// HEX: #FFE9BF + public static let mvmYellow33 = UIColor.color8Bits(red: 255, green: 233, blue: 191) + + /// HEX: #FFD37F + public static let mvmYellow66 = UIColor.color8Bits(red: 255, green: 211, blue: 127) + + /// HEX: #CC9630 + public static let mvmYellowShade1 = UIColor.color8Bits(red: 204, green: 150, blue: 48) + + /// HEX: #997126 + public static let mvmYellowShade2 = UIColor.color8Bits(red: 153, green: 113, blue: 38) + + //-------------------------------------------------- + // MARK: - Gray + //-------------------------------------------------- + /// HEX: #F6F6F6 public static let mvmCoolGray1 = UIColor.grayscale(rgb: 246) @@ -75,17 +213,14 @@ extension UIColor { // MARK: - VZ UP Brand //-------------------------------------------------- - /// HEX: #B89B56 - public static let vzupGold = UIColor.color8Bits(red: 184, green: 155, blue: 68) - /// HEX: #F9D542 - public static let vzupYellow1 = UIColor.color8Bits(red: 249, green: 213, blue: 66) + public static let vzupGold1 = UIColor.color8Bits(red: 249, green: 213, blue: 66) /// HEX: #F4CA53 - public static let vzupYellow2 = UIColor.color8Bits(red: 244, green: 202, blue: 83) + public static let vzupGold2 = UIColor.color8Bits(red: 244, green: 202, blue: 83) /// HEX: #CC9B2D - public static let vzupYellow3 = UIColor.color8Bits(red: 204, green: 155, blue: 45) + public static let vzupGold3 = UIColor.color8Bits(red: 204, green: 155, blue: 45) //-------------------------------------------------- // MARK: - Functions diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.h b/MVMCoreUI/Categories/UIColor+MFConvenience.h index 4a51a13b..c3c78c7a 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.h +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.h @@ -21,6 +21,7 @@ + (nonnull UIColor *)mfLightSilver; + (nonnull UIColor *)mfDarkSilver; + (nonnull UIColor *)mfTomatoRed; ++ (nonnull UIColor *)mvmOrange; + (nonnull UIColor *)mfPumpkinColor; + (nonnull UIColor *)mfShamrock; + (nonnull UIColor *)mfCerulean; diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.m b/MVMCoreUI/Categories/UIColor+MFConvenience.m index e56d89bc..6ff8f70f 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.m +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.m @@ -37,7 +37,6 @@ return [UIColor mfColor8bitsWithRed:198 green:197 blue:197 alpha:1.0]; } - + (nonnull UIColor *)mfPrimaryButtonHighlightBlackColor { return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.0]; } @@ -54,6 +53,10 @@ return [UIColor mfColor8bitsWithRed:204 green:77 blue:15 alpha:1.0]; } ++ (nonnull UIColor *)mvmOrange { + return [UIColor mfColor8bitsWithRed:237 green:112 blue:0 alpha:1.0]; +} + + (nonnull UIColor *)mfShamrock { return [UIColor mfColor8bitsWithRed:0 green:134 blue:49 alpha:1.0]; } diff --git a/MVMCoreUI/Categories/UIContentMode+Extension.swift b/MVMCoreUI/Categories/UIContentMode+Extension.swift new file mode 100644 index 00000000..19cf523b --- /dev/null +++ b/MVMCoreUI/Categories/UIContentMode+Extension.swift @@ -0,0 +1,98 @@ +// +// UIContentMode+Extension.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/17/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +enum ContentModeError: Error { + case notAContentMode +} + +extension UIView.ContentMode: RawRepresentable { + + init?(rawValue: String) { + switch rawValue { + case "scaleToFill": + self = .scaleToFill + case "scaleAspectFit": + self = .scaleAspectFit + case "scaleAspectFill": + self = .scaleAspectFill + case "redraw": + self = .redraw + case "center": + self = .center + case "top": + self = .top + case "bottom": + self = .bottom + case "left": + self = .left + case "right": + self = .right + case "topLeft": + self = .topLeft + case "topRight": + self = .topRight + case "bottomLeft": + self = .bottomLeft + case "bottomRight": + self = .bottomRight + default: + return nil + } + } + + var rawValueString: String { + switch self { + case .scaleToFill: + return "scaleToFill" + case .scaleAspectFit: + return "scaleAspectFit" + case .scaleAspectFill: + return "scaleAspectFill" + case .redraw: + return "redraw" + case .center: + return "center" + case .top: + return "top" + case .bottom: + return "bottom" + case .left: + return "left" + case .right: + return "right" + case .topLeft: + return "topLeft" + case .topRight: + return "topRight" + case .bottomLeft: + return "bottomLeft" + case .bottomRight: + return "bottomRight" + @unknown default: + return "" + } + } +} + +extension UIView.ContentMode: Codable { + public init(from decoder: Decoder) throws { + let typeContainer = try decoder.singleValueContainer() + let string = try typeContainer.decode(String.self) + guard let mode = UIView.ContentMode(rawValue: string) else { + throw ContentModeError.notAContentMode + } + self = mode + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(rawValueString) + } +} diff --git a/MVMCoreUI/CustomPrimitives/Color.swift b/MVMCoreUI/CustomPrimitives/Color.swift index a34fbd45..165fa8ad 100644 --- a/MVMCoreUI/CustomPrimitives/Color.swift +++ b/MVMCoreUI/CustomPrimitives/Color.swift @@ -49,7 +49,7 @@ public final class Color: Codable { // MARK: - Class Initializers //-------------------------------------------------- - init(uiColor: UIColor) { + public init(uiColor: UIColor) { self.uiColor = uiColor hex = UIColor.hexString(for: uiColor) ?? "" determineRGBA() diff --git a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift index 1ec0d13c..cec7b90a 100644 --- a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift @@ -3,7 +3,7 @@ import Foundation public protocol MoleculeModelProtocol: Model { var moleculeName: String? { get } - var backgroundColor: Color? { get set} + var backgroundColor: Color? { get set } } public extension MoleculeModelProtocol { diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift new file mode 100644 index 00000000..2bfbc321 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -0,0 +1,69 @@ +// +// ListRightVariablePayments.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ListRightVariablePayments: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + + let leftLabel = Label.commonLabelB1(true) + let rightImage = MFLoadImageView(pinnedEdges: .all) + let stack = Stack(frame: .zero) + + //----------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + stack.updateView(size) + } + + override open func setupView() { + super.setupView() + guard leftLabel.superview == nil else { + return + } + stack.translatesAutoresizingMaskIntoConstraints = false + stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] + contentView.addSubview(stack) + containerHelper.constrainView(stack) + } + + //---------------------------------------------------- + // MARK: - Molecule + //------------------------------------------------------ + override open func reset() { + super.reset() + stack.reset() + } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ListRightVariablePaymentsModel else { return } + leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) + rightImage.setWithModel(model.image, delegateObject, additionalData) + + // Create a stack model to use for the internal stack and set the alignment of label and image + let leftLabel = StackItemModel() + leftLabel.horizontalAlignment = .leading + let rightImage = StackItemModel() + rightImage.horizontalAlignment = .fill + let stackModel = StackModel(molecules: [leftLabel,rightImage]) + stackModel.axis = .horizontal + stack.model = stackModel + stack.restack() + } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 65 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift new file mode 100644 index 00000000..a8c6ff80 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -0,0 +1,52 @@ +// +// ListRightVariablePaymentsModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtocol { + + public static var identifier: String = "listRVImg" + public var image: ImageViewModel + public var leftLabel: LabelModel + + public init(image: ImageViewModel, leftLabel: LabelModel) { + self.leftLabel = leftLabel + self.image = image + super.init() + } + + static func createPayPalImage() -> ImageViewModel { + let image = ImageViewModel(image: "imageName_PayPal_logo") + image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI() + image.width = 70.0 + image.height = 18.0 + image.contentMode = .scaleAspectFit + return image + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case leftLabel + case image + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) + image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) ?? ListRightVariablePaymentsModel.createPayPalImage() + 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(image, forKey: .image) + } +} diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift index 42acd2f0..1e5c7dce 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift @@ -11,6 +11,7 @@ import Foundation @objcMembers public class DoughnutChartModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChart" + public var moleculeName: String? = DoughnutChartModel.identifier public var title: LabelModel? public var subtitle: LabelModel? public var sections: [DoughnutChartItemModel] @@ -24,6 +25,7 @@ import Foundation @objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChartItem" + public var moleculeName: String? = DoughnutChartItemModel.identifier public var label: LabelModel @Percent public var percent: CGFloat public var color: Color diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index 4966ce58..7f3d52dc 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -10,6 +10,7 @@ import Foundation public struct ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" + public var moleculeName: String? = ImageHeadlineBodyModel.identifier public var backgroundColor: Color? public var image: ImageViewModel public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift index f45c771d..8b69c590 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -22,6 +22,7 @@ public class TabsModel: MoleculeModelProtocol { case backgroundColor case selectedColor case selectedIndex + case moleculeName } public init(with tabs: [LabelModel]) { @@ -42,6 +43,7 @@ public class TabsModel: MoleculeModelProtocol { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) try container.encode(backgroundColor, forKey: .backgroundColor) try container.encode(selectedColor, forKey: .selectedColor) diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 5938692b..057203e9 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -21,6 +21,11 @@ public class TwoButtonViewModel: MoleculeModelProtocol { case secondaryButton } + public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { + self.primaryButton = primaryButton + self.secondaryButton = secondaryButton + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) diff --git a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift index f2c88e9b..9fc218a7 100644 --- a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift @@ -14,7 +14,6 @@ import Foundation public var backgroundColor: Color? public var peakingUI: Bool? public var peakingArrowColor: Color? - public var moleculeName: String? private enum CodingKeys: String, CodingKey { case moleculeName @@ -25,7 +24,6 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI) peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor) diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift index 4731ef34..dc01fd11 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift @@ -25,7 +25,7 @@ import Foundation public override init(with moleculeModel: MoleculeModelProtocol) { super.init(with: moleculeModel) } - + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index 2058353c..b7d1a269 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -10,6 +10,7 @@ import Foundation @objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol { public static var identifier: String = "simpleStackItem" + public var moleculeName: String? = StackItemModel.identifier public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? diff --git a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index a397c1a1..9dbf53c0 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -10,6 +10,7 @@ import Foundation public struct ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" + public var moleculeName: String? = ActionDetailWithImageModel.identifier public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel public var image: ImageViewModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift index f4b67216..bb3e6f17 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift @@ -28,6 +28,7 @@ public class CornerLabelsModel: MoleculeModelProtocol { case bottomLeftLabel case bottomRightLabel case molecule + case moleculeName } required public init(from decoder: Decoder) throws { @@ -48,5 +49,6 @@ public class CornerLabelsModel: MoleculeModelProtocol { try container.encodeIfPresent(topRightLabel, forKey: .topRightLabel) try container.encodeIfPresent(bottomLeftLabel, forKey: .bottomLeftLabel) try container.encodeIfPresent(bottomRightLabel, forKey: .bottomRightLabel) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index 5ce04f9c..aad8ec06 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -9,6 +9,7 @@ import Foundation public struct HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" + public var moleculeName: String? = HeadlineBodyLinkToggleModel.identifier public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index dd7c2b1c..bb3391a6 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -11,6 +11,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" + public var moleculeName: String? = HeadlineBodyToggleModel.identifier open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift index 7ed5857e..526ac6b9 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift @@ -10,7 +10,13 @@ import Foundation public class LabelToggleModel: MoleculeModelProtocol { public static var identifier: String = "labelToggle" + public var moleculeName: String? = LabelToggleModel.identifier public var backgroundColor: Color? public var label: LabelModel public var toggle: ToggleModel + + init(_ label: LabelModel, _ toggle: ToggleModel) { + self.label = label + self.toggle = toggle + } } diff --git a/MVMCoreUI/Molecules/ScrollerModel.swift b/MVMCoreUI/Molecules/ScrollerModel.swift index f92fe13b..91dc2e1c 100644 --- a/MVMCoreUI/Molecules/ScrollerModel.swift +++ b/MVMCoreUI/Molecules/ScrollerModel.swift @@ -10,5 +10,6 @@ import UIKit public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol { public static var identifier: String = "scroller" + public var moleculeName: String? = ScrollerModel.identifier public var backgroundColor: Color? } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index e9341535..81a38111 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -11,7 +11,7 @@ import Foundation struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { static var identifier: String = "eyebrowHeadlineBodyLink" var backgroundColor: Color? - + var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier public var eyeBrow: LabelModel? public var headline: LabelModel? public var body: LabelModel? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 74e85ea9..ec97fda0 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -10,6 +10,7 @@ import Foundation public struct HeadlineBodyButtonModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyButton" + public var moleculeName: String? = HeadlineBodyButtonModel.identifier public var backgroundColor: Color? public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index 9eae8e03..27f0d670 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -10,6 +10,7 @@ import Foundation public struct HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" + public var moleculeName: String? = HeadlineBodyLinkModel.identifier public var headlineBody: HeadlineBodyModel public var link: LinkModel public var backgroundColor: Color? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 1fbe98e7..d7a08091 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers public class HeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "headlineBody" - public var moleculeName: String? + public var moleculeName: String? = HeadlineBodyModel.identifier public var headline: LabelModel? public var body: LabelModel? public var style: String? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift index caa00021..c66f27b8 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeModel.swift @@ -38,5 +38,6 @@ public class StringAndMoleculeModel: MoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(string, forKey: .string) try container.encodeModel(molecule, forKey: .molecule) + try container.encode(moleculeName, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Organisms/CarouselModel.swift b/MVMCoreUI/Organisms/CarouselModel.swift index e43e6caa..79693135 100644 --- a/MVMCoreUI/Organisms/CarouselModel.swift +++ b/MVMCoreUI/Organisms/CarouselModel.swift @@ -53,7 +53,7 @@ import UIKit public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(moleculeName, forKey: .moleculeName) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(molecules, forKey: .molecules) try container.encode(spacing, forKey: .spacing) diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index 741946c5..8d670efb 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -45,5 +45,6 @@ import Foundation try container.encodeIfPresent(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/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index 7bdccc8e..5b9592cc 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -22,8 +22,7 @@ @"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], @"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], - @"threeLayer" : - [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]] + @"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]] } mutableCopy]; }); return viewControllerMapping; diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 4b4ee536..ac7375d7 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -72,7 +72,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) // List items MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self) diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json new file mode 100644 index 00000000..b4c381b8 --- /dev/null +++ b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo@2x.jpeg", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "paypal_horiz_logo@3x.jpeg", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..95113ebf4001cf2eed20fbe23530dea3d1e475a9 GIT binary patch literal 1826 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 literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg b/MVMCoreUI/SupportingFiles/Media.xcassets/imageName_PayPal_logo.imageset/paypal_horiz_logo@3x.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..cbd78652ce3bdb9fb3e62b4b4522b2f40b1556a2 GIT binary patch literal 4606 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 literal 0 HcmV?d00001 diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 01d0a5e6..9741f110 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -23,8 +23,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Computed Properties //-------------------------------------------------- - @objc public override func parsePageJSON() throws { - try parseTemplateJSON() + open override func parsePageJSON(_ error: NSErrorPointer) { + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 03d21c6b..ef7a470d 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -12,8 +12,12 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? - public override func parsePageJSON() throws { - try parseTemplateJSON() + open override func parsePageJSON(_ error: NSErrorPointer) { + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 785d1055..eb822279 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -11,8 +11,13 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { public var templateModel: ThreeLayerPageTemplateModel? - @objc public override func parsePageJSON() throws { - try parseTemplateJSON() + + open override func parsePageJSON(_ error: NSErrorPointer) { + do { + try parseTemplateJSON() + } catch let parseError { + error?.pointee = parseError as NSError + } } override open func viewDidLoad() { diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index 947e6ffc..d0a027b3 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -108,7 +108,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; - (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type { if ([type isEqualToString:ValueTypeError]) { - return [UIColor mfPumpkinColor]; + return [UIColor mvmOrange]; } else { return [UIColor mfShamrock]; } From d7a13704f2aadc4329b45fc523c8aefeb6399303 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 20 Feb 2020 15:56:02 +0530 Subject: [PATCH 64/96] Reference files --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++++++ MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift | 1 + 2 files changed, 9 insertions(+) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 281a0672..6fed15b6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -96,6 +96,8 @@ 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; + 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; + 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; @@ -422,6 +424,8 @@ 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; + 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; + 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; @@ -985,6 +989,8 @@ D22B38EB23F4E0AE00490EF6 /* LeftVariable */ = { isa = PBXGroup; children = ( + 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, + 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, ); @@ -1652,6 +1658,7 @@ DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */, 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */, + 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */, 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */, 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, @@ -1777,6 +1784,7 @@ D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, + 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ac7375d7..b3bfd241 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -72,6 +72,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) // List items From eacaff5a104fe372871694ad196902fbd55a2243 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Thu, 20 Feb 2020 17:58:50 +0530 Subject: [PATCH 65/96] changing eybrow variable as per contract --- .../VerticalCombinationViews/EyebrowHeadlineBodyLink.swift | 2 +- .../VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index ff8e6cfa..76eb447f 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -47,7 +47,7 @@ import UIKit // MARK:- ModelMoleculeViewProtocol open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) - eyebrow.setWithModel(casteModel?.eyeBrow, delegateObject, additionalData) + eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData) headline.setWithModel(casteModel?.headline, delegateObject, additionalData) body.setWithModel(casteModel?.body, delegateObject, additionalData) link.setWithModel(casteModel?.link, delegateObject, additionalData) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 81a38111..e63d69e2 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -12,7 +12,7 @@ struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { static var identifier: String = "eyebrowHeadlineBodyLink" var backgroundColor: Color? var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier - public var eyeBrow: LabelModel? + public var eyebrow: LabelModel? public var headline: LabelModel? public var body: LabelModel? public var link: LinkModel? From 3f1e37c8783e571336ac179f8c95f388373faf19 Mon Sep 17 00:00:00 2001 From: Prateek Arora Date: Thu, 20 Feb 2020 20:45:20 +0530 Subject: [PATCH 66/96] Using stack as per review comments --- .../ListRVWheel.swift | 59 +++++++------------ .../ListRVWheelModel.swift | 11 +++- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift index 47c77ed8..51f1133f 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift @@ -12,14 +12,13 @@ import Foundation let wheel = GraphView(frame: .zero) let leftLabel = Label(frame: .zero) let rightLabel = Label(frame: .zero) + let stack = Stack(frame: .zero) //------------------------------------------------- // MARK: - View Cycle //------------------------------------------------- open override func updateView(_ size: CGFloat) { super.updateView(size) - wheel.updateView(size) - leftLabel.updateView(size) - rightLabel.updateView(size) + stack.updateView(size) } //------------------------------------------------- @@ -27,39 +26,10 @@ import Foundation //------------------------------------------------- open override func setupView() { super.setupView() - guard leftLabel.superview == nil else { - return - } - contentView.addSubview(wheel) - contentView.addSubview(leftLabel) - contentView.addSubview(rightLabel) - NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) - contentView.translatesAutoresizingMaskIntoConstraints = false - - //------------------------------------------------- - // MARK: - Constraining - //------------------------------------------------- - self.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - leftLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), - leftLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - leftLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - leftLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.3) - ]) - NSLayoutConstraint.activate([ - wheel.topAnchor.constraint(equalTo: contentView.topAnchor), - wheel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - - let rightLabelTrailing = rightLabel.trailingAnchor.constraint(greaterThanOrEqualTo: contentView.trailingAnchor) - rightLabelTrailing.priority = UILayoutPriority(900) - NSLayoutConstraint.activate([ - rightLabelTrailing, - rightLabel.leadingAnchor.constraint(equalTo: wheel.trailingAnchor), - rightLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.32), - rightLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - rightLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) + stack.translatesAutoresizingMaskIntoConstraints = false + stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)] + contentView.addSubview(stack) + containerHelper.constrainView(stack) } //------------------------------------------------- // MARK: - MVMCoreUIMoleculeViewProtocol @@ -70,6 +40,19 @@ import Foundation leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) wheel.setWithModel(model.wheel, delegateObject, additionalData) + + // Create a stack model to use for the internal stack and set the alignment of models + let leftHeadlineBodyAlignment = StackItemModel(percent: 55) + leftHeadlineBodyAlignment.horizontalAlignment = .leading + + let centerHeadLineBodyAlignment = StackItemModel(percent: 20) + centerHeadLineBodyAlignment.horizontalAlignment = .trailing + let rightHeadLineBodyAlignment = StackItemModel(percent: 25) + rightHeadLineBodyAlignment.horizontalAlignment = .trailing + let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment]) + stackModel.axis = .horizontal + stack.model = stackModel + stack.restack() } //------------------------------------------------- @@ -77,9 +60,7 @@ import Foundation //------------------------------------------------- open override func reset() { super.reset() - leftLabel.reset() - rightLabel.reset() - wheel.reset() + stack.reset() } public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 43 diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift index ec856bb1..ab5f3c2a 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift @@ -7,8 +7,7 @@ // import Foundation -public class ListRVWheelModel:MoleculeModelProtocol { - public var backgroundColor: Color? +public class ListRVWheelModel:ListItemModel,MoleculeModelProtocol { public static var identifier: String = "listRVWheel" public var leftLabel: LabelModel? public var rightLabel: LabelModel? @@ -17,20 +16,26 @@ public class ListRVWheelModel:MoleculeModelProtocol { self.leftLabel = leftLabel self.rightLabel = rightLabel self.wheel = wheel + super.init() } + private enum CodingKeys: String,CodingKey { case moleculeName case leftLabel case rightLabel case wheel } + required public init(from decoder: Decoder) throws { 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.decode(CircleProgressModel.self, forKey: .wheel) + 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.encode(ListRVWheelModel.identifier, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) From 7d8f850e638c18ab9cf30d4eb9a08692c911713e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 20 Feb 2020 14:35:35 -0500 Subject: [PATCH 67/96] providing new molecule --- MVMCoreUI.xcodeproj/project.pbxproj | 20 ++++- .../Atoms/Buttons/Link/ExternalLink.swift | 73 +++++++++++++++++++ .../Buttons/Link/ExternalLinkModel.swift | 16 ++++ MVMCoreUI/Atoms/Buttons/{ => Link}/Link.swift | 2 + .../Atoms/Buttons/{ => Link}/LinkModel.swift | 4 +- .../Buttons/MFCustomButton+ActionModel.swift | 2 + ...maryButton+MoleculeProtocolExtension.swift | 7 +- .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 8 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift create mode 100644 MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift rename MVMCoreUI/Atoms/Buttons/{ => Link}/Link.swift (99%) rename MVMCoreUI/Atoms/Buttons/{ => Link}/LinkModel.swift (97%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 281a0672..480d2219 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -94,6 +94,8 @@ 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 */; }; + 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */; }; + 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; @@ -420,6 +422,8 @@ 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 = ""; }; + 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLink.swift; sourceTree = ""; }; + 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLinkModel.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; @@ -755,6 +759,17 @@ path = Views; sourceTree = ""; }; + 0AE98BAD23FEF92B004C5109 /* Link */ = { + isa = PBXGroup; + children = ( + D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, + C07065C32395677300FBF997 /* Link.swift */, + 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */, + 0AE98BAE23FEF956004C5109 /* ExternalLink.swift */, + ); + path = Link; + sourceTree = ""; + }; 946EE1B5237B663A0036751F /* Extensions */ = { isa = PBXGroup; children = ( @@ -1239,12 +1254,11 @@ D29DF16821E69E1F003B2FB9 /* Buttons */ = { isa = PBXGroup; children = ( + 0AE98BAD23FEF92B004C5109 /* Link */, 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */, DBC4391A224421A0001AB423 /* CaretLink.swift */, D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */, D2E2A99E23E07F8A000B42E6 /* PillButton.swift */, - D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, - C07065C32395677300FBF997 /* Link.swift */, D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */, D28A837623C79FC600DFE4FC /* MFCustomButton+ActionModel.swift */, ); @@ -1679,6 +1693,7 @@ C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, + 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, @@ -1780,6 +1795,7 @@ 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, + 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift new file mode 100644 index 00000000..3f0aa5d6 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -0,0 +1,73 @@ +// +// ExternalLink.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 2/20/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + + +open class ExternalLink: Link { + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + + guard let model = model as? ExternalLinkModel else { return } + + } +} + +// MARK: - MVMCoreViewProtocol +extension ExternalLink { + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + } + + public override func setupView() { + super.setupView() + + let imageView = UIImageView(image: MVMCoreUIUtility.imageNamed("externalLink")) + imageView.contentMode = .scaleAspectFit + imageView.translatesAutoresizingMaskIntoConstraints = false + + addSubview(imageView) + + imageView.heightAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true + imageView.widthAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true + + imageView.leadingAnchor.constraint(equalTo: titleLabel!.trailingAnchor, constant: PaddingOne).isActive = true + trailingAnchor.constraint(greaterThanOrEqualTo: imageView.trailingAnchor).isActive = true + + imageView.bottomAnchor.constraint(equalTo: titleLabel!.lastBaselineAnchor).isActive = true + } +} + +/* + static func getTextAttachmentFrom(url: String, dimension: CGFloat, label: Label) -> NSTextAttachment { + + let dimension = round(dimension * 0.8) + + let imageAttachment = NSTextAttachment() + imageAttachment.bounds = CGRect(x: 0, y: 0, width: dimension, height: dimension) + + DispatchQueue.global(qos: .default).async { + + guard let url = URL(string: url), + let data = try? Data(contentsOf: url) + else { return } + + DispatchQueue.main.sync { + imageAttachment.image = UIImage(data: data) + label.setNeedsDisplay() + } + } + + return imageAttachment + } + */ diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift new file mode 100644 index 00000000..a7fc5211 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift @@ -0,0 +1,16 @@ +// +// ExternalLinkModel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 2/20/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +class ExternalLinkModel: LinkModel { + + override public class var identifier: String { + return "externalLink" + } +} diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link/Link.swift similarity index 99% rename from MVMCoreUI/Atoms/Buttons/Link.swift rename to MVMCoreUI/Atoms/Buttons/Link/Link.swift index 5dbbed16..a0e2583c 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/Link.swift @@ -42,7 +42,9 @@ import UIKit public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? LinkModel else { return } + setTitle(model.title, for: .normal) setTitleColor(model.textColor.uiColor, for: .normal) setTitleColor(model.disabledColor.uiColor, for: .disabled) diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift similarity index 97% rename from MVMCoreUI/Atoms/Buttons/LinkModel.swift rename to MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift index 7094a038..5a58decd 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift @@ -13,7 +13,9 @@ public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "link" + public class var identifier: String { + return "link" + } public var backgroundColor: Color? public var title: String diff --git a/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift b/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift index d008a7fb..84f4be33 100644 --- a/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift +++ b/MVMCoreUI/Atoms/Buttons/MFCustomButton+ActionModel.swift @@ -9,7 +9,9 @@ import Foundation public extension MFCustomButton { + func set(with action: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + buttonDelegate = delegateObject?.buttonDelegate add({ [weak self] sender in guard let self = self else { return } diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift index 39b015ae..62b16927 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift @@ -10,8 +10,11 @@ import Foundation // temporary until link is finished extension PrimaryButton: ModelMoleculeViewProtocol { - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + + public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let model = model as? ButtonModel else { return } + setTitle(model.title, for: .normal) backgroundColor = model.backgroundColor?.uiColor @@ -23,7 +26,6 @@ extension PrimaryButton: ModelMoleculeViewProtocol { FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) } - if let style = model.style { switch style { case .primary: @@ -32,6 +34,7 @@ extension PrimaryButton: ModelMoleculeViewProtocol { setAsSecondaryCustom() } } + if let size = model.size { switch size { case .standard: diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ac7375d7..329347b1 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -29,6 +29,7 @@ import Foundation // Buttons MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ExternalLink.self, viewModelClass: ExternalLinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretLink.self, viewModelClass: CaretLinkModel.self) From ae62d161fd5804edc69e9495d0ac91b2622e28d0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 20 Feb 2020 18:33:03 -0500 Subject: [PATCH 68/96] code improvements --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +-- .../List/RightVariable}/ListRVWheel.swift | 33 +++++++++++-------- .../RightVariable}/ListRVWheelModel.swift | 15 +++++---- 3 files changed, 29 insertions(+), 23 deletions(-) rename MVMCoreUI/Molecules/{VerticalCombinationViews => DesignedComponents/List/RightVariable}/ListRVWheel.swift (72%) rename MVMCoreUI/Molecules/{VerticalCombinationViews => DesignedComponents/List/RightVariable}/ListRVWheelModel.swift (75%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8c9bb884..6e224df7 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -795,6 +795,8 @@ children = ( AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */, AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, + C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, + C7F8012023E8303200396FBD /* ListRVWheel.swift */, ); path = RightVariable; sourceTree = ""; @@ -903,8 +905,6 @@ C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */, D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */, 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, - C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, - C7F8012023E8303200396FBD /* ListRVWheel.swift */, ); path = VerticalCombinationViews; sourceTree = ""; diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift similarity index 72% rename from MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index 51f1133f..e9e09639 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -7,12 +7,12 @@ // import Foundation -@objcMembers public class ListRVWheel: TableViewCell { - +@objcMembers open class ListRVWheel: TableViewCell { let wheel = GraphView(frame: .zero) - let leftLabel = Label(frame: .zero) - let rightLabel = Label(frame: .zero) + let leftLabel = Label.commonLabelB1(true) + let rightLabel = Label.commonLabelB2(true) let stack = Stack(frame: .zero) + //------------------------------------------------- // MARK: - View Cycle //------------------------------------------------- @@ -26,13 +26,15 @@ import Foundation //------------------------------------------------- open override func setupView() { super.setupView() + rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)] contentView.addSubview(stack) containerHelper.constrainView(stack) } + //------------------------------------------------- - // MARK: - MVMCoreUIMoleculeViewProtocol + // MARK: - ModelMoleculeViewProtocol //------------------------------------------------- public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) @@ -42,14 +44,14 @@ import Foundation wheel.setWithModel(model.wheel, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of models - let leftHeadlineBodyAlignment = StackItemModel(percent: 55) - leftHeadlineBodyAlignment.horizontalAlignment = .leading - - let centerHeadLineBodyAlignment = StackItemModel(percent: 20) - centerHeadLineBodyAlignment.horizontalAlignment = .trailing - let rightHeadLineBodyAlignment = StackItemModel(percent: 25) - rightHeadLineBodyAlignment.horizontalAlignment = .trailing - let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment]) + let leftLabelStackItem = StackItemModel() + leftLabelStackItem.horizontalAlignment = .leading + let wheelStackItem = StackItemModel() + wheelStackItem.horizontalAlignment = .fill + let rightLabelStackItem = StackItemModel() + rightLabelStackItem.horizontalAlignment = .fill + rightLabelStackItem.spacing = 4 + let stackModel = StackModel(molecules: [leftLabelStackItem,wheelStackItem,rightLabelStackItem]) stackModel.axis = .horizontal stack.model = stackModel stack.restack() @@ -61,8 +63,11 @@ import Foundation open override func reset() { super.reset() stack.reset() + leftLabel.styleB1(true) + rightLabel.styleB2(true) } + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 43 + return 70 } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift similarity index 75% rename from MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift rename to MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift index ab5f3c2a..3831f5c7 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/ListRVWheelModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift @@ -7,19 +7,20 @@ // import Foundation -public class ListRVWheelModel:ListItemModel,MoleculeModelProtocol { +public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol { public static var identifier: String = "listRVWheel" - public var leftLabel: LabelModel? - public var rightLabel: LabelModel? - public var wheel : CircleProgressModel? - init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) { + public var leftLabel: LabelModel + public var rightLabel: LabelModel + public var wheel : CircleProgressModel + + public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) { self.leftLabel = leftLabel self.rightLabel = rightLabel self.wheel = wheel super.init() } - private enum CodingKeys: String,CodingKey { + private enum CodingKeys: String, CodingKey { case moleculeName case leftLabel case rightLabel @@ -37,7 +38,7 @@ public class ListRVWheelModel:ListItemModel,MoleculeModelProtocol { public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(ListRVWheelModel.identifier, forKey: .moleculeName) + try container.encode(moleculeName, forKey: .moleculeName) try container.encode(leftLabel, forKey: .leftLabel) try container.encode(rightLabel, forKey: .rightLabel) try container.encode(wheel, forKey: .wheel) From cc5536a8d1c9f255b5912d0e1dba6d670774de40 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 20 Feb 2020 19:07:54 -0500 Subject: [PATCH 69/96] Minor fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 2 +- ...tLeftVariableCheckboxAllTextAndLinks.swift | 26 ++++++++++--------- ...VariableCheckboxAllTextAndLinksModel.swift | 5 ++-- .../EyebrowHeadlineBodyLink.swift | 3 --- .../EyebrowHeadlineBodyLinkModel.swift | 8 +++--- 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 7ed0a2e3..4afd3a24 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -995,8 +995,8 @@ D22B38EB23F4E0AE00490EF6 /* LeftVariable */ = { isa = PBXGroup; children = ( - 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, + 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */, ); diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift index d83e8389..553e6359 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift @@ -9,11 +9,11 @@ import Foundation @objcMembers public class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { - - let checkbox = Checkbox(frame: .zero) - let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) - let stack = Stack(frame: .zero) + public let checkbox = Checkbox(frame: .zero) + public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) + public let stack = Stack(frame: .zero) + // MARK: - View Lifecycle open override func updateView(_ size: CGFloat) { super.updateView(size) stack.updateView(size) @@ -21,20 +21,18 @@ import Foundation override open func setupView() { super.setupView() - guard checkbox.superview == nil else { - return - } - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)] contentView.addSubview(stack) containerHelper.constrainView(stack) } + // MARK:- ModelMoleculeViewProtocol override open func reset() { super.reset() stack.reset() } + // MARK:- MVMCoreUIMoleculeViewProtocol public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return} @@ -42,13 +40,17 @@ import Foundation eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of labels - let checkbox = StackItemModel(percent: 10) - checkbox.horizontalAlignment = .leading - let eyebrowHeadlineBodyLink = StackItemModel(percent: 90) - eyebrowHeadlineBodyLink.horizontalAlignment = .fill + let checkbox = StackItemModel() + checkbox.horizontalAlignment = .fill + let eyebrowHeadlineBodyLink = StackItemModel() + eyebrowHeadlineBodyLink.horizontalAlignment = .leading let stackModel = StackModel(molecules: [checkbox,eyebrowHeadlineBodyLink]) stackModel.axis = .horizontal stack.model = stackModel stack.restack() } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 140 + } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift index 80ab9506..2fb89b1e 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -9,12 +9,11 @@ import Foundation public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { - public static var identifier: String = "listLVCB" public var checkbox: CheckboxModel - var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel - init(checkbox: CheckboxModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { + public init(checkbox: CheckboxModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { self.checkbox = checkbox self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink super.init() diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index 76eb447f..8f206e35 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -21,9 +21,6 @@ import UIKit // MARK: - MFViewProtocol open override func setupView() { super.setupView() - guard stack.superview == nil else { - return - } stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)] addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index e63d69e2..913933d9 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -8,10 +8,10 @@ import Foundation -struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { - static var identifier: String = "eyebrowHeadlineBodyLink" - var backgroundColor: Color? - var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier +public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { + public static var identifier: String = "eyebrowHeadlineBodyLink" + public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier + public var backgroundColor: Color? public var eyebrow: LabelModel? public var headline: LabelModel? public var body: LabelModel? From 47603e7a599ba67c0bf5640cbcb16a40d926c45f Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Fri, 21 Feb 2020 16:58:16 +0530 Subject: [PATCH 70/96] Added ListOneColumnFullWidthTextAllTextAndLinks molecule class and model files. --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++++ ...neColumnFullWidthTextAllTextAndLinks.swift | 74 +++++++++++++++++++ ...umnFullWidthTextAllTextAndLinksModel.swift | 57 ++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 2 + 4 files changed, 149 insertions(+) create mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift create mode 100644 MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 4afd3a24..4f81feab 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -98,6 +98,8 @@ 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; + 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; + 52267A0923FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0823FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; @@ -428,6 +430,8 @@ 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; + 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; + 52267A0823FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; @@ -763,6 +767,15 @@ path = Views; sourceTree = ""; }; + 52267A0523FFE0A900906CBA /* OneColumn */ = { + isa = PBXGroup; + children = ( + 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */, + 52267A0823FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */, + ); + path = OneColumn; + sourceTree = ""; + }; 946EE1B5237B663A0036751F /* Extensions */ = { isa = PBXGroup; children = ( @@ -1006,6 +1019,7 @@ D22B38EC23F4E10700490EF6 /* SectionDividers */ = { isa = PBXGroup; children = ( + 52267A0523FFE0A900906CBA /* OneColumn */, D22B38ED23F4E11100490EF6 /* ThreeColumn */, ); path = SectionDividers; @@ -1672,6 +1686,7 @@ D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, + 52267A0923FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, @@ -1847,6 +1862,7 @@ 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, + 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */, 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift new file mode 100644 index 00000000..9827fed4 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -0,0 +1,74 @@ +// +// ListOneColumnFullWidthTextAllTextAndLinks.swift +// MVMCoreUI +// +// Created by Kruthika KP on 14/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class ListOneColumnFullWidthTextAllTextAndLinks: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + + let stack = Stack(frame: .zero) + let eyebrow = Label.commonLabelB3(true) + let headline = Label.commonLabelH3(true) + let subHeadline = Label.commonLabelB1(true) + let body = Label.commonLabelB2(true) + let link = Link() + + //----------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + stack.updateView(size) + } + + override open func setupView() { + super.setupView() + guard stack.superview == nil else { + return + } + stack.translatesAutoresizingMaskIntoConstraints = false + stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: subHeadline),StackItem(andContain: body),StackItem(andContain: link)] + contentView.addSubview(stack) + containerHelper.constrainView(stack) + } + //---------------------------------------------------- + // MARK: - Molecule + //------------------------------------------------------ + + override open func reset() { + super.reset() + stack.reset() + eyebrow.styleB3(true) + headline.styleH3(true) + subHeadline.styleB1(true) + body.styleB2(true) + } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return} + eyebrow.setWithModel(model.eyebrow, delegateObject, additionalData) + headline.setWithModel(model.headline, delegateObject, additionalData) + subHeadline.setWithModel(model.subHeadline, delegateObject, additionalData) + body.setWithModel(model.body, delegateObject, additionalData) + link.setWithModel(model.link, delegateObject, additionalData) + + let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),StackItemModel(gone: !headline.hasText),StackItemModel(gone: !subHeadline.hasText),StackItemModel(gone: !body.hasText),StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) + stack.model = stackModel + stackModel.spacing = 2 + stack.restack() + } + + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 90 + } +} diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift new file mode 100644 index 00000000..ebc87aa4 --- /dev/null +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift @@ -0,0 +1,57 @@ +// +// ListOneColumnFullWidthTextAllTextAndLinksModel.swift +// MVMCoreUI +// +// Created by Kruthika KP on 14/02/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "list1CTxt" + public var eyebrow: LabelModel? + public var headline : LabelModel? + public var subHeadline: LabelModel? + public var body: LabelModel? + public var link : LinkModel? + + public init(eyebrow:LabelModel, headline: LabelModel, subHeadline: LabelModel, body: LabelModel, link: LinkModel) { + self.eyebrow = eyebrow + self.headline = headline + self.subHeadline = subHeadline + self.body = body + self.link = link + super.init() + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case eyebrow + case headline + case subHeadline + case body + case link + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + eyebrow = try typeContainer.decode(LabelModel.self, forKey: .eyebrow) + headline = try typeContainer.decode(LabelModel.self, forKey: .headline) + subHeadline = try typeContainer.decode(LabelModel.self, forKey: .subHeadline) + body = try typeContainer.decode(LabelModel.self, forKey: .body) + link = try typeContainer.decode(LinkModel.self, forKey: .link) + 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(eyebrow, forKey: .eyebrow) + try container.encode(headline, forKey: .headline) + try container.encode(subHeadline, forKey: .subHeadline) + try container.encode(body, forKey: .body) + try container.encode(link, forKey: .link) + } +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 7ae80d49..0c82b7fe 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -55,6 +55,8 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) + // Vertical Combination Molecules From ee66dbe8d59bf0b06bfd486bbf83de095e675748 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Feb 2020 09:27:30 -0500 Subject: [PATCH 71/96] Caret fix in table view cell code condensing extra init functions --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 2 +- MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift | 2 +- MVMCoreUI/Atoms/Views/Checkbox.swift | 2 +- MVMCoreUI/Atoms/Views/CheckboxModel.swift | 2 + .../Atoms/Views/CircleProgressModel.swift | 5 +- MVMCoreUI/BaseClasses/TableViewCell.swift | 14 ++--- .../Views/Container/ContainerModel.swift | 6 +++ ...tLeftVariableCheckboxAllTextAndLinks.swift | 30 +++-------- ...VariableCheckboxAllTextAndLinksModel.swift | 2 +- .../ListLeftVariableIconWithRightCaret.swift | 38 +++++-------- ...tLeftVariableIconWithRightCaretModel.swift | 3 +- .../List/RightVariable/ListRVWheel.swift | 29 +++------- .../List/RightVariable/ListRVWheelModel.swift | 8 ++- .../ListRightVariablePayments.swift | 40 +++++--------- .../ListRightVariablePaymentsModel.swift | 6 +++ .../ListThreeColumnPlanDataDivider.swift | 30 +++-------- .../ListThreeColumnPlanDataDividerModel.swift | 3 ++ .../Molecules/Items/StackItemModel.swift | 13 ++--- .../EyebrowHeadlineBodyLinkModel.swift | 54 ++++++++++++++++++- MVMCoreUI/Organisms/StackModel.swift | 3 +- 20 files changed, 149 insertions(+), 143 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index f02eaf5c..917f573d 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -24,7 +24,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public var title: String public var action: ActionModelProtocol public var enabled: Bool = true - public var style: ButtonStyle? + public var style: ButtonStyle? = .primary public var size: ButtonSize? = .standard public var fillColor: Color? public var textColor: Color? diff --git a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift index 4b28fc8c..4ea79ef8 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift @@ -15,7 +15,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol { public var title: String public var action: ActionModelProtocol public var enabledColor: Color = Color(uiColor: .black) - public var disabledColor: Color? = Color(uiColor: .mfSilver()) + public var disabledColor: Color? = Color(uiColor: .mvmCoolGray6) public var enabled = true public init(title: String, action: ActionModelProtocol) { diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 27bed31e..2980b879 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -395,7 +395,7 @@ import MVMCore heightConstraint?.constant = dimension } - layoutIfNeeded() + //layoutIfNeeded() } public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index de79c6c6..706597ff 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -58,6 +58,8 @@ import Foundation case isEnabled case action } + + init(isChecked: Bool = false) {} //-------------------------------------------------- // MARK: - Codec diff --git a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift index 3cafb1bb..2fc67b44 100644 --- a/MVMCoreUI/Atoms/Views/CircleProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/CircleProgressModel.swift @@ -37,7 +37,10 @@ public class CircleProgressModel: MoleculeModelProtocol { public var colors = [Color]() public var backgroundColor: Color? - public init() {} + public init() { + updateStyle() + updateSize() + } private enum CodingKeys: String, CodingKey { case style diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index fe06a05a..ac91f292 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -198,16 +198,16 @@ import UIKit /// Adds the standard mvm style caret to the accessory view @objc public func addCaretViewAccessory() { guard accessoryView == nil else { return } - caretView = CaretView(lineWidth: 1) - caretView?.translatesAutoresizingMaskIntoConstraints = true - caretView?.size = .small(.vertical) - caretView?.setConstraints() - - if let size = caretView?.size?.dimensions() { + let caret = CaretView(lineWidth: 1) + caret.translatesAutoresizingMaskIntoConstraints = true + caret.size = .small(.vertical) + if let size = caret.size?.dimensions() { + caret.frame = CGRect(origin: CGPoint.zero, size: size) caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9) caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16) } - accessoryView = caretView + caretView = caret + accessoryView = caret } /// NOTE: Should only be called when displayed or about to be displayed. diff --git a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift index cdc6d743..a5e89adb 100644 --- a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift +++ b/MVMCoreUI/Containers/Views/Container/ContainerModel.swift @@ -27,6 +27,12 @@ public class ContainerModel: ContainerModelProtocol, Codable { } public init() {} + + public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) { + self.init() + self.horizontalAlignment = horizontalAlignment + self.verticalAlignment = verticalAlignment + } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift index 553e6359..0dad7228 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinks.swift @@ -8,49 +8,33 @@ import Foundation -@objcMembers public class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { +@objcMembers open class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { public let checkbox = Checkbox(frame: .zero) public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let stack = Stack(frame: .zero) // MARK: - View Lifecycle - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - override open func setupView() { super.setupView() stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) - } - - // MARK:- ModelMoleculeViewProtocol - override open func reset() { - super.reset() - stack.reset() + addMolecule(stack) } // MARK:- MVMCoreUIMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return} checkbox.setWithModel(model.checkbox, delegateObject, additionalData) eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) - // Create a stack model to use for the internal stack and set the alignment of labels - let checkbox = StackItemModel() - checkbox.horizontalAlignment = .fill - let eyebrowHeadlineBodyLink = StackItemModel() - eyebrowHeadlineBodyLink.horizontalAlignment = .leading - let stackModel = StackModel(molecules: [checkbox,eyebrowHeadlineBodyLink]) - stackModel.axis = .horizontal + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .leading)], + axis: .horizontal) stack.model = stackModel stack.restack() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 140 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift index 2fb89b1e..fec71c0b 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableCheckboxAllTextAndLinksModel.swift @@ -28,7 +28,7 @@ public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, Molecu required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) - checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox) + checkbox = try typeContainer.decodeIfPresent(CheckboxModel.self, forKey: .checkbox) ?? CheckboxModel() try super.init(from: decoder) } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 9f0e2deb..058d0da3 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -9,7 +9,7 @@ import Foundation import UIKit -@objcMembers public class ListLeftVariableIconWithRightCaret: TableViewCell { +@objcMembers open class ListLeftVariableIconWithRightCaret: TableViewCell { //----------------------------------------------------- // MARK: - Outlets @@ -22,17 +22,11 @@ import UIKit //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } override open func setupView() { super.setupView() - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) + addMolecule(stack) leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) } @@ -40,32 +34,28 @@ import UIKit //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ - override open func reset() { - super.reset() - stack.reset() - } - - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return} leftImage.setWithModel(model.image, delegateObject, additionalData) leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) - // Create a stack model to use for the internal stack and set the alignment of labels - let leftImage = StackItemModel() - leftImage.horizontalAlignment = .fill - let leftLabel = StackItemModel() - leftLabel.horizontalAlignment = .fill - let rightLabel = StackItemModel() - rightLabel.horizontalAlignment = .trailing - let stackModel = StackModel(molecules: [leftImage,leftLabel,rightLabel]) - stackModel.axis = .horizontal + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .fill), + StackItemModel(horizontalAlignment: .trailing)], + axis: .horizontal) stack.model = stackModel stack.restack() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 90 } + + open override func reset() { + super.reset() + leftLabel.styleB2(true) + rightLabel.styleB2(true) + } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift index bccf5320..4b426909 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretModel.swift @@ -19,6 +19,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod if image.height == nil { image.height = 30.0 } + rightLabel.hero = 0 } public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) { @@ -43,7 +44,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod 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/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index e9e09639..46d4b955 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -13,46 +13,30 @@ import Foundation let rightLabel = Label.commonLabelB2(true) let stack = Stack(frame: .zero) - //------------------------------------------------- - // MARK: - View Cycle - //------------------------------------------------- - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - //------------------------------------------------- // MARK: - Setup //------------------------------------------------- open override func setupView() { super.setupView() rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) + addMolecule(stack) } //------------------------------------------------- // MARK: - ModelMoleculeViewProtocol //------------------------------------------------- - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListRVWheelModel else { return } leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) wheel.setWithModel(model.wheel, delegateObject, additionalData) - // Create a stack model to use for the internal stack and set the alignment of models - let leftLabelStackItem = StackItemModel() - leftLabelStackItem.horizontalAlignment = .leading - let wheelStackItem = StackItemModel() - wheelStackItem.horizontalAlignment = .fill - let rightLabelStackItem = StackItemModel() - rightLabelStackItem.horizontalAlignment = .fill - rightLabelStackItem.spacing = 4 - let stackModel = StackModel(molecules: [leftLabelStackItem,wheelStackItem,rightLabelStackItem]) - stackModel.axis = .horizontal + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), + StackItemModel(horizontalAlignment: .fill), + StackItemModel(spacing: 4, horizontalAlignment: .fill)], + axis: .horizontal) stack.model = stackModel stack.restack() } @@ -62,7 +46,6 @@ import Foundation //------------------------------------------------- open override func reset() { super.reset() - stack.reset() leftLabel.styleB1(true) rightLabel.styleB2(true) } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift index 3831f5c7..89b70b0f 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRVWheelModel.swift @@ -20,6 +20,12 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol { super.init() } + /// Defaults to set + override public func setDefaults() { + super.setDefaults() + rightLabel.hero = 0 + } + private enum CodingKeys: String, CodingKey { case moleculeName case leftLabel @@ -31,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.decode(CircleProgressModel.self, forKey: .wheel) + wheel = try typeContainer.decodeIfPresent(CircleProgressModel.self, forKey: .wheel) ?? CircleProgressModel() try super.init(from: decoder) } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 2bfbc321..66f88371 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -8,12 +8,11 @@ import Foundation -@objcMembers public class ListRightVariablePayments: TableViewCell { +@objcMembers open class ListRightVariablePayments: TableViewCell { //----------------------------------------------------- // MARK: - Outlets //------------------------------------------------------- - let leftLabel = Label.commonLabelB1(true) let rightImage = MFLoadImageView(pinnedEdges: .all) let stack = Stack(frame: .zero) @@ -21,49 +20,34 @@ import Foundation //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - override open func setupView() { super.setupView() - guard leftLabel.superview == nil else { - return - } - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) + addMolecule(stack) } //---------------------------------------------------- // MARK: - Molecule //------------------------------------------------------ - override open func reset() { - super.reset() - stack.reset() - } - - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListRightVariablePaymentsModel else { return } leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) rightImage.setWithModel(model.image, delegateObject, additionalData) - // Create a stack model to use for the internal stack and set the alignment of label and image - let leftLabel = StackItemModel() - leftLabel.horizontalAlignment = .leading - let rightImage = StackItemModel() - rightImage.horizontalAlignment = .fill - let stackModel = StackModel(molecules: [leftLabel,rightImage]) - stackModel.axis = .horizontal + let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), + StackItemModel(horizontalAlignment: .fill)], + axis: .horizontal) stack.model = stackModel stack.restack() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 65 } + + open override func reset() { + super.reset() + leftLabel.styleB1(true) + } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift index a8c6ff80..4842b60a 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePaymentsModel.swift @@ -20,6 +20,12 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco super.init() } + /// Defaults to set + override public func setDefaults() { + super.setDefaults() + leftLabel.hero = 0 + } + static func createPayPalImage() -> ImageViewModel { let image = ImageViewModel(image: "imageName_PayPal_logo") image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI() diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift index 19774110..565ed737 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDivider.swift @@ -16,23 +16,16 @@ import Foundation let stack = Stack(frame: .zero) // MARK: - MFViewProtocol - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - open override func setupView() { super.setupView() //using stackItems to align the three headlineBody - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)] - contentView.addSubview(stack) - containerHelper.constrainView(stack) + addMolecule(stack) } // MARK: - MVMCoreUIMoleculeViewProtocol - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListThreeColumnPlanDataDividerModel else { return } leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData) @@ -40,24 +33,15 @@ import Foundation rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData) // Create a stack model to use for the internal stack and set the alignment of models - let leftHeadlineBodyAlignment = StackItemModel(percent: 33) - leftHeadlineBodyAlignment.horizontalAlignment = .leading - let centerHeadLineBodyAlignment = StackItemModel(percent: 34) - centerHeadLineBodyAlignment.horizontalAlignment = .center - let rightHeadLineBodyAlignment = StackItemModel(percent: 33) - rightHeadLineBodyAlignment.horizontalAlignment = .trailing - let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment]) - stackModel.axis = .horizontal + let stackModel = StackModel(molecules: [StackItemModel(percent: 33, horizontalAlignment: .leading), + StackItemModel(percent: 34, horizontalAlignment: .center), + StackItemModel(percent: 33, horizontalAlignment: .trailing)], + axis: .horizontal) stack.model = stackModel stack.restack() } - open override func reset() { - super.reset() - stack.reset() - } - - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 121 } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift index fd946eb0..3ddfe64b 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnPlanDataDividerModel.swift @@ -26,6 +26,9 @@ public class ListThreeColumnPlanDataDividerModel: ListItemModel, MoleculeModelPr override public func setDefaults() { super.setDefaults() style = "tallDivider" + leftHeadlineBody.style = "itemHeader" + centerHeadlineBody.style = "itemHeader" + rightHeadlineBody.style = "itemHeader" } private enum CodingKeys: String, CodingKey { diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index b7d1a269..795b2983 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -16,13 +16,14 @@ import Foundation public var percent: Int? public var gone: Bool = false - public convenience init(gone: Bool) { - self.init() - self.gone = gone - } - - public convenience init(percent: Int) { + 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 + self.spacing = spacing self.percent = percent + if let gone = gone { + self.gone = gone + } } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 913933d9..2ff3ca57 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -8,7 +8,7 @@ import Foundation -public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { +public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "eyebrowHeadlineBodyLink" public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier public var backgroundColor: Color? @@ -16,4 +16,56 @@ public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { public var headline: LabelModel? public var body: LabelModel? public var link: LinkModel? + + public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) throws { + // TODO: This class initializers should ensure that atleast one item is set. + /*guard eyebrow != nil || headline != nil || body != nil || link != nil else { + throw + }*/ + self.eyebrow = eyebrow + self.headline = headline + self.body = body + self.link = link + setDefaults() + } + + /// Defaults to set + public func setDefaults() { + if let headline = headline { + headline.hero = 0 + } + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case eyebrow + case headline + case body + case link + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) + headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) + link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) + setDefaults() + // TODO: This class initializers should ensure that atleast one item is set. + /*guard eyebrow != nil || headline != nil || body != nil || link != nil else { + throw + }*/ + } + + 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.encodeIfPresent(eyebrow, forKey: .eyebrow) + try container.encodeIfPresent(headline, forKey: .headline) + try container.encodeIfPresent(body, forKey: .body) + try container.encodeIfPresent(link, forKey: .link) + } } diff --git a/MVMCoreUI/Organisms/StackModel.swift b/MVMCoreUI/Organisms/StackModel.swift index 8d670efb..b762a03c 100644 --- a/MVMCoreUI/Organisms/StackModel.swift +++ b/MVMCoreUI/Organisms/StackModel.swift @@ -16,8 +16,9 @@ import Foundation public var spacing: CGFloat = 16.0 public var useStackSpacingBeforeFirstItem = false - public init(molecules: [StackItemModel]) { + public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical) { self.molecules = molecules + self.axis = axis } private enum CodingKeys: String, CodingKey { From dedcd9de12a9d02dcaf3da414e6a78bf4bcf3f2b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Feb 2020 10:16:00 -0500 Subject: [PATCH 72/96] undo commented code --- MVMCoreUI/Atoms/Views/Checkbox.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index 2980b879..27bed31e 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -395,7 +395,7 @@ import MVMCore heightConstraint?.constant = dimension } - //layoutIfNeeded() + layoutIfNeeded() } public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { From 17583c107ce721dab4a044d76add9fc61eae3e38 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 21 Feb 2020 14:31:46 -0500 Subject: [PATCH 73/96] moved hero is setWithModel. Was not being set. Mild changes. --- MVMCoreUI/Atoms/Views/Label/Label.swift | 3 ++- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 20 +++++++++++++-- MVMCoreUI/BaseClasses/TableViewCell.swift | 6 ++--- .../EyebrowHeadlineBodyLink.swift | 14 ++++++++--- MVMCoreUI/Organisms/Stack.swift | 25 ++++++++----------- 5 files changed, 44 insertions(+), 24 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 013f7f11..b300b7bb 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -231,6 +231,7 @@ public typealias ActionBlock = () -> () attributedText = nil originalAttributedString = nil text = labelModel.text + hero = labelModel.hero Label.setLabel(self, withHTML: labelModel.html) let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "") @@ -344,7 +345,6 @@ public typealias ActionBlock = () -> () } attributedText = attributedString originalAttributedString = attributedText - hero = labelModel.hero } } @@ -716,6 +716,7 @@ extension Label { public func reset() { text = nil attributedText = nil + hero = nil textAlignment = .left originalAttributedString = nil styleB2(true) diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index d7fb4fa3..cb9cc0a9 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -10,6 +10,10 @@ import Foundation @objcMembers public class LabelModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "label" public var backgroundColor: Color? public var text: String @@ -24,6 +28,10 @@ import Foundation public var hero: Int? public var makeWholeViewClickable: Bool? + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case text @@ -43,11 +51,19 @@ import Foundation enum AttributeTypeKey: String, CodingKey { case type } - + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(text: String) { self.text = text } - + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) text = try typeContainer.decode(String.self, forKey: .text) diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index ac91f292..a301926c 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -198,8 +198,8 @@ import UIKit /// Adds the standard mvm style caret to the accessory view @objc public func addCaretViewAccessory() { guard accessoryView == nil else { return } + let caret = CaretView(lineWidth: 1) - caret.translatesAutoresizingMaskIntoConstraints = true caret.size = .small(.vertical) if let size = caret.size?.dimensions() { caret.frame = CGRect(origin: CGPoint.zero, size: size) @@ -217,11 +217,11 @@ import UIKit layoutIfNeeded() guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) - accessoryView?.center.y = contentView.convert(UIView(frame: rect).center, from: heroLabel).y + accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y heroAccessoryCenter = accessoryView?.center } - /// Traverses the view hierarchy for a 🦸‍♂️heroic Label. + /// Traverses the view hierarchy for a 🦸‍♂️ heroic Label. private func findHeroLabel(views: [UIView]) -> Label? { if views.isEmpty { diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index 8f206e35..c964c6ed 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -9,11 +9,13 @@ import UIKit @objcMembers open class EyebrowHeadlineBodyLink: Container { + let stack = Stack(frame: .zero) let eyebrow = Label.commonLabelB3(true) let headline = Label.commonLabelB1(true) let body = Label.commonLabelB2(true) let link = Link() + var casteModel: EyebrowHeadlineBodyLinkModel? { get { return model as? EyebrowHeadlineBodyLinkModel } } @@ -21,7 +23,10 @@ import UIKit // MARK: - MFViewProtocol open override func setupView() { super.setupView() - stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)] + stack.stackItems = [StackItem(andContain: eyebrow), + StackItem(andContain: headline), + StackItem(andContain: body), + StackItem(andContain: link)] addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) } @@ -42,7 +47,7 @@ import UIKit } // MARK:- ModelMoleculeViewProtocol - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData) headline.setWithModel(casteModel?.headline, delegateObject, additionalData) @@ -50,7 +55,10 @@ import UIKit link.setWithModel(casteModel?.link, delegateObject, additionalData) // Create a stack model to use for the internal stack. - let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),StackItemModel(gone: !headline.hasText),StackItemModel(gone: !body.hasText),StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) + let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), + StackItemModel(gone: !headline.hasText), + StackItemModel(gone: !body.hasText), + StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) stackModel.spacing = 0 stack.model = stackModel stack.restack() diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 4e7a3114..1f2fa288 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -51,7 +51,7 @@ open class Stack: Container where T: StackModelProtocol { super.init(frame: frame) } - public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.init(frame: CGRect.zero) setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } @@ -63,9 +63,7 @@ open class Stack: Container where T: StackModelProtocol { // MARK: - MFViewProtocol public override func setupView() { super.setupView() - guard contentView.superview == nil else { - return - } + guard contentView.superview == nil else { return } MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) translatesAutoresizingMaskIntoConstraints = false backgroundColor = .clear @@ -91,7 +89,7 @@ open class Stack: Container where T: StackModelProtocol { } } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { let previousModel = self.model super.setWithModel(model, delegateObject, additionalData) removeAllItemViews() @@ -132,6 +130,7 @@ open class Stack: Container where T: StackModelProtocol { guard let model = molecule as? T else { return 0 } let horizontal = model.axis == .horizontal var estimatedHeight: CGFloat = 0 + for case let item in model.molecules { if item.gone { continue } let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0 @@ -161,11 +160,10 @@ open class Stack: Container where T: StackModelProtocol { // MARK: - Subclassables /// Can be subclassed to create views when we get stack item models and have no views yet - func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - } + func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { } /// Can be subclassed to set stack items with model when we already have views - func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let models = stackModel?.molecules else { return } for (index, element) in models.enumerated() { (stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData) @@ -178,6 +176,7 @@ open class Stack: Container where T: StackModelProtocol { guard let stackModel = stackModel else { return 0.0 } var totalSpace: CGFloat = 0.0 var firstMoleculeFound = false + for stackItemModel in stackModel.molecules { guard !stackItemModel.gone else { continue } let spacing = stackItemModel.spacing ?? stackModel.spacing @@ -214,9 +213,7 @@ open class Stack: Container where T: StackModelProtocol { if stackModel.axis == .vertical { if first { pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) - } else if let previousView = stackItems.last(where: { item in - return !model.gone - }) { + } else if let previousView = stackItems.last(where: { item in !model.gone }) { view.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true } pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) @@ -233,15 +230,13 @@ open class Stack: Container where T: StackModelProtocol { if first { // First horizontal item has no spacing by default unless told otherwise. pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) - } else if let previousView = stackItems.last(where: { item in - return !model.gone - }) { + } else if let previousView = stackItems.last(where: { item in !model.gone }) { view.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true } pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) if let percent = model.percent { - let multiplier = CGFloat(percent)/100.0 + let multiplier = CGFloat(percent) / 100.0 let constant = multiplier * totalSpacing view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true } From 0c11ded57778570e316f981f16a4ac4f4361d567 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 21 Feb 2020 14:41:53 -0500 Subject: [PATCH 74/96] rolled back change. --- MVMCoreUI/Organisms/Stack.swift | 35 ++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 1f2fa288..67ff0110 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -9,13 +9,20 @@ import Foundation open class Stack: Container where T: StackModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() var stackModel: T? { get { return model as? T } } var stackItems: [UIView] = [] + //-------------------------------------------------- // MARK: - Helpers + //-------------------------------------------------- + public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) constraint.priority = priority @@ -45,8 +52,11 @@ open class Stack: Container where T: StackModelProtocol { item.removeFromSuperview() } } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- - // MARK: - Inits public override init(frame: CGRect) { super.init(frame: frame) } @@ -60,7 +70,10 @@ open class Stack: Container where T: StackModelProtocol { fatalError("init(coder:) has not been implemented") } + //-------------------------------------------------- // MARK: - MFViewProtocol + //-------------------------------------------------- + public override func setupView() { super.setupView() guard contentView.superview == nil else { return } @@ -80,7 +93,10 @@ open class Stack: Container where T: StackModelProtocol { } } + //-------------------------------------------------- // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + public override func reset() { super.reset() backgroundColor = .clear @@ -157,8 +173,10 @@ open class Stack: Container where T: StackModelProtocol { return modules.count > 0 ? modules : nil } + //-------------------------------------------------- // MARK: - Subclassables - + //-------------------------------------------------- + /// Can be subclassed to create views when we get stack item models and have no views yet func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { } @@ -170,7 +188,10 @@ open class Stack: Container where T: StackModelProtocol { } } + //-------------------------------------------------- // MARK: - Adding to stack + //-------------------------------------------------- + /// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved. private func getTotalSpace() -> CGFloat { guard let stackModel = stackModel else { return 0.0 } @@ -213,13 +234,15 @@ open class Stack: Container where T: StackModelProtocol { if stackModel.axis == .vertical { if first { pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) - } else if let previousView = stackItems.last(where: { item in !model.gone }) { + } else if let previousView = stackItems.last(where: { item in + return !model.gone + }) { view.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true } pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0) if let percent = model.percent { - let multiplier = CGFloat(percent)/100.0 + let multiplier = CGFloat(percent) / 100.0 let constant = multiplier * totalSpacing view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true } @@ -230,7 +253,9 @@ open class Stack: Container where T: StackModelProtocol { if first { // First horizontal item has no spacing by default unless told otherwise. pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: stackModel.useStackSpacingBeforeFirstItem ? spacing : model.spacing ?? 0) - } else if let previousView = stackItems.last(where: { item in !model.gone }) { + } else if let previousView = stackItems.last(where: { item in + return !model.gone + }) { view.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true } pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) From f8895157097676ce1ce3e4e41363f2f85544c87b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Sun, 23 Feb 2020 13:34:20 -0500 Subject: [PATCH 75/96] hero is working. commenting done. --- .../EyebrowHeadlineBodyLink.swift | 15 +++++++++- .../EyebrowHeadlineBodyLinkModel.swift | 28 ++++++++++++++++--- MVMCoreUI/Organisms/Stack.swift | 2 ++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index c964c6ed..e9d7d34e 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -9,6 +9,9 @@ import UIKit @objcMembers open class EyebrowHeadlineBodyLink: Container { + //-------------------------------------------------- + // MARK: - Outlets + //-------------------------------------------------- let stack = Stack(frame: .zero) let eyebrow = Label.commonLabelB3(true) @@ -20,7 +23,10 @@ import UIKit get { return model as? EyebrowHeadlineBodyLinkModel } } + //-------------------------------------------------- // MARK: - MFViewProtocol + //-------------------------------------------------- + open override func setupView() { super.setupView() stack.stackItems = [StackItem(andContain: eyebrow), @@ -36,7 +42,10 @@ import UIKit stack.updateView(size) } + //-------------------------------------------------- // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + open override func reset() { super.reset() stack.reset() @@ -46,9 +55,13 @@ import UIKit body.styleB2(true) } - // MARK:- ModelMoleculeViewProtocol + //-------------------------------------------------- + // MARK: - ModelMoleculeViewProtocol + //-------------------------------------------------- + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) + eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData) headline.setWithModel(casteModel?.headline, delegateObject, additionalData) body.setWithModel(casteModel?.body, delegateObject, additionalData) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index 2ff3ca57..e277f5de 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -9,6 +9,10 @@ import Foundation public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "eyebrowHeadlineBodyLink" public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier public var backgroundColor: Color? @@ -17,11 +21,15 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { public var body: LabelModel? public var link: LinkModel? + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) throws { // TODO: This class initializers should ensure that atleast one item is set. /*guard eyebrow != nil || headline != nil || body != nil || link != nil else { - throw - }*/ + throw + }*/ self.eyebrow = eyebrow self.headline = headline self.body = body @@ -29,6 +37,10 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { setDefaults() } + //-------------------------------------------------- + // MARK: - Method + //-------------------------------------------------- + /// Defaults to set public func setDefaults() { if let headline = headline { @@ -36,6 +48,10 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { } } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor @@ -45,6 +61,10 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { case link } + //-------------------------------------------------- + // 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) @@ -55,8 +75,8 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { setDefaults() // TODO: This class initializers should ensure that atleast one item is set. /*guard eyebrow != nil || headline != nil || body != nil || link != nil else { - throw - }*/ + throw + }*/ } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 67ff0110..602ab0f1 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -8,6 +8,7 @@ import Foundation + open class Stack: Container where T: StackModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -24,6 +25,7 @@ open class Stack: Container where T: StackModelProtocol { //-------------------------------------------------- public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { + let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) constraint.priority = priority constraint.isActive = true From e33fe346c69bd3e0a748a4d2f51d6e5917fe96fd Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 24 Feb 2020 09:58:47 -0500 Subject: [PATCH 76/96] mild updates --- MVMCoreUI/Atoms/Views/Label/Label.swift | 3 --- MVMCoreUI/BaseClasses/TableViewCell.swift | 7 ++----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index b300b7bb..f08d532d 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -808,9 +808,6 @@ extension Label { - Attention: This method expects text to be set first. Otherwise, it will do nothing. - parameter range: The range of text to be tapped. - - parameter actionMap: - - parameter delegate: - - parameter additionalData: */ @objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) { diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index a301926c..8547457e 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -139,7 +139,6 @@ import UIKit topSeparatorView?.updateView(size) bottomSeparatorView?.updateView(size) - molecule?.updateView(size) } @@ -153,9 +152,7 @@ import UIKit //TODO: Model, Change to model public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? ListItemModelProtocol else { - return - } + guard let model = model as? ListItemModelProtocol else { return } self.listItemModel = model style(with: model.style) @@ -194,7 +191,7 @@ import UIKit return nil } - // MARK: - Arrow + // MARK: - Caret View /// Adds the standard mvm style caret to the accessory view @objc public func addCaretViewAccessory() { guard accessoryView == nil else { return } From 9b5379626607dab86fbca95d8b8d4fab72ab7ff9 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 24 Feb 2020 10:13:45 -0500 Subject: [PATCH 77/96] undoing removal --- MVMCoreUI/BaseClasses/TableViewCell.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index 8547457e..d96a4587 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -197,6 +197,7 @@ import UIKit guard accessoryView == nil else { return } let caret = CaretView(lineWidth: 1) + caret.translatesAutoresizingMaskIntoConstraints = true caret.size = .small(.vertical) if let size = caret.size?.dimensions() { caret.frame = CGRect(origin: CGPoint.zero, size: size) From 2f94f3435ab3049471f8786e08d1851505331854 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Mon, 24 Feb 2020 22:04:28 +0530 Subject: [PATCH 78/96] Code changes as per condensed code feature branch. --- ...neColumnFullWidthTextAllTextAndLinks.swift | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 9827fed4..8d588374 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -36,24 +36,15 @@ import Foundation return } stack.translatesAutoresizingMaskIntoConstraints = false - stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: subHeadline),StackItem(andContain: body),StackItem(andContain: link)] + stack.stackItems = [StackItem(andContain: eyebrow), + StackItem(andContain: headline), + StackItem(andContain: body), + StackItem(andContain: link)] contentView.addSubview(stack) - containerHelper.constrainView(stack) - } - //---------------------------------------------------- - // MARK: - Molecule - //------------------------------------------------------ - - override open func reset() { - super.reset() - stack.reset() - eyebrow.styleB3(true) - headline.styleH3(true) - subHeadline.styleB1(true) - body.styleB2(true) + addMolecule(stack) } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){ super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return} eyebrow.setWithModel(model.eyebrow, delegateObject, additionalData) @@ -61,14 +52,25 @@ import Foundation subHeadline.setWithModel(model.subHeadline, delegateObject, additionalData) body.setWithModel(model.body, delegateObject, additionalData) link.setWithModel(model.link, delegateObject, additionalData) - - let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),StackItemModel(gone: !headline.hasText),StackItemModel(gone: !subHeadline.hasText),StackItemModel(gone: !body.hasText),StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) + let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), + StackItemModel(gone: !headline.hasText), + StackItemModel(gone: !body.hasText), + StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) stack.model = stackModel stackModel.spacing = 2 stack.restack() } - public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat?{ return 90 } + + open override func reset() { + super.reset() + stack.reset() + eyebrow.styleB3(true) + headline.styleH3(true) + subHeadline.styleB1(true) + body.styleB2(true) + } } From 9a8c510b7fc0a4c97e5268f6583a0912bc4782a4 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Mon, 24 Feb 2020 22:06:31 +0530 Subject: [PATCH 79/96] minor change --- .../OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 8d588374..b10a9d65 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -40,7 +40,6 @@ import Foundation StackItem(andContain: headline), StackItem(andContain: body), StackItem(andContain: link)] - contentView.addSubview(stack) addMolecule(stack) } From b255b1acac35b5c41b41bbb6ba2699335c7a74b7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 24 Feb 2020 16:53:42 -0500 Subject: [PATCH 80/96] header updates --- MVMCoreUI.xcodeproj/project.pbxproj | 16 +++++-- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 2 +- .../Containers/Views/MoleculeContainer.swift | 8 ++-- .../Views/MoleculeContainerModel.swift | 2 +- .../Views/MoleculeContainerProtocol.swift | 13 ++++++ MVMCoreUI/Molecules/HeaderModel.swift | 20 ++++---- MVMCoreUI/Molecules/MoleculeHeaderModel.swift | 37 +++++++++++++++ ...derView.swift => MoleculeHeaderView.swift} | 46 +++++++------------ .../OtherHandlers/MoleculeObjectMapping.swift | 2 +- 9 files changed, 95 insertions(+), 51 deletions(-) create mode 100644 MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift create mode 100644 MVMCoreUI/Molecules/MoleculeHeaderModel.swift rename MVMCoreUI/Molecules/{HeaderView.swift => MoleculeHeaderView.swift} (60%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 4afd3a24..3e9138f7 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -307,7 +307,7 @@ 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 /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* HeaderView.swift */; }; + D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MoleculeHeaderView.swift */; }; D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; }; D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; }; D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; }; @@ -322,6 +322,8 @@ D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C521A823EDE79E00CA2634 /* ViewController.swift */; }; D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; }; D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; }; + D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; }; + D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */; }; D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; }; D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; }; D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; }; @@ -650,7 +652,7 @@ 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 /* HeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; }; + D2A514662213885800345BFB /* MoleculeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderView.swift; sourceTree = ""; }; D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerViewController.swift; sourceTree = ""; }; D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = ""; }; D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = ""; }; @@ -665,6 +667,8 @@ D2C521A823EDE79E00CA2634 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = ""; }; D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = ""; }; + D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = ""; }; + D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainerProtocol.swift; sourceTree = ""; }; D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = ""; }; D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = ""; }; D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = ""; }; @@ -757,6 +761,7 @@ children = ( 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */, D29E28DE23D740FC00ACEA85 /* Container */, + D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */, 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, ); @@ -1128,7 +1133,8 @@ D224798E2316A995003FCCF9 /* HorizontalCombinationViews */, D224798D2316A988003FCCF9 /* VerticalCombinationViews */, 01EB368C23609801006832FA /* HeaderModel.swift */, - D2A514662213885800345BFB /* HeaderView.swift */, + D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */, + D2A514662213885800345BFB /* MoleculeHeaderView.swift */, 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, D274CA322236A78900B01B62 /* FooterView.swift */, 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, @@ -1716,7 +1722,7 @@ D2E2A99C23D8D975000B42E6 /* ImageHeadlineBodyModel.swift in Sources */, D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, - D2A514672213885800345BFB /* HeaderView.swift in Sources */, + D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, @@ -1781,6 +1787,7 @@ D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, + D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */, 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */, @@ -1802,6 +1809,7 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */, + D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 917f573d..f02eaf5c 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -24,7 +24,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public var title: String public var action: ActionModelProtocol public var enabled: Bool = true - public var style: ButtonStyle? = .primary + public var style: ButtonStyle? public var size: ButtonSize? = .standard public var fillColor: Color? public var textColor: Color? diff --git a/MVMCoreUI/Containers/Views/MoleculeContainer.swift b/MVMCoreUI/Containers/Views/MoleculeContainer.swift index 9a907222..d179ef72 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainer.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainer.swift @@ -31,7 +31,7 @@ open class MoleculeContainer: Container { } public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - if let casteModel = model as? MoleculeContainerModel { + if let casteModel = model as? MoleculeContainerModelProtocol { if view != nil { (view as? ModelMoleculeViewProtocol)?.setWithModel(casteModel.molecule, delegateObject, additionalData) } else { @@ -44,7 +44,7 @@ open class MoleculeContainer: Container { } public override static func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - guard let containerModel = model as? MoleculeContainerModel, + guard let containerModel = model as? MoleculeContainerModelProtocol, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type, let moleculeName = moleculeClass.nameForReuse(containerModel.molecule, delegateObject) else { return "\(model?.moleculeName ?? "moleculeContainer")<>" @@ -53,7 +53,7 @@ open class MoleculeContainer: Container { } public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let containerModel = molecule as? MoleculeContainerModel else { return 0 } + guard let containerModel = molecule as? MoleculeContainerModelProtocol else { return 0 } guard let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type, let moleculeHeight = moleculeClass.estimatedHeight(forRow: containerModel.molecule, delegateObject: delegateObject) else { return (containerModel.topMarginPadding ?? 0) + (containerModel.bottomMarginPadding ?? 0) @@ -62,7 +62,7 @@ open class MoleculeContainer: Container { } public override class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let containerModel = molecule as? MoleculeContainerModel, + guard let containerModel = molecule as? MoleculeContainerModelProtocol, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(containerModel.molecule) as? ModelMoleculeViewProtocol.Type else { return nil } return moleculeClass.requiredModules(containerModel.molecule, delegateObject: delegateObject, error: error) } diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift b/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift index 0421b3d1..95683f8f 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift +++ b/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift @@ -8,7 +8,7 @@ import Foundation -public class MoleculeContainerModel: ContainerModel { +public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol { public var molecule: MoleculeModelProtocol private enum CodingKeys: String, CodingKey { diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift b/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift new file mode 100644 index 00000000..882cf181 --- /dev/null +++ b/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift @@ -0,0 +1,13 @@ +// +// MoleculeContainerProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol MoleculeContainerModelProtocol: ContainerModelProtocol { + var molecule: MoleculeModelProtocol { get set } +} diff --git a/MVMCoreUI/Molecules/HeaderModel.swift b/MVMCoreUI/Molecules/HeaderModel.swift index b6f3629f..6314947c 100644 --- a/MVMCoreUI/Molecules/HeaderModel.swift +++ b/MVMCoreUI/Molecules/HeaderModel.swift @@ -8,19 +8,17 @@ import Foundation -@objcMembers public class HeaderModel: MoleculeContainerModel, MoleculeModelProtocol { - public static var identifier: String = "header" +@objcMembers public class HeaderModel: ContainerModel { public var backgroundColor: Color? public var line: LineModel? private enum CodingKeys: String, CodingKey { - case moleculeName case line case backgroundColor } /// Defaults to set - func setDefaults() { + public func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } @@ -33,25 +31,27 @@ import Foundation if bottomMarginPadding == nil { bottomMarginPadding = PaddingDefaultVerticalSpacing } - line?.type = .heavy + if line == nil { + line = LineModel(type: .heavy) + } } - public override init(with moleculeModel: MoleculeModelProtocol) { - super.init(with: moleculeModel) + public override init() { + super.init() setDefaults() } required public init(from decoder: Decoder) throws { try super.init(from: decoder) - setDefaults() let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .heavy) + 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 { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(moleculeName, forKey: .moleculeName) try container.encode(line, forKey: .line) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } diff --git a/MVMCoreUI/Molecules/MoleculeHeaderModel.swift b/MVMCoreUI/Molecules/MoleculeHeaderModel.swift new file mode 100644 index 00000000..92958ca1 --- /dev/null +++ b/MVMCoreUI/Molecules/MoleculeHeaderModel.swift @@ -0,0 +1,37 @@ +// +// MoleculeHeaderModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 10/3/19. +// Copyright © 2019 Suresh, Kamlesh. All rights reserved. +// + +import Foundation + +@objcMembers public class MoleculeHeaderModel: HeaderModel, MoleculeModelProtocol, MoleculeContainerModelProtocol { + public static var identifier: String = "header" + public var molecule: MoleculeModelProtocol + + private enum CodingKeys: String, CodingKey { + case moleculeName + case molecule + } + + public init(with moleculeModel: MoleculeModelProtocol) { + molecule = moleculeModel + super.init() + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) + 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) + } +} diff --git a/MVMCoreUI/Molecules/HeaderView.swift b/MVMCoreUI/Molecules/MoleculeHeaderView.swift similarity index 60% rename from MVMCoreUI/Molecules/HeaderView.swift rename to MVMCoreUI/Molecules/MoleculeHeaderView.swift index c90be96d..5d58c675 100644 --- a/MVMCoreUI/Molecules/HeaderView.swift +++ b/MVMCoreUI/Molecules/MoleculeHeaderView.swift @@ -1,5 +1,5 @@ // -// HeaderView.swift +// MoleculeHeaderView.swift // MVMCoreUI // // Created by Scott Pfeil on 2/12/19. @@ -8,55 +8,41 @@ import UIKit -public class HeaderView: MoleculeContainer { - var line: Line? +public class MoleculeHeaderView: MoleculeContainer { + var line = Line() - var headerModel: HeaderModel? { - get { return model as? HeaderModel } + var headerModel: MoleculeHeaderModel? { + get { return model as? MoleculeHeaderModel } } // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { super.updateView(size) - line?.updateView(size) + line.updateView(size) } public override func setupView() { super.setupView() - - guard line == nil else { return } - let line = Line() line.setStyle(.heavy) addSubview(line) NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true NSLayoutConstraint.pinViewRight(toSuperview: line, useMargins: true, constant: 0).isActive = true - self.line = line } // MARK: - MVMCoreUIMoleculeViewProtocol - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let separatorJSON = json?.optionalDictionaryForKey("line") { - line?.setWithJSON(separatorJSON, delegateObject: delegateObject, additionalData: additionalData) - } - } - - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) - - guard let headerModel = model as? HeaderModel else { - return - } - - if let seperatorModel = headerModel.line { - line?.setWithJSON(seperatorModel.toJSON(), delegateObject: delegateObject, additionalData: additionalData) - } - } - open override func reset() { super.reset() - line?.setStyle(.heavy) + line.setStyle(.heavy) + } + + // MARK: - ModelMoleculeViewProtocol + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let headerModel = headerModel else { return } + if let lineModel = headerModel.line { + line.setWithModel(lineModel, delegateObject, additionalData) + } } public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 7ae80d49..fde8f4cb 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -88,7 +88,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: CarouselItemModel.self) // Other Container Molecules - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeaderView.self, viewModelClass: HeaderModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self) From fea1c2e9972ddbb220d6af95f50bb807638fdfb6 Mon Sep 17 00:00:00 2001 From: Kruthika KP <> Date: Tue, 25 Feb 2020 13:33:40 +0530 Subject: [PATCH 81/96] added subHeadline and changed the files order --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++---- .../ListOneColumnFullWidthTextAllTextAndLinks.swift | 12 +++--------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0fb1da3a..95bd45b6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -99,11 +99,11 @@ 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; - 52267A0923FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0823FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */; }; 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; }; + 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.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 */; }; @@ -433,11 +433,11 @@ 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; - 52267A0823FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; 5248BFEA23F12E350059236A /* ListThreeColumnPlanDataDivider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDivider.swift; sourceTree = ""; }; 5248BFEB23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListThreeColumnPlanDataDividerModel.swift; sourceTree = ""; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = ""; }; 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = ""; }; + 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = ""; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.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 = ""; }; @@ -775,8 +775,8 @@ 52267A0523FFE0A900906CBA /* OneColumn */ = { isa = PBXGroup; children = ( + 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */, 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */, - 52267A0823FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */, ); path = OneColumn; sourceTree = ""; @@ -1692,7 +1692,6 @@ D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, - 52267A0923FFE28200906CBA /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, @@ -1793,6 +1792,7 @@ 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */, D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */, + 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */, 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */, diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index b10a9d65..e13bdd8b 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -32,12 +32,9 @@ import Foundation override open func setupView() { super.setupView() - guard stack.superview == nil else { - return - } - stack.translatesAutoresizingMaskIntoConstraints = false stack.stackItems = [StackItem(andContain: eyebrow), StackItem(andContain: headline), + StackItem(andContain: subHeadline), StackItem(andContain: body), StackItem(andContain: link)] addMolecule(stack) @@ -53,6 +50,7 @@ import Foundation link.setWithModel(model.link, delegateObject, additionalData) let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), StackItemModel(gone: !headline.hasText), + StackItemModel(gone: !subHeadline.hasText), StackItemModel(gone: !body.hasText), StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) stack.model = stackModel @@ -66,10 +64,6 @@ import Foundation open override func reset() { super.reset() - stack.reset() - eyebrow.styleB3(true) - headline.styleH3(true) - subHeadline.styleB1(true) - body.styleB2(true) + } } From 54782b187132f158fd9d955b1cc36e2168052500 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Tue, 25 Feb 2020 20:11:22 +0530 Subject: [PATCH 82/96] Changes in init method and spacing --- ...neColumnFullWidthTextAllTextAndLinks.swift | 16 +++++++----- ...umnFullWidthTextAllTextAndLinksModel.swift | 26 +++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index e13bdd8b..4b0e2e91 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -48,13 +48,12 @@ import Foundation subHeadline.setWithModel(model.subHeadline, delegateObject, additionalData) body.setWithModel(model.body, delegateObject, additionalData) link.setWithModel(model.link, delegateObject, additionalData) - let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText), - StackItemModel(gone: !headline.hasText), - StackItemModel(gone: !subHeadline.hasText), - StackItemModel(gone: !body.hasText), - StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) + let stackModel = StackModel(molecules: [StackItemModel(spacing: 2, gone: !eyebrow.hasText), + StackItemModel(spacing: 2, gone: !headline.hasText), + StackItemModel(spacing: 2, gone: !subHeadline.hasText), + StackItemModel(spacing: 2, gone: !body.hasText), + StackItemModel(spacing: 2, gone: (link.titleLabel?.text?.count ?? 0) == 0)]) stack.model = stackModel - stackModel.spacing = 2 stack.restack() } @@ -64,6 +63,9 @@ import Foundation open override func reset() { super.reset() - + eyebrow.styleB3(true) + headline.styleH3(true) + subHeadline.styleB1(true) + body.styleB2(true) } } diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift index ebc87aa4..47e482a0 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinksModel.swift @@ -15,8 +15,8 @@ public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, Mole public var subHeadline: LabelModel? public var body: LabelModel? public var link : LinkModel? - - public init(eyebrow:LabelModel, headline: LabelModel, subHeadline: LabelModel, body: LabelModel, link: LinkModel) { + + public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, subHeadline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) { self.eyebrow = eyebrow self.headline = headline self.subHeadline = subHeadline @@ -36,22 +36,22 @@ public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, Mole required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - eyebrow = try typeContainer.decode(LabelModel.self, forKey: .eyebrow) - headline = try typeContainer.decode(LabelModel.self, forKey: .headline) - subHeadline = try typeContainer.decode(LabelModel.self, forKey: .subHeadline) - body = try typeContainer.decode(LabelModel.self, forKey: .body) - link = try typeContainer.decode(LinkModel.self, forKey: .link) + eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) + headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) + subHeadline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .subHeadline) + body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) + link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) 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(eyebrow, forKey: .eyebrow) - try container.encode(headline, forKey: .headline) - try container.encode(subHeadline, forKey: .subHeadline) - try container.encode(body, forKey: .body) - try container.encode(link, forKey: .link) + try container.encodeIfPresent(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(eyebrow, forKey: .eyebrow) + try container.encodeIfPresent(headline, forKey: .headline) + try container.encodeIfPresent(subHeadline, forKey: .subHeadline) + try container.encodeIfPresent(body, forKey: .body) + try container.encodeIfPresent(link, forKey: .link) } } From 2ec429974abd978b90adadb838a064154e99ffa0 Mon Sep 17 00:00:00 2001 From: Subhankar Acharya Date: Tue, 25 Feb 2020 21:24:04 +0530 Subject: [PATCH 83/96] removing updateView. --- .../ListOneColumnFullWidthTextAllTextAndLinks.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 4b0e2e91..9e930396 100644 --- a/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -24,12 +24,6 @@ import Foundation //----------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) - } - override open func setupView() { super.setupView() stack.stackItems = [StackItem(andContain: eyebrow), From 4ad4eb7f469226d9be57a1cb4604c2dfd856b086 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Tue, 25 Feb 2020 11:49:26 -0500 Subject: [PATCH 84/96] add new font --- MVMCoreUI.xcodeproj/project.pbxproj | 28 ++++++++------- .../Containers/NavigationController.swift | 6 ++-- .../Fonts/NHaasGroteskDSStd-45Lt.otf | Bin 62664 -> 0 bytes .../Fonts/NHaasGroteskDSStd-55Rg.otf | Bin 75048 -> 0 bytes .../Fonts/NHaasGroteskDSStd-75Bd.otf | Bin 64188 -> 0 bytes .../Fonts/VerizonNHGeDS-Bold.otf | Bin 0 -> 54172 bytes .../Fonts/VerizonNHGeDS-Regular.otf | Bin 0 -> 50284 bytes .../Fonts/VerizonNHGeTX-Bold.otf | Bin 0 -> 55316 bytes .../Fonts/VerizonNHGeTX-Regular.otf | Bin 0 -> 53776 bytes MVMCoreUI/Utility/MFFonts.h | 6 ++-- MVMCoreUI/Utility/MFFonts.m | 34 ++++++++++++++---- 11 files changed, 49 insertions(+), 25 deletions(-) delete mode 100644 MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-45Lt.otf delete mode 100644 MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf delete mode 100644 MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-75Bd.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Bold.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Regular.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Bold.otf create mode 100755 MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Regular.otf diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 3e9138f7..cb821240 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -126,6 +126,10 @@ 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; }; 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; + 94CA227C24058534002D6750 /* VerizonNHGeTX-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */; }; + 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */; }; + 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */; }; + 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 */; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -288,10 +292,7 @@ D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF14D21E693AD003B2FB9 /* MFFonts.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF14C21E693AD003B2FB9 /* MFFonts.m */; }; - D29DF31A21ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */; }; D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */; }; - D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */; }; - D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */; }; D29DF32021ED0CBA003B2FB9 /* LabelView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF31E21ED0CBA003B2FB9 /* LabelView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF31F21ED0CBA003B2FB9 /* LabelView.m */; }; D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */; }; @@ -457,6 +458,10 @@ 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = ""; }; 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; + 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Bold.otf"; sourceTree = ""; }; + 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Regular.otf"; sourceTree = ""; }; + 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Bold.otf"; sourceTree = ""; }; + 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 = ""; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = ""; }; @@ -631,10 +636,7 @@ D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoadingViewController.h; sourceTree = ""; }; D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoadingViewController.m; sourceTree = ""; }; D29DF2E021E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPanelProtocol.h; sourceTree = ""; }; - D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-45Lt.otf"; sourceTree = ""; }; D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = OCRAExtended.ttf; sourceTree = ""; }; - D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = ""; }; - D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = ""; }; D29DF31E21ED0CBA003B2FB9 /* LabelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelView.h; sourceTree = ""; }; D29DF31F21ED0CBA003B2FB9 /* LabelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LabelView.m; sourceTree = ""; }; D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextButtonView.m; sourceTree = ""; }; @@ -1410,10 +1412,11 @@ D29DF31521ECECC0003B2FB9 /* Fonts */ = { isa = PBXGroup; children = ( - D29DF31621ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf */, + 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */, + 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */, + 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */, + 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */, D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */, - D29DF31821ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf */, - D29DF31921ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf */, ); path = Fonts; sourceTree = ""; @@ -1613,14 +1616,15 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */, D29DF2AF21E7B3A4003B2FB9 /* MFTextView.xib in Resources */, - D29DF31C21ECECC0003B2FB9 /* NHaasGroteskDSStd-75Bd.otf in Resources */, - D29DF31D21ECECC0003B2FB9 /* NHaasGroteskDSStd-55Rg.otf in Resources */, 0A21DB8E235E06EF00C160A2 /* MFDigitTextField.xib in Resources */, + 94CA227C24058534002D6750 /* VerizonNHGeTX-Bold.otf in Resources */, D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, 0A21DB86235E06EF00C160A2 /* MFTextField.xib in Resources */, - D29DF31A21ECECC0003B2FB9 /* NHaasGroteskDSStd-45Lt.otf in Resources */, + 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */, D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */, + 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */, D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 623b2f47..e10f09c5 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -20,9 +20,9 @@ import UIKit navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true navigationBar.tintColor = .black - if let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 14, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 14) { - navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; - } + let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 14, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 14) + + navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; } public static func setupNavigationController() -> Self? { diff --git a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-45Lt.otf b/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-45Lt.otf deleted file mode 100644 index bddef9eb7e16ee3c6d72d91ee3ad064ad5d15b43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62664 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�=> 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

jan8MpnGKFv7c}Nl?0Cx%b?Ma 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 F{{T=I5EuXe diff --git a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf b/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf deleted file mode 100644 index f56ed7aaf89f16bad53d72034e0002639d48364e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75048 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

_D2qW`Ep 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

3x1o+N6#i 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�p+^D*}?d&IQRY`36#If$`3Wb_t9AUr? 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 N4tK2zzhVXQ{{W43)8_yH literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Regular.otf b/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeDS-Regular.otf new file mode 100755 index 0000000000000000000000000000000000000000..ce34c5964033809a6a7565f6baae1dc41a8c102f GIT binary patch literal 50284 zcmeFYcU)7+_cwlTF1a_}XjEccO}t6K0)kTQVnq=|v0y2*JC92OgnStoHOUnyl2vH(4c-) zEh?R2sQ%tQKKkUd-ft+Xp-53fvU&vi^$PY|@iRs3ETpJL>wER+=|dlE=UD~bOEmqtk@5if??JhqqDfVX`dsRKFQm5DM~Y!y zLJoDWp~Do*v)PBhKLh^k#@aJmAk9z`k_-Q!4O9N7D@AcHp*(=Kw{WtSSu4a+RDX(w zZ^}lZqnA)pN+y{n34*l0^+}JSJZMjflE_&b3HfIOWt^pP^;h410sV+x{`gb!@=qUH z!IV?CplCTMrvH%S!b4BV;oF|h{Hy}py@Imw1q(>16jvKiGh&y0}mtfu9ZOHHPluK68Zi;b=6UY)P_ zF2Bxqa@HksddJ15B}7GzG3j^fJ>1;e>HEgT#+lOMje5TrLu6EJq~0$!%thZVI$Ce3 zmZ(oKCK?lxjo~gsj0sT_;$rmyzPFj0mdYw-q&DA)b~n=GZ_=d>7x?$2E8f45N?byB#hI?Mf?x48)C!t zF@`jKs1an3j7l^a6O7^ds91fNF~MYj=h&o#sKoH7FcS!n=<=@$@E!wIOi_kdePGy_ z6hne(LJwnNRAekL3Qg1hXDR5?tyN1dPT93@8vgAu7TY8D&fa^BJRB=!sgOPAn)TIm*HaG7`Sy>T8TnHkzWs z45a@)QPpnItrzJ#IV#x@t&jUQvaqHk4Ui@v@_3#&Cqn1Oi$mW&6L5v_k!;@>54 z(fdVw<7$Xa(~nOAKPK@9+Qvd)ime`C!q>1%2Aeo0E-9K!(&Q*(ip4?xT~>%2M)0|C zYb+r{`>Fz~m|+mdAbKRk>SN--OV`a+FZ_%lJRc*+PlepC!)fZ9=zA8AR)Qel(}P~E6# z_~^gmmS{;CsYGa*KqbR>IMf_sNkvf;EWGtp0Od>df|^FE2Ng&Sgl8m`1e^@e#vSUr zSw0;>mVQvTA1pTh&cWK=+PdXG+W)=gKl{@EYwbiB8yU6!uipR8<^R-Q07#z%e|i{` z0X{?nyI}2#}d* zgy_IJ`;3rkVHt(hTdaJDjmTJ%q4b+X)*2-L-(>Z*F{|q8oVs z*Kw0RlA$(<5pn-&voOeyfe(@8>n!}XA_pPbcF^fu|AXIO(6rMoO$@L|Rh%Eeijq_gbyr9cq!8WQ|WG#t^HK zK3#yL2|n>u2g(&bDVC25jPmah+y%x$#%`5>#3wS&SZJvSUc_Tf(30qtcoeY&iBnep ziiceC#<0pjM*rVNE8>B~_T-z4{VNAD$4E~G=syB_jfOv>S*vA?7WqgWt4Hf8N6RS4 z`{wIBB>or;79lUw zVfD2bi_}&vkaaJI%{YoDYat2F;7 z`w*Y8N43ZwNc#@Z>i_R;Lx4gHs>#5!9znD$PaEbbJk#OB!jl60cMA0By(TZ3CN{m{u=2e`{1e;!G4zi= z|NOIB0zI{fcBi|61Ow^OAi-pi;0j1^?>h;U`Ud(&dc8#g4}E)!1SWm@cM=5J4YylT zEkRw7py6KoI)!*|_Er-vC2(<$m<$A=ydo#0sq{(g8UulTtF(A)=k zsqQ$LADCv9q+vB?I*D#af1*DFu=|-d!}oW8)?Udsl>H(3ic){e z{u@PGFm9*|&#yF4fRg|7A6-5MIu$&32K74~NPVC^==#(%x*@Hl)wGTtME9Y?>Auu*x+b9S zf6@W;7`i|0M&(iYbO`N5`%^FJQ0gYNg04lCQg^5_>IEeO^q!@7z@}>e-mU;_+?G

y76(UbB4{Jj?hI)B(I4~C^{ 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 literal 0 HcmV?d00001 diff --git a/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Bold.otf b/MVMCoreUI/SupportingFiles/Fonts/VerizonNHGeTX-Bold.otf new file mode 100755 index 0000000000000000000000000000000000000000..59b1f438744b24d3f81258a69e52fac419e39a86 GIT binary patch literal 55316 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 MLDurIPMCxIKZ(ilegFUf literal 0 HcmV?d00001 diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index 484e2c82..28e502c6 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -12,9 +12,9 @@ @interface MFFonts : NSObject -+ (nullable UIFont *)mfFont75Bd:(CGFloat)size; -+ (nullable UIFont *)mfFont55Rg:(CGFloat)size; ++ (nonnull UIFont *)mfFont75Bd:(CGFloat)size; ++ (nonnull UIFont *)mfFont55Rg:(CGFloat)size; + (nullable UIFont *)mfFontOcratxt:(CGFloat)size; -+ (nullable UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; ++ (nonnull UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; @end diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 65326e6c..264dcf18 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -11,13 +11,21 @@ #import "MVMCoreUIUtility.h" @import MVMCore.MVMCoreLoggingHandler; +static NSString * const DSBold = @"VerizonNHGeDS-Bold"; +static NSString * const DSRegular = @"VerizonNHGeDS-Regular"; +static NSString * const TXBold = @"VerizonNHGeTX-Bold"; +static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; + + @implementation MFFonts + (void)loadMVMFonts { static dispatch_once_t once; dispatch_once(&once, ^{ - [MFFonts loadFont:@"NHaasGroteskDSStd-75Bd" type:@"otf"]; - [MFFonts loadFont:@"NHaasGroteskDSStd-55Rg" type:@"otf"]; + [MFFonts loadFont:DSBold type:@"otf"]; + [MFFonts loadFont:DSRegular type:@"otf"]; + [MFFonts loadFont:TXBold type:@"otf"]; + [MFFonts loadFont:TXRegular type:@"otf"]; [MFFonts loadFont:@"OCRAExtended" type:@"ttf"]; }); } @@ -39,14 +47,26 @@ CFRelease(provider); } -+ (nullable UIFont *)mfFont75Bd:(CGFloat)size { ++ (UIFont *)mfFont75Bd:(CGFloat)size { [self loadMVMFonts]; - return [UIFont fontWithName:@"NHaasGroteskDSStd-75Bd" size:size]; + UIFont *font; + if (size >= 15) { + font = [UIFont fontWithName:DSBold size:size]; + } else { + font = [UIFont fontWithName:TXBold size:size]; + } + return font ?: [UIFont boldSystemFontOfSize:size]; } -+ (nullable UIFont *)mfFont55Rg:(CGFloat)size { ++ (UIFont *)mfFont55Rg:(CGFloat)size { [self loadMVMFonts]; - return [UIFont fontWithName:@"NHaasGroteskDSStd-55Rg" size:size]; + UIFont *font; + if (size >= 15) { + font = [UIFont fontWithName:DSRegular size:size]; + } else { + font = [UIFont fontWithName:TXRegular size:size]; + } + return font ?: [UIFont systemFontOfSize:size]; } + (nullable UIFont *)mfFontOcratxt:(CGFloat)size { @@ -54,7 +74,7 @@ return [UIFont fontWithName:@"OCRAExtended" size:size]; } -+ (nullable UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size { ++ (UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size { return [UIFont fontWithName:name size:size] ?: [self mfFont55Rg:size]; } From 455507626cda24a3c6021d62e5082dd6baf7d206 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Tue, 25 Feb 2020 13:59:24 -0500 Subject: [PATCH 85/96] add new fonts method, change font from nullable to non null for better swift typing --- MVMCoreUI/Atoms/Views/Label/Label.swift | 145 +++++++++ MVMCoreUI/Styles/MFStyler.h | 120 ++++++- MVMCoreUI/Styles/MFStyler.m | 402 +++++++++++++++++++++++- MVMCoreUI/Utility/MFFonts.h | 9 + MVMCoreUI/Utility/MFFonts.m | 25 +- 5 files changed, 695 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index f08d532d..5e11e116 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -132,6 +132,89 @@ public typealias ActionBlock = () -> () // MARK: - Factory Functions //------------------------------------------------------ + /// Title 2XLarge + @objc public static func commonLabelTitle2XLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleTitle2XLarge(scale) + return label + } + + /// TitleXLarge + @objc public static func commonLabelTitleXLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleTitleXLarge(scale) + return label + } + + /// BoldTitleLarge + @objc public static func commonLabelBoldTitleLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldTitleLarge(scale) + return label + } + + /// RegularTitleLarge + @objc public static func commonLabelRegularTitleLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularTitleLarge(scale) + return label + } + + /// BoldTitleMedium + @objc public static func commonLabelBoldTitleMedium(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldTitleMedium(scale) + return label + } + + /// RegularTitleMedium + @objc public static func commonLabelRegularTitleMedium(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularTitleMedium(scale) + return label + } + + /// BoldBodyLarge + @objc public static func commonLabelBoldBodyLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldBodyLarge(scale) + return label + } + + /// RegularBodyLarge + @objc public static func commonLabelRegularBodyLarge(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularBodyLarge(scale) + return label + } + + /// BoldBodySmall + @objc public static func commonLabelBoldBodySmall(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldBodySmall(scale) + return label + } + + /// RegularBodySmall + @objc public static func commonLabelRegularBodySmall(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularBodySmall(scale) + return label + } + /// BoldMicro + @objc public static func commonLabelBoldMicro(_ scale: Bool) -> Label { + let label = Label.label() + label.styleBoldMicro(scale) + return label + } + /// RegularMicro + @objc public static func commonLabelRegularMicro(_ scale: Bool) -> Label { + let label = Label.label() + label.styleRegularMicro(scale) + return label + } + + //2.0 fonts init methods /// H1 -> HeadlineLarge @objc public static func commonLabelH1(_ scale: Bool) -> Label { let label = Label.label() @@ -481,6 +564,68 @@ public typealias ActionBlock = () -> () // MARK: - Methods //------------------------------------------------------ + //mva 3.0 font + @objc public func styleTitle2XLarge(_ scale: Bool) { + MFStyler.styleLabelTitle2XLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleTitleXLarge(_ scale: Bool) { + MFStyler.styleLabelTitleXLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldTitleLarge(_ scale: Bool) { + MFStyler.styleLabelBoldTitleLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularTitleLarge(_ scale: Bool) { + MFStyler.styleLabelRegularTitleLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldTitleMedium(_ scale: Bool) { + MFStyler.styleLabelBoldTitleMedium(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularTitleMedium(_ scale: Bool) { + MFStyler.styleLabelRegularTitleMedium(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldBodyLarge(_ scale: Bool) { + MFStyler.styleLabelBoldBodyLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularBodyLarge(_ scale: Bool) { + MFStyler.styleLabelRegularBodyLarge(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldBodySmall(_ scale: Bool) { + MFStyler.styleLabelBoldBodySmall(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularBodySmall(_ scale: Bool) { + MFStyler.styleLabelRegularBodySmall(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleBoldMicro(_ scale: Bool) { + MFStyler.styleLabelBoldMicro(self, genericScaling: false) + setScale(scale) + } + + @objc public func styleRegularMicro(_ scale: Bool) { + MFStyler.styleLabelRegularMicro(self, genericScaling: false) + setScale(scale) + } + + //2.0 fonts @objc public func styleH1(_ scale: Bool) { MFStyler.styleLabelH1(self, genericScaling: false) setScale(scale) diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index bdef57ba..eb89312c 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -98,6 +98,46 @@ B3 -> Legal //------------------------------------------------- // Returns the fonts for these styles. Scales them as needed by default + +#pragma mark - 3.0 fonts +///Bold 36pt ++ (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontTitle2XLarge; +///Bold 32pt ++ (nonnull UIFont *)fontTitleXLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontTitleXLarge; +///Bold 24pt ++ (nonnull UIFont *)fontBoldTitleLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldTitleLarge; +///Regular 24pt ++ (nonnull UIFont *)fontRegularTitleLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularTitleLarge; +///Bold 20pt ++ (nonnull UIFont *)fontBoldTitleMedium:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldTitleMedium; +///Regular 20pt ++ (nonnull UIFont *)fontRegularTitleMedium:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularTitleMedium; +///Bold 16pt ++ (nonnull UIFont *)fontBoldBodyLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldBodyLarge; +///Regular 16pt ++ (nonnull UIFont *)fontRegularBodyLarge:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularBodyLarge; +///Bold 13pt ++ (nonnull UIFont *)fontBoldBodySmall:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldBodySmall; +///Regular 13pt ++ (nonnull UIFont *)fontRegularBodySmall:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularBodySmall; +///Bold 11pt ++ (nonnull UIFont *)fontBoldMicro:(BOOL)genericScaling; ++ (nonnull UIFont *)fontBoldMicro; +///Regular 11pt ++ (nonnull UIFont *)fontRegularMicro:(BOOL)genericScaling; ++ (nonnull UIFont *)fontRegularMicro; + + #pragma mark - 2.0 fonts //75Bd 40pt @@ -206,9 +246,50 @@ B3 -> Legal //------------------------------------------------- // Applies the styles to the passed in objects. +#pragma mark - 3.0 Styles + ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label; + ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label; + ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label; + ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label; + ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label; + ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label; + ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label; + ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label; + ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label; + ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label; + ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label; + ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label; + +/// Will style the label with mva 3.0 fonts based on the string. ++ (BOOL)styleMVA3Label:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; + #pragma mark - 2.0 styles -/// Will style the label based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20 +/// Will style the label based on the string. Accepted values, including mva3.0 fonts and 2.0 fonts H1, H2, H3, H32, B1, B2, B3, B20 + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style; + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; @@ -257,6 +338,43 @@ B3 -> Legal #pragma mark - Attributed Strings ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + + /// Will style the string based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20 + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style; + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index c3dc8946..69a04b3e 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -111,6 +111,152 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; }]; } +#pragma mark - 3.0 fonts + ++ (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling { + CGFloat size = 36; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontTitle2XLarge { + return [self fontTitle2XLarge:YES]; +} + ++ (nonnull UIFont *)fontTitleXLarge:(BOOL)genericScaling { + CGFloat size = 32; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} ++ (nonnull UIFont *)fontTitleXLarge{ + return [self fontTitleXLarge:YES]; +} + ++ (nonnull UIFont *)fontBoldTitleLarge:(BOOL)genericScaling { + CGFloat size = 24; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldTitleLarge { + return [self fontBoldTitleLarge:YES]; +} + ++ (nonnull UIFont *)fontRegularTitleLarge:(BOOL)genericScaling { + CGFloat size = 24; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularTitleLarge { + return [self fontRegularTitleLarge:YES]; +} + ++ (nonnull UIFont *)fontBoldTitleMedium:(BOOL)genericScaling { + CGFloat size = 20; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldTitleMedium { + return [self fontBoldTitleMedium:YES]; +} + ++ (nonnull UIFont *)fontRegularTitleMedium:(BOOL)genericScaling { + CGFloat size = 20; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularTitleMedium { + return [self fontRegularTitleMedium:YES]; +} + ++ (nonnull UIFont *)fontBoldBodyLarge:(BOOL)genericScaling { + CGFloat size = 16; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldBodyLarge { + return [self fontBoldBodyLarge:YES]; +} + ++ (nonnull UIFont *)fontRegularBodyLarge:(BOOL)genericScaling { + CGFloat size = 16; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularBodyLarge { + return [self fontRegularBodyLarge:YES]; +} + ++ (nonnull UIFont *)fontBoldBodySmall:(BOOL)genericScaling { + CGFloat size = 13; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldBodySmall { + return [self fontBoldBodySmall:YES]; +} + ++ (nonnull UIFont *)fontRegularBodySmall:(BOOL)genericScaling { + CGFloat size = 13; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularBodySmall { + return [self fontRegularBodySmall:YES]; +} + ++ (nonnull UIFont *)fontBoldMicro:(BOOL)genericScaling { + CGFloat size = 11; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont75Bd:size]; +} + ++ (nonnull UIFont *)fontBoldMicro { + return [self fontBoldMicro:YES]; +} + ++ (nonnull UIFont *)fontRegularMicro:(BOOL)genericScaling { + CGFloat size = 11; + if (genericScaling) { + size = [self sizeFontGenericForCurrentDevice:size]; + } + return [MFFonts mfFont55Rg:size]; +} + ++ (nonnull UIFont *)fontRegularMicro { + return [self fontRegularMicro:YES]; +} + + #pragma mark - 2.0 fonts + (nullable UIFont *)fontH1:(BOOL)genericScaling { @@ -514,10 +660,165 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; return [MFFonts mfFont55Rg:[self sizeFontGenericForCurrentDevice:size]]; } +#pragma mark - 3.0 Styles + ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontTitle2XLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelTitle2XLarge:(nonnull UILabel *)label { + [self styleLabelTitle2XLarge:label genericScaling:YES]; +} + ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontTitleXLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelTitleXLarge:(nonnull UILabel *)label { + [self styleLabelTitleXLarge:label genericScaling:YES]; +} + ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldTitleLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldTitleLarge:(nonnull UILabel *)label { + [self styleLabelBoldTitleLarge:label genericScaling:YES]; +} + ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularTitleLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularTitleLarge:(nonnull UILabel *)label { + [self styleLabelBoldTitleLarge:label genericScaling:YES]; +} + ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldTitleMedium:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldTitleMedium:(nonnull UILabel *)label { + [self styleLabelBoldTitleMedium:label genericScaling:YES]; +} + ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularTitleMedium:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularTitleMedium:(nonnull UILabel *)label { + [self styleLabelRegularTitleMedium:label genericScaling:YES]; +} + ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldBodyLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldBodyLarge:(nonnull UILabel *)label { + [self styleLabelBoldBodyLarge:label genericScaling:YES]; +} + ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularBodyLarge:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularBodyLarge:(nonnull UILabel *)label { + [self styleLabelRegularBodyLarge:label genericScaling:YES]; +} + ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldBodySmall:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldBodySmall:(nonnull UILabel *)label { + [self styleLabelBoldBodySmall:label genericScaling:YES]; +} + ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularBodySmall:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularBodySmall:(nonnull UILabel *)label { + [self styleLabelRegularBodySmall:label genericScaling:YES]; +} + ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontBoldMicro:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelBoldMicro:(nonnull UILabel *)label { + [self styleLabelBoldMicro:label genericScaling:YES]; +} + ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { + label.font = [MFStyler fontRegularMicro:genericScaling]; + label.textColor = [UIColor blackColor]; +} + ++ (void)styleLabelRegularMicro:(nonnull UILabel *)label { + [self styleLabelRegularMicro:label genericScaling:YES]; +} + ++ (BOOL)styleMVA3Label:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling { + if ([style isEqualToString:@"Title2XLarge"]) { + [self styleLabelTitle2XLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"TitleXLarge"]) { + [self styleLabelTitleXLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldTitleLarge"]) { + [self styleLabelBoldTitleLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularTitleLarge"]) { + [self styleLabelRegularTitleLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldTitleMedium"]) { + [self styleLabelBoldTitleMedium:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularTitleMedium"]) { + [self styleLabelRegularTitleMedium:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldBodyLarge"]) { + [self styleLabelBoldBodyLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularBodyLarge"]) { + [self styleLabelRegularBodyLarge:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldBodySmall"]) { + [self styleLabelBoldBodySmall:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularBodySmall"]) { + [self styleLabelRegularBodySmall:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"BoldMicro"]) { + [self styleLabelBoldMicro:label genericScaling:genericScaling]; + return YES; + } else if ([style isEqualToString:@"RegularMicro"]) { + [self styleLabelRegularMicro:label genericScaling:genericScaling]; + return YES; + } else { + return NO; + } +} + + #pragma mark - 2.0 Styles + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling { - if ([style isEqualToString:@"H1"]) { + if ([self styleMVA3Label:label withStyle:style genericScaling:genericScaling]) { + //try mva 3.0 font first + } else if ([style isEqualToString:@"H1"]) { [self styleLabelH1:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"H2"]) { [self styleLabelH2:label genericScaling:genericScaling]; @@ -697,6 +998,105 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; return attributedString; } + ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetTitle2XLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontTitle2XLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetTitleXLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetTitleXLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontTitleXLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldTitleLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldTitleLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularTitleLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularTitleLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldTitleMediumAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldTitleMedium:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularTitleMediumAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularTitleMediumAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularTitleMedium:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldBodyLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldBodyLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularBodyLargeAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodyLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularBodyLarge:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldBodySmallAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldBodySmall:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularBodySmallAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularBodySmallAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularBodySmall:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string { + return [MFStyler styleGetBoldMicroAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetBoldMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontBoldMicro:genericScaling] color:[UIColor blackColor]]; +} + ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string { + return [MFStyler styleGetRegularBodySmallAttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontRegularMicro:genericScaling] color:[UIColor blackColor]]; +} + + +//2.0 font get attributedString + (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string { return [MFStyler styleGetH1AttributedString:string genericScaling:YES]; } diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index 28e502c6..ba167df1 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -12,8 +12,17 @@ @interface MFFonts : NSObject +///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold + (nonnull UIFont *)mfFont75Bd:(CGFloat)size; +///return mfFontTXRegular when size smaller than 15, otherwise, return mfFontDSRegular + (nonnull UIFont *)mfFont55Rg:(CGFloat)size; + +//mva 3.0 font, should use mfFont75Bd/55Rg in most case. ++ (nonnull UIFont *)mfFontDSBold:(CGFloat)size; ++ (nonnull UIFont *)mfFontDSRegular:(CGFloat)size; ++ (nonnull UIFont *)mfFontTXBold:(CGFloat)size; ++ (nonnull UIFont *)mfFontTXRegular:(CGFloat)size; + + (nullable UIFont *)mfFontOcratxt:(CGFloat)size; + (nonnull UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 264dcf18..09956ae4 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -47,13 +47,30 @@ static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; CFRelease(provider); } ++ (nonnull UIFont *)mfFontDSBold:(CGFloat)size { + return [UIFont fontWithName:DSBold size:size]; +} + ++ (nonnull UIFont *)mfFontDSRegular:(CGFloat)size { + return [UIFont fontWithName:DSRegular size:size]; +} + ++ (nonnull UIFont *)mfFontTXBold:(CGFloat)size { + return [UIFont fontWithName:TXBold size:size]; +} + ++ (nonnull UIFont *)mfFontTXRegular:(CGFloat)size { + return [UIFont fontWithName:TXRegular size:size]; +} + + + (UIFont *)mfFont75Bd:(CGFloat)size { [self loadMVMFonts]; UIFont *font; if (size >= 15) { - font = [UIFont fontWithName:DSBold size:size]; + font = [self mfFontDSBold:size]; } else { - font = [UIFont fontWithName:TXBold size:size]; + font = [self mfFontTXBold:size]; } return font ?: [UIFont boldSystemFontOfSize:size]; } @@ -62,9 +79,9 @@ static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; [self loadMVMFonts]; UIFont *font; if (size >= 15) { - font = [UIFont fontWithName:DSRegular size:size]; + font = [self mfFontDSRegular:size]; } else { - font = [UIFont fontWithName:TXRegular size:size]; + font = [self mfFontTXRegular:size]; } return font ?: [UIFont systemFontOfSize:size]; } From e54c87becf9f597cdfc7724a97af83576048db13 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 11:06:34 -0500 Subject: [PATCH 86/96] update font --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++++ MVMCoreUI/Atoms/Views/Label/Label.swift | 16 +++++----- MVMCoreUI/MVMCoreUI.h | 1 + MVMCoreUI/Styles/MFStyler.h | 2 ++ MVMCoreUI/Styles/MFStyler.m | 40 +++++++++++++++++-------- MVMCoreUI/Utility/MFFonts.h | 5 ++++ MVMCoreUI/Utility/MFFonts.m | 8 ++--- MVMCoreUI/Utility/UIFont+FontWrapping.h | 19 ++++++++++++ MVMCoreUI/Utility/UIFont+FontWrapping.m | 25 ++++++++++++++++ 9 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 MVMCoreUI/Utility/UIFont+FontWrapping.h create mode 100644 MVMCoreUI/Utility/UIFont+FontWrapping.m diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index cb821240..a28f633b 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -111,6 +111,8 @@ 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944589202385D6E900DE9FD4 /* DashLineModel.swift */; }; 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944589222385DA9500DE9FD4 /* ImageViewModel.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; + 9458C3172406C8FD00930963 /* UIFont+FontWrapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */; }; 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; 94AF4A3E23E9D13900676048 /* MFCaretButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF4A3C23E9D13900676048 /* MFCaretButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -445,6 +447,8 @@ 944589202385D6E900DE9FD4 /* DashLineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashLineModel.swift; sourceTree = ""; }; 944589222385DA9500DE9FD4 /* ImageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewModel.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; + 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+FontWrapping.h"; sourceTree = ""; }; + 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+FontWrapping.m"; sourceTree = ""; }; 946EE1B9237B66D80036751F /* MoleculeModelHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeModelHelper.swift; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; 94AF4A3C23E9D13900676048 /* MFCaretButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFCaretButton.h; sourceTree = ""; }; @@ -1234,6 +1238,8 @@ D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */, D29DF14D21E693AD003B2FB9 /* MFFonts.h */, D29DF14C21E693AD003B2FB9 /* MFFonts.m */, + 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */, + 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */, D29DF29F21E7AF4E003B2FB9 /* MVMCoreUIUtility.h */, D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */, D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */, @@ -1497,6 +1503,7 @@ D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */, D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */, D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */, + 9458C3172406C8FD00930963 /* UIFont+FontWrapping.h in Headers */, D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */, D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */, D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */, @@ -1674,6 +1681,7 @@ DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */, 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */, + 9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */, 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */, 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */, 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 5e11e116..70e54e45 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -350,7 +350,7 @@ public typealias ActionBlock = () -> () if let fontName = labelModel.fontName { font = MFFonts.mfFont(withName: fontName, size: fontSize ?? standardFontSize) } else if let fontSize = fontSize { - font = font.withSize(fontSize) + font = font.updateSize(fontSize) } } @@ -359,7 +359,7 @@ public typealias ActionBlock = () -> () } if let attributes = labelModel.attributes, let labelText = text { - let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.withSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor]) + let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font.updateSize(standardFontSize), NSAttributedString.Key.foregroundColor: textColor as UIColor]) for attribute in attributes { let range = NSRange(location: attribute.location, length: attribute.length) @@ -407,7 +407,7 @@ public typealias ActionBlock = () -> () if let fontName = fontAtt.name { font = MFFonts.mfFont(withName: fontName, size: fontSize ?? self.font.pointSize) } else if let fontSize = fontSize { - font = self.font.withSize(fontSize) + font = self.font.updateSize(fontSize) } if let font = font { attributedString.removeAttribute(.font, range: range) @@ -473,7 +473,7 @@ public typealias ActionBlock = () -> () if let fontName = json?.optionalStringForKey("fontName") { label.font = MFFonts.mfFont(withName: fontName, size: fontSize ?? mvmLabel?.standardFontSize ?? label.font.pointSize) } else if let fontSize = fontSize { - label.font = label.font.withSize(fontSize) + label.font = label.font.updateSize(fontSize) } } @@ -483,7 +483,7 @@ public typealias ActionBlock = () -> () if let attributes = json?.optionalArrayForKey("attributes"), let labelText = label.text { let attributedString = NSMutableAttributedString(string: labelText, - attributes: [NSAttributedString.Key.font: mvmLabel?.font.withSize(mvmLabel!.standardFontSize) ?? label.font as UIFont, + attributes: [NSAttributedString.Key.font: mvmLabel?.font.updateSize(mvmLabel!.standardFontSize) ?? label.font as UIFont, NSAttributedString.Key.foregroundColor: label.textColor as UIColor]) for case let attribute as [String: Any] in attributes { guard let attributeType = attribute.optionalStringForKey(KeyType), @@ -535,7 +535,7 @@ public typealias ActionBlock = () -> () if let fontName = attribute.optionalStringForKey("name") { font = MFFonts.mfFont(withName: fontName, size: fontSize ?? mvmLabel?.standardFontSize ?? label.font.pointSize) } else if let fontSize = fontSize { - font = label.font.withSize(fontSize) + font = label.font.updateSize(fontSize) } if let font = font { @@ -677,7 +677,7 @@ public typealias ActionBlock = () -> () originalAttributedString.enumerateAttribute(.font, in: NSRange(location: 0, length: originalAttributedString.length), options: []) { value, range, stop in if let fontObj = value as? UIFont, let stylerSize = MFStyler.sizeObjectGeneric(forCurrentDevice: fontObj.pointSize)?.getValueBased(onSize: size) { - attributedString.addAttribute(.font, value: fontObj.withSize(stylerSize) as Any, range: range) + attributedString.addAttribute(.font, value: fontObj.updateSize(stylerSize) as Any, range: range) } } @@ -693,7 +693,7 @@ public typealias ActionBlock = () -> () attributedText = attributedString } else if !MVMCoreGetterUtility.fequal(a: Float(standardFontSize), b: 0.0), let sizeObject = sizeObject ?? MFStyler.sizeObjectGeneric(forCurrentDevice: standardFontSize) { - font = font.withSize(sizeObject.getValueBased(onSize: size)) + font = font.updateSize(sizeObject.getValueBased(onSize: size)) } } diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index 1b2183aa..5e8c92cc 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -32,6 +32,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #pragma mark - Categories #import #import +#import #pragma mark - Styles #import diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index eb89312c..6accea28 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -100,6 +100,8 @@ B3 -> Legal // Returns the fonts for these styles. Scales them as needed by default #pragma mark - 3.0 fonts +///auto select corresponding font based on font size, DS for font bigger than 15 pt, TX for font smaller than 15 pt ++ (nonnull UIFont *)getMVA3FontSize:(CGFloat)size bold:(BOOL)isBold; ///Bold 36pt + (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling; + (nonnull UIFont *)fontTitle2XLarge; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 69a04b3e..55978976 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -113,12 +113,28 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - 3.0 fonts ++ (nonnull UIFont *)getMVA3FontSize:(CGFloat)size bold:(BOOL)isBold { + if (isBold) { + if (size >= 15) { + return [MFFonts mfFontDSBold:size]; + } else { + return [MFFonts mfFontTXBold:size]; + } + } else { + if (size >= 15) { + return [MFFonts mfFontDSRegular:size]; + } else { + return [MFFonts mfFontTXRegular:size]; + } + } +} + + (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling { CGFloat size = 36; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontTitle2XLarge { @@ -130,7 +146,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontTitleXLarge{ return [self fontTitleXLarge:YES]; @@ -141,7 +157,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldTitleLarge { @@ -153,7 +169,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularTitleLarge { @@ -165,7 +181,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldTitleMedium { @@ -177,7 +193,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularTitleMedium { @@ -189,7 +205,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldBodyLarge { @@ -201,7 +217,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularBodyLarge { @@ -213,7 +229,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldBodySmall { @@ -225,7 +241,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularBodySmall { @@ -237,7 +253,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont75Bd:size]; + return [self getMVA3FontSize:size bold:YES]; } + (nonnull UIFont *)fontBoldMicro { @@ -249,7 +265,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; if (genericScaling) { size = [self sizeFontGenericForCurrentDevice:size]; } - return [MFFonts mfFont55Rg:size]; + return [self getMVA3FontSize:size bold:NO]; } + (nonnull UIFont *)fontRegularMicro { diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index ba167df1..4bd1f532 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -10,6 +10,11 @@ #import #import +extern NSString * _Nonnull const DSBold; +extern NSString * _Nonnull const DSRegular; +extern NSString * _Nonnull const TXBold; +extern NSString * _Nonnull const TXRegular; + @interface MFFonts : NSObject ///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 09956ae4..964707a0 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -11,10 +11,10 @@ #import "MVMCoreUIUtility.h" @import MVMCore.MVMCoreLoggingHandler; -static NSString * const DSBold = @"VerizonNHGeDS-Bold"; -static NSString * const DSRegular = @"VerizonNHGeDS-Regular"; -static NSString * const TXBold = @"VerizonNHGeTX-Bold"; -static NSString * const TXRegular = @"VerizonNHGeTX-Regular"; +NSString * const DSBold = @"VerizonNHGeDS-Bold"; +NSString * const DSRegular = @"VerizonNHGeDS-Regular"; +NSString * const TXBold = @"VerizonNHGeTX-Bold"; +NSString * const TXRegular = @"VerizonNHGeTX-Regular"; @implementation MFFonts diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.h b/MVMCoreUI/Utility/UIFont+FontWrapping.h new file mode 100644 index 00000000..1fd3360d --- /dev/null +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.h @@ -0,0 +1,19 @@ +// +// UIFont+FontWrapping.h +// MVMCoreUI +// +// Created by Ryan on 2/26/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIFont (FontWrapping) + +- (UIFont *)updateFontSize:(CGFloat)size; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.m b/MVMCoreUI/Utility/UIFont+FontWrapping.m new file mode 100644 index 00000000..8af7783d --- /dev/null +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.m @@ -0,0 +1,25 @@ +// +// UIFont+FontWrapping.m +// MVMCoreUI +// +// Created by Ryan on 2/26/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +#import "UIFont+FontWrapping.h" +#import "MFFonts.h" +#import "MFStyler.h" +#import + +@implementation UIFont (FontWrapping) + +- (UIFont *)updateFontSize:(CGFloat)size { + if ([self.familyName isEqualToString:@"Verizon NHG eDS"] || [self.familyName isEqualToString:@"Verizon NHG eTX"]) { + return [MFStyler getMVA3FontSize:size bold:[self.fontName isEqualToString:DSBold]]; + } else { + return [self fontWithSize:size]; + } + +} + +@end From cfcff1aa6ea5a43ee3b613b7692504799de64467 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 26 Feb 2020 11:49:31 -0500 Subject: [PATCH 87/96] Top Alert Fixes for top color and status bar color --- .../TopAlert/MVMCoreUITopAlertExpandableView.m | 5 ++++- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h | 2 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 14 ++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m index f215fa0b..cc25cd9b 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m @@ -109,6 +109,7 @@ self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; UIColor *contentColor = [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; [self setupTopMessage:nil]; + self.shortView.label.textColor = contentColor; MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:self.backgroundColor contentColor:contentColor message:topAlertObject.message subMessage:nil closeButton:YES animationDelegate:animationDelegate]; [self setupTopAlertWithButton:topAlertWithButton]; [self expand:NO]; @@ -173,6 +174,7 @@ - (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle { [self setupTopMessage:topMessage]; + self.shortView.label.textColor = contentColor; MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:nil]; [self setupTopAlertWithButton:topAlertWithButton]; @@ -181,7 +183,8 @@ - (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { [self setupTopMessage:topMessage]; - + self.shortView.label.textColor = contentColor; + MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self setupTopAlertWithButton:topAlertWithButton]; } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h index ca9520f3..ec11530a 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h @@ -45,7 +45,7 @@ - (void)resetDefaultBackgroundColor:(nullable UIColor *)backgroundColor basedOnStatusBarStyle:(UIStatusBarStyle)style; // Can be subclassed for custom views. -- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor; +- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle; /// Get the background color based on the type - (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index d0a027b3..930828f6 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -98,10 +98,17 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; } } -- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor { +- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle { MVMCoreUITopAlertExpandableView *view = [[MVMCoreUITopAlertExpandableView alloc] initWithTopAlertObject:topAlertObject animationDelegate:animationDelegate viewToLayout:self.superview]; if (statusBarColor && view.shortView.label.text) { *statusBarColor = view.backgroundColor; + + if (statusBarStyle) { + CGFloat greyScale = 0; + if ([view.shortView.label.textColor getWhite:&greyScale alpha:nil]) { + *statusBarStyle = greyScale > 0.5 ? UIStatusBarStyleLightContent : UIStatusBarStyleDefault; + } + } } return view; } @@ -131,12 +138,11 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; self.topAlertClearspotView = nil; UIColor *statusBarColor = nil; - MVMCoreUITopAlertBaseView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor]; + UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault; + MVMCoreUITopAlertBaseView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle]; if (!statusBarColor) { statusBarColor = [UIColor whiteColor]; } -#warning This logic is incomplete, it is possible to show the wrong status bar color here if the background is yellow or pumpkin. - UIStatusBarStyle statusBarStyle = statusBarColor == [UIColor whiteColor] ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent; [self setStatusBarColor:statusBarColor statusBarStyle:statusBarStyle]; [self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler]; }); From 16f49329f7fae62cda52b607f7c9a18b6ae86f89 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 12:35:44 -0500 Subject: [PATCH 88/96] update create label method name --- MVMCoreUI/Atoms/Views/Label/Label.swift | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atoms/Views/Label/Label.swift index 70e54e45..6550d307 100644 --- a/MVMCoreUI/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label/Label.swift @@ -133,82 +133,82 @@ public typealias ActionBlock = () -> () //------------------------------------------------------ /// Title 2XLarge - @objc public static func commonLabelTitle2XLarge(_ scale: Bool) -> Label { + @objc public static func createLabelTitle2XLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleTitle2XLarge(scale) return label } /// TitleXLarge - @objc public static func commonLabelTitleXLarge(_ scale: Bool) -> Label { + @objc public static func createLabelTitleXLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleTitleXLarge(scale) return label } /// BoldTitleLarge - @objc public static func commonLabelBoldTitleLarge(_ scale: Bool) -> Label { + @objc public static func createLabelBoldTitleLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldTitleLarge(scale) return label } /// RegularTitleLarge - @objc public static func commonLabelRegularTitleLarge(_ scale: Bool) -> Label { + @objc public static func createLabelRegularTitleLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularTitleLarge(scale) return label } /// BoldTitleMedium - @objc public static func commonLabelBoldTitleMedium(_ scale: Bool) -> Label { + @objc public static func createLabelBoldTitleMedium(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldTitleMedium(scale) return label } /// RegularTitleMedium - @objc public static func commonLabelRegularTitleMedium(_ scale: Bool) -> Label { + @objc public static func createLabelRegularTitleMedium(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularTitleMedium(scale) return label } /// BoldBodyLarge - @objc public static func commonLabelBoldBodyLarge(_ scale: Bool) -> Label { + @objc public static func createLabelBoldBodyLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldBodyLarge(scale) return label } /// RegularBodyLarge - @objc public static func commonLabelRegularBodyLarge(_ scale: Bool) -> Label { + @objc public static func createLabelRegularBodyLarge(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularBodyLarge(scale) return label } /// BoldBodySmall - @objc public static func commonLabelBoldBodySmall(_ scale: Bool) -> Label { + @objc public static func createLabelBoldBodySmall(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldBodySmall(scale) return label } /// RegularBodySmall - @objc public static func commonLabelRegularBodySmall(_ scale: Bool) -> Label { + @objc public static func createLabelRegularBodySmall(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularBodySmall(scale) return label } /// BoldMicro - @objc public static func commonLabelBoldMicro(_ scale: Bool) -> Label { + @objc public static func createLabelBoldMicro(_ scale: Bool) -> Label { let label = Label.label() label.styleBoldMicro(scale) return label } /// RegularMicro - @objc public static func commonLabelRegularMicro(_ scale: Bool) -> Label { + @objc public static func createLabelRegularMicro(_ scale: Bool) -> Label { let label = Label.label() label.styleRegularMicro(scale) return label From 1d7fb0d219046e68a3b2b1af8b29d1719097445d Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 12:45:06 -0500 Subject: [PATCH 89/96] change font of top navigation from 14 to 13 for new design --- MVMCoreUI/Containers/NavigationController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index e10f09c5..524ec68c 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -20,7 +20,7 @@ import UIKit navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true navigationBar.tintColor = .black - let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 14, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 14) + let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 13, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 13) navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; } From 4b31b191743bfe0623e7c69ed50186969e27e823 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:00:40 -0500 Subject: [PATCH 90/96] update font --- MVMCoreUI/Containers/NavigationController.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 524ec68c..6e18e427 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -20,9 +20,7 @@ import UIKit navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true navigationBar.tintColor = .black - let font = MFFonts.mfFont75Bd(MFSizeObject(standardSize: 13, standardiPadPortraitSize: 16, iPadProLandscapeSize: 18)?.getValueBasedOnScreenSize() ?? 13) - - navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font]; + navigationBar.titleTextAttributes = [NSAttributedString.Key.font: MFStyler.fontBoldBodySmall(false)]; } public static func setupNavigationController() -> Self? { From 8ff8f9aa3ad0e8aa493784636174db0435a664d7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 26 Feb 2020 13:21:43 -0500 Subject: [PATCH 91/96] external icon convenience --- .../Atoms/Buttons/Link/ExternalLink.swift | 68 +++++++------------ .../Buttons/Link/ExternalLinkModel.swift | 2 +- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift index 3f0aa5d6..b8026f99 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -10,6 +10,12 @@ import UIKit open class ExternalLink: Link { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + private var exportImageView: UIImageView? + //-------------------------------------------------- // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- @@ -19,55 +25,33 @@ open class ExternalLink: Link { guard let model = model as? ExternalLinkModel else { return } + exportImageView?.tintColor = model.textColor.uiColor } -} - -// MARK: - MVMCoreViewProtocol -extension ExternalLink { - public override func updateView(_ size: CGFloat) { - super.updateView(size) - } + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- public override func setupView() { super.setupView() - - let imageView = UIImageView(image: MVMCoreUIUtility.imageNamed("externalLink")) - imageView.contentMode = .scaleAspectFit - imageView.translatesAutoresizingMaskIntoConstraints = false - - addSubview(imageView) - imageView.heightAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true - imageView.widthAnchor.constraint(equalToConstant: round(0.8 * titleLabel!.font.pointSize)).isActive = true + let image = MVMCoreUIUtility.imageNamed("externalLink") + exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate)) - imageView.leadingAnchor.constraint(equalTo: titleLabel!.trailingAnchor, constant: PaddingOne).isActive = true - trailingAnchor.constraint(greaterThanOrEqualTo: imageView.trailingAnchor).isActive = true + guard let exportIcon = exportImageView else { return } - imageView.bottomAnchor.constraint(equalTo: titleLabel!.lastBaselineAnchor).isActive = true + exportIcon.contentMode = .scaleAspectFit + exportIcon.translatesAutoresizingMaskIntoConstraints = false + + addSubview(exportIcon) + trailingAnchor.constraint(greaterThanOrEqualTo: exportIcon.trailingAnchor).isActive = true + + if let titleLabel = titleLabel { + let dimension = round(0.6 * titleLabel.font.pointSize) + exportIcon.heightAnchor.constraint(equalToConstant: dimension).isActive = true + exportIcon.widthAnchor.constraint(equalToConstant: dimension).isActive = true + exportIcon.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: PaddingOne).isActive = true + exportIcon.bottomAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor).isActive = true + } } } - -/* - static func getTextAttachmentFrom(url: String, dimension: CGFloat, label: Label) -> NSTextAttachment { - - let dimension = round(dimension * 0.8) - - let imageAttachment = NSTextAttachment() - imageAttachment.bounds = CGRect(x: 0, y: 0, width: dimension, height: dimension) - - DispatchQueue.global(qos: .default).async { - - guard let url = URL(string: url), - let data = try? Data(contentsOf: url) - else { return } - - DispatchQueue.main.sync { - imageAttachment.image = UIImage(data: data) - label.setNeedsDisplay() - } - } - - return imageAttachment - } - */ diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift index a7fc5211..070e501e 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift @@ -8,7 +8,7 @@ import UIKit -class ExternalLinkModel: LinkModel { +public class ExternalLinkModel: LinkModel { override public class var identifier: String { return "externalLink" From 80b2513feb58e9d674c533820d6fcdd588d7b52a Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:28:23 -0500 Subject: [PATCH 92/96] fix semi colon paste in m file --- MVMCoreUI/Containers/TabBarController/TopTabbar.m | 2 +- MVMCoreUI/Styles/MFStyler.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Containers/TabBarController/TopTabbar.m b/MVMCoreUI/Containers/TabBarController/TopTabbar.m index e9d77c77..4b89903f 100644 --- a/MVMCoreUI/Containers/TabBarController/TopTabbar.m +++ b/MVMCoreUI/Containers/TabBarController/TopTabbar.m @@ -338,7 +338,7 @@ static NSString * const COLLECTION_CELL_ID = @"cell"; #pragma mark - helper -- (void)pinHeight:(CGFloat)height; { +- (void)pinHeight:(CGFloat)height { self.heightConstraint.constant = height; [self setNeedsLayout]; [self layoutIfNeeded]; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 55978976..213c205e 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -1019,7 +1019,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; return [MFStyler styleGetTitle2XLargeAttributedString:string genericScaling:YES]; } -+ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; { ++ (nonnull NSAttributedString *)styleGetTitle2XLargeAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { return [MFStyler styleGetAttributedString:string font:[MFStyler fontTitle2XLarge:genericScaling] color:[UIColor blackColor]]; } From fcc21ebf283657f0105fd544edfe32e082bdb700 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:34:01 -0500 Subject: [PATCH 93/96] fix typo --- MVMCoreUI/Utility/MFFonts.h | 11 +++++------ MVMCoreUI/Utility/UIFont+FontWrapping.m | 4 +++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index 4bd1f532..46947581 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -17,17 +17,16 @@ extern NSString * _Nonnull const TXRegular; @interface MFFonts : NSObject -///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold -+ (nonnull UIFont *)mfFont75Bd:(CGFloat)size; -///return mfFontTXRegular when size smaller than 15, otherwise, return mfFontDSRegular -+ (nonnull UIFont *)mfFont55Rg:(CGFloat)size; - -//mva 3.0 font, should use mfFont75Bd/55Rg in most case. +//mva 3.0 font, should use MFStyler.getMVA3FontSize:bold: instead, in most case. + (nonnull UIFont *)mfFontDSBold:(CGFloat)size; + (nonnull UIFont *)mfFontDSRegular:(CGFloat)size; + (nonnull UIFont *)mfFontTXBold:(CGFloat)size; + (nonnull UIFont *)mfFontTXRegular:(CGFloat)size; +///return mfFontTXBold when size smaller than 15, otherwise, return mfFontDSBold ++ (nonnull UIFont *)mfFont75Bd:(CGFloat)size; +///return mfFontTXRegular when size smaller than 15, otherwise, return mfFontDSRegular ++ (nonnull UIFont *)mfFont55Rg:(CGFloat)size; + (nullable UIFont *)mfFontOcratxt:(CGFloat)size; + (nonnull UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size; diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.m b/MVMCoreUI/Utility/UIFont+FontWrapping.m index 8af7783d..a3fa2429 100644 --- a/MVMCoreUI/Utility/UIFont+FontWrapping.m +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.m @@ -14,8 +14,10 @@ @implementation UIFont (FontWrapping) - (UIFont *)updateFontSize:(CGFloat)size { - if ([self.familyName isEqualToString:@"Verizon NHG eDS"] || [self.familyName isEqualToString:@"Verizon NHG eTX"]) { + if ([self.familyName isEqualToString:@"Verizon NHG eDS"]) { return [MFStyler getMVA3FontSize:size bold:[self.fontName isEqualToString:DSBold]]; + } else if ([self.familyName isEqualToString:@"Verizon NHG eTX"]) { + return [MFStyler getMVA3FontSize:size bold:[self.fontName isEqualToString:TXBold]]; } else { return [self fontWithSize:size]; } From a96427b79322fb443d4d9391eb60f930e970c3bc Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 13:36:20 -0500 Subject: [PATCH 94/96] add comment --- MVMCoreUI/Utility/UIFont+FontWrapping.h | 1 + MVMCoreUI/Utility/UIFont+FontWrapping.m | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.h b/MVMCoreUI/Utility/UIFont+FontWrapping.h index 1fd3360d..0302e25e 100644 --- a/MVMCoreUI/Utility/UIFont+FontWrapping.h +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.h @@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface UIFont (FontWrapping) +///if using mva3.0 font, should call this method to update font size. When size is bigger than 15 pt, using DS font family. Otherwise using TX font family - (UIFont *)updateFontSize:(CGFloat)size; @end diff --git a/MVMCoreUI/Utility/UIFont+FontWrapping.m b/MVMCoreUI/Utility/UIFont+FontWrapping.m index a3fa2429..8eedbb01 100644 --- a/MVMCoreUI/Utility/UIFont+FontWrapping.m +++ b/MVMCoreUI/Utility/UIFont+FontWrapping.m @@ -21,7 +21,6 @@ } else { return [self fontWithSize:size]; } - } @end From 1fa8cfd16ab750358e1d03aed16096be7a838e0e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 26 Feb 2020 13:39:44 -0500 Subject: [PATCH 95/96] opening up funcs --- MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift | 6 +++--- MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift | 4 ++-- MVMCoreUI/Atoms/Buttons/Link/Link.swift | 8 ++++---- MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift index b8026f99..d6374d78 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLink.swift @@ -14,13 +14,13 @@ open class ExternalLink: Link { // MARK: - Properties //-------------------------------------------------- - private var exportImageView: UIImageView? + public var exportImageView: UIImageView? //-------------------------------------------------- // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? ExternalLinkModel else { return } @@ -32,7 +32,7 @@ open class ExternalLink: Link { // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - public override func setupView() { + open override func setupView() { super.setupView() let image = MVMCoreUIUtility.imageNamed("externalLink") diff --git a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift index 070e501e..f492a546 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/ExternalLinkModel.swift @@ -8,9 +8,9 @@ import UIKit -public class ExternalLinkModel: LinkModel { +open class ExternalLinkModel: LinkModel { - override public class var identifier: String { + override open class var identifier: String { return "externalLink" } } diff --git a/MVMCoreUI/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atoms/Buttons/Link/Link.swift index a0e2583c..05d19454 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/Link.swift @@ -40,7 +40,7 @@ import UIKit // MARK: - ModelMoleculeViewProtocol //-------------------------------------------------- - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? LinkModel else { return } @@ -60,7 +60,7 @@ import UIKit // MARK: - MVMCoreViewProtocol extension Link { - public override func updateView(_ size: CGFloat) { + open override func updateView(_ size: CGFloat) { super.updateView(size) DispatchQueue.main.async { [weak self] in guard let self = self else { return } @@ -72,7 +72,7 @@ extension Link { } } - public override func setupView() { + open override func setupView() { super.setupView() backgroundColor = .clear contentMode = .redraw @@ -88,7 +88,7 @@ extension Link { // MARK: - MVMCoreUIViewConstrainingProtocol extension Link: MVMCoreUIViewConstrainingProtocol { - public func horizontalAlignment() -> UIStackView.Alignment { + open func horizontalAlignment() -> UIStackView.Alignment { return .leading } } diff --git a/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift index 5a58decd..6e7fc83d 100644 --- a/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/Link/LinkModel.swift @@ -8,7 +8,7 @@ import UIKit -public class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { +open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- From 6efbd196a876a1814663b048c6d67751b425b110 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Wed, 26 Feb 2020 14:02:26 -0500 Subject: [PATCH 96/96] add error log --- MVMCoreUI/Utility/MFFonts.m | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 964707a0..0a73fb36 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -10,6 +10,7 @@ #import #import "MVMCoreUIUtility.h" @import MVMCore.MVMCoreLoggingHandler; +@import MVMCore.MVMCoreErrorConstants; NSString * const DSBold = @"VerizonNHGeDS-Bold"; NSString * const DSRegular = @"VerizonNHGeDS-Regular"; @@ -48,19 +49,27 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; } + (nonnull UIFont *)mfFontDSBold:(CGFloat)size { - return [UIFont fontWithName:DSBold size:size]; + UIFont *font = [UIFont fontWithName:DSBold size:size]; + [self validFont:font fontName:DSBold]; + return font ?: [UIFont boldSystemFontOfSize:size]; } + (nonnull UIFont *)mfFontDSRegular:(CGFloat)size { - return [UIFont fontWithName:DSRegular size:size]; + UIFont *font = [UIFont fontWithName:DSRegular size:size]; + [self validFont:font fontName:DSRegular]; + return font ?: [UIFont systemFontOfSize:size]; } + (nonnull UIFont *)mfFontTXBold:(CGFloat)size { - return [UIFont fontWithName:TXBold size:size]; + UIFont *font = [UIFont fontWithName:TXBold size:size]; + [self validFont:font fontName:TXBold]; + return font ?: [UIFont boldSystemFontOfSize:size]; } + (nonnull UIFont *)mfFontTXRegular:(CGFloat)size { - return [UIFont fontWithName:TXRegular size:size]; + UIFont *font = [UIFont fontWithName:TXRegular size:size]; + [self validFont:font fontName:TXRegular]; + return font ?: [UIFont systemFontOfSize:size]; } @@ -72,7 +81,7 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; } else { font = [self mfFontTXBold:size]; } - return font ?: [UIFont boldSystemFontOfSize:size]; + return font; } + (UIFont *)mfFont55Rg:(CGFloat)size { @@ -83,16 +92,26 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; } else { font = [self mfFontTXRegular:size]; } - return font ?: [UIFont systemFontOfSize:size]; + return font; } + (nullable UIFont *)mfFontOcratxt:(CGFloat)size { [self loadMVMFonts]; - return [UIFont fontWithName:@"OCRAExtended" size:size]; + UIFont *font = [UIFont fontWithName:@"OCRAExtended" size:size]; + [self validFont:font fontName:@"OCRAExtended"]; + return font; } + (UIFont *)mfFontWithName:(nonnull NSString *)name size:(CGFloat)size { - return [UIFont fontWithName:name size:size] ?: [self mfFont55Rg:size]; + UIFont *font = [UIFont fontWithName:name size:size]; + [self validFont:font fontName:name]; + return font ?: [self mfFont55Rg:size]; } ++ (void)validFont:(UIFont *)font fontName:(NSString *)fontName { + if (font == nil) { + MVMCoreErrorObject *errorObject = [[MVMCoreErrorObject alloc] initWithTitle:@"font can not load" message:[NSString stringWithFormat:@"missing font name is %@", fontName] code:ErrorCodeFontNotFound domain:ErrorDomainNative location:@"MFStyler"]; + [MVMCoreLoggingHandler addErrorToLog:errorObject]; + } +} @end