From 5834b8fcd2fcaa2a87c064a6daa8f0e269e46ed6 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 6 Mar 2024 14:19:46 -0600 Subject: [PATCH 01/12] fixed issue where users set the textColor property directly Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 37eff177..e7c7e8bc 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -46,6 +46,14 @@ public typealias ActionBlock = () -> () return !text.isEmpty || !attributedText.string.isEmpty } + open override var textColor: UIColor! { + didSet { + if let textColor { + textColorConfiguration = SurfaceColorConfiguration(textColor, textColor).eraseToAnyColorable() + } + } + } + //------------------------------------------------------ // MARK: - Convenience Setter For objective-C //------------------------------------------------------ From deac7b37f0dfdfd19401a5c9691c0ea27d5b96c8 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Fri, 8 Mar 2024 18:05:23 +0530 Subject: [PATCH 02/12] ecoding & decoding fillContainer param in TwoButtonView molecule --- .../HorizontalCombinationViews/TwoButtonViewModel.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index c2cad75a..0ed1db11 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -38,6 +38,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { case backgroundColor case primaryButton case secondaryButton + case fillContainer } //-------------------------------------------------- @@ -69,6 +70,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { try decoder.setContext(value: Use.secondary, for: "style") { self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton) } + fillContainer = try typeContainer.decodeIfPresent(Bool.self, forKey: .fillContainer) ?? false } public func encode(to encoder: Encoder) throws { @@ -78,5 +80,6 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(primaryButton, forKey: .primaryButton) try container.encodeIfPresent(secondaryButton, forKey: .secondaryButton) + try container.encodeIfPresent(fillContainer, forKey: .fillContainer) } } From dcb5b91e32d28c48b9d8433fcd2033eb3fda451c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 14:03:05 -0600 Subject: [PATCH 03/12] deleted method and refactored atomic label even more Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/Label/Label.swift | 34 ++----------------- .../Atomic/Extensions/VDS-TextStyle.swift | 9 ----- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index e7c7e8bc..7d05bc3b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -46,14 +46,6 @@ public typealias ActionBlock = () -> () return !text.isEmpty || !attributedText.string.isEmpty } - open override var textColor: UIColor! { - didSet { - if let textColor { - textColorConfiguration = SurfaceColorConfiguration(textColor, textColor).eraseToAnyColorable() - } - } - } - //------------------------------------------------------ // MARK: - Convenience Setter For objective-C //------------------------------------------------------ @@ -229,7 +221,6 @@ public typealias ActionBlock = () -> () } if let style = viewModel.fontStyle?.vdsTextStyle() { - font = style.font textStyle = style } else if let fontName = viewModel.fontName { // there is a TextStyle.defaultStyle @@ -237,9 +228,8 @@ public typealias ActionBlock = () -> () if let fontSize { standardFontSize = fontSize } - if let customStyle = style(for: fontName, pointSize: fontSize ?? standardFontSize), customStyle != textStyle { - font = customStyle.font - textStyle = customStyle + if let newFont = UIFont(name: fontName, size: fontSize ?? standardFontSize) { + font = newFont } } @@ -256,26 +246,6 @@ public typealias ActionBlock = () -> () } } - - /// See if the font that is currently set matches a VDS Font and if so grab the matching TextStyle or create custom TextStyle that - /// that the Label will use moving forward. - private func checkforFontChange() { - guard let customStyle = style(for: font.fontName, pointSize: font.pointSize), customStyle != textStyle - else { return } - textStyle = customStyle - } - - private func style(for fontName: String, pointSize: CGFloat) -> TextStyle? { - guard let vdsFont = Font.from(fontName: fontName), - let customStyle = TextStyle.style(from: vdsFont, pointSize: pointSize) - else { return nil } - return customStyle - } - - open override func updateView() { - checkforFontChange() - super.updateView() - } open override func updateAccessibility() { super.updateAccessibility() diff --git a/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift b/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift index f7e5917e..2d24c5a1 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift @@ -54,12 +54,3 @@ extension VDS.Font { Self.allCases.filter({$0.fontName == fontName }).first } } - -extension VDS.TextStyle { - internal static func style(from font: VDS.Font, pointSize: CGFloat) -> TextStyle? { - guard let first = allCases.filter({$0.fontFace == font && $0.pointSize == pointSize}).first else { - return TextStyle(rawValue: "Custom-TextStyle", fontFace: font, pointSize: pointSize) - } - return first - } -} From b638637af7350307c0b68e64df20d01bda2c53eb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 14:20:44 -0600 Subject: [PATCH 04/12] removed code and call the code that does the same thing under the hood. Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/Label/Label.swift | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 7d05bc3b..0b12b5a9 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -182,29 +182,7 @@ public typealias ActionBlock = () -> () } @objc public func resetAttributeStyle() { - /* - * This is to address a reuse issue with iOS 13 and up. - * Even if you set text & attributedText to nil, the moment you set text with a value, - * attributedText will hold a dirty value from a previously reused cell even if reset() is - * appropriately called. - * Only other reference found of issue: https://www.thetopsites.net/article/58142205.shtml - */ - if let text = text, !text.isEmpty { - - //create the primary string - let mutableText = NSMutableAttributedString.mutableText(for: text, - textStyle: textStyle, - useScaledFont: useScaledFont, - textColor: textColorConfiguration.getColor(self), - alignment: textAlignment, - lineBreakMode: lineBreakMode) - - if let attributes = attributes { - mutableText.apply(attributes: attributes) - } - - self.attributedText = mutableText - } + setNeedsUpdate() } public func viewModelDidUpdate() { From 2877534c704cb346628c3c04dcca7a9b87ce8b59 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Fri, 8 Mar 2024 16:45:11 -0500 Subject: [PATCH 05/12] Hide and show the carousel pager based upon the content size. --- .../Atomic/Organisms/Carousel/Carousel.swift | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 421c2e95..a9fcc040 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -55,6 +55,9 @@ open class Carousel: View { /// The view that we use for paging public var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? + /// The pagingView anchor to the bottom of the carousel. Disabled when the pagingView is hidden. + public var pagingBottomPin: NSLayoutConstraint? + /// If the carousel should loop after scrolling past the first and final cells. public var loop = false @@ -89,10 +92,16 @@ open class Carousel: View { // Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled. guard let model = model as? CarouselModel, !model.molecules.isEmpty, (model.paging == true || loop == true) else { return } - DispatchQueue.main.async { - self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false) - self.collectionView.layoutIfNeeded() - self.showPeaking(true) + DispatchQueue.main.async { [self] in + collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: false) + collectionView.layoutIfNeeded() + showPeaking(true) + + let shouldHidePager = model.molecules.isEmpty || collectionView.contentSize.width < bounds.width + if let pagingView = pagingView, shouldHidePager != pagingView.isHidden { + pagingView.isHidden = shouldHidePager + pagingBottomPin?.isActive = !shouldHidePager + } } } @@ -276,7 +285,8 @@ open class Carousel: View { addSubview(pagingView) pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true + pagingBottomPin = bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor) + pagingBottomPin?.isActive = true bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.priority = .defaultLow bottomPin?.isActive = true From 73d13ba37b0a51b2eda83b22d186f7f096c999ab Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Fri, 8 Mar 2024 16:53:40 -0500 Subject: [PATCH 06/12] Pager should still hide on the empty condition. --- .../Atomic/Organisms/Carousel/Carousel.swift | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index a9fcc040..0328e1ff 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -96,12 +96,6 @@ open class Carousel: View { collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: false) collectionView.layoutIfNeeded() showPeaking(true) - - let shouldHidePager = model.molecules.isEmpty || collectionView.contentSize.width < bounds.width - if let pagingView = pagingView, shouldHidePager != pagingView.isHidden { - pagingView.isHidden = shouldHidePager - pagingBottomPin?.isActive = !shouldHidePager - } } } @@ -146,6 +140,15 @@ open class Carousel: View { (cell as? MVMCoreViewProtocol)?.updateView(size) } layoutCollection() + + // Check must be dispatched to main for the layout to complete in layoutCollection. + DispatchQueue.main.async { [self] in + let shouldHidePager = molecules?.isEmpty ?? true || collectionView.contentSize.width < bounds.width + if let pagingView = pagingView, shouldHidePager != pagingView.isHidden { + pagingView.isHidden = shouldHidePager + pagingBottomPin?.isActive = !shouldHidePager + } + } } //-------------------------------------------------- From 959bdce13f57b78bf71edce5dfab2462b547a817 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Mon, 11 Mar 2024 10:45:55 -0400 Subject: [PATCH 07/12] Code review. Include the only 1 element condition to the carousel pager logic. --- MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 0328e1ff..5dd4612b 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -143,7 +143,7 @@ open class Carousel: View { // Check must be dispatched to main for the layout to complete in layoutCollection. DispatchQueue.main.async { [self] in - let shouldHidePager = molecules?.isEmpty ?? true || collectionView.contentSize.width < bounds.width + let shouldHidePager = molecules?.count ?? 0 < 2 || collectionView.contentSize.width < bounds.width if let pagingView = pagingView, shouldHidePager != pagingView.isHidden { pagingView.isHidden = shouldHidePager pagingBottomPin?.isActive = !shouldHidePager From 19b4fb308c0d3dfa989b77ebe3db4915f30e9693 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Mon, 11 Mar 2024 14:11:17 -0400 Subject: [PATCH 08/12] Code review -- Update of molecule layout change when pager is state changes. --- MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 5dd4612b..c4f7d825 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -147,6 +147,7 @@ open class Carousel: View { if let pagingView = pagingView, shouldHidePager != pagingView.isHidden { pagingView.isHidden = shouldHidePager pagingBottomPin?.isActive = !shouldHidePager + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) } } } From bfe209305d489de1b9c1ee40deb44c0211a0df8c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 15:36:40 -0500 Subject: [PATCH 09/12] added heightConstraint for the twobutton Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/TwoButtonView.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 4785cfb9..34e0bd11 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -17,11 +17,11 @@ import VDS open var viewModel: TwoButtonViewModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - + open var primaryButton = PillButton() open var secondaryButton = PillButton() private var buttonGroup = VDS.ButtonGroup() - + private var heightConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -34,6 +34,7 @@ import VDS buttonGroup.alignment = .center buttonGroup.rowQuantityPhone = 2 buttonGroup.rowQuantityTablet = 2 + heightConstraint = height(constant: VDS.Button.Size.large.height, priority: .defaultHigh) } //-------------------------------------------------- @@ -70,6 +71,8 @@ import VDS if buttons.count != buttonGroup.buttons.count { buttonGroup.buttons = buttons } + + heightConstraint?.constant = primaryButton.size == .small || secondaryButton.size == .small ? VDS.Button.Size.small.height : VDS.Button.Size.large.height } //-------------------------------------------------- From 5ba126038367d836c9f875c42c54d1064d3967ef Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 16:44:53 -0500 Subject: [PATCH 10/12] updated to required Signed-off-by: Matt Bruce --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 34e0bd11..536bc16b 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -34,7 +34,7 @@ import VDS buttonGroup.alignment = .center buttonGroup.rowQuantityPhone = 2 buttonGroup.rowQuantityTablet = 2 - heightConstraint = height(constant: VDS.Button.Size.large.height, priority: .defaultHigh) + heightConstraint = height(constant: VDS.Button.Size.large.height, priority: .required) } //-------------------------------------------------- From 8d57b0ae0e50bfb965ca026e1f18d68aa20d262f Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Mon, 11 Mar 2024 17:46:13 -0400 Subject: [PATCH 11/12] Remove 2-way binding on Tabs selected index to avoid applying 0 on view reset. --- .../Molecules/HorizontalCombinationViews/Tabs.swift | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 2d176986..654e48ac 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -41,16 +41,6 @@ import VDS } } } - - //-------------------------------------------------- - // MARK: - Public Properties Overrides - //-------------------------------------------------- - open override var selectedIndex: Int { - didSet { - guard let viewModel else { return } - viewModel.selectedIndex = selectedIndex - } - } //------------------------------------------------- // MARK: - Layout Views From 582cd33a1cc13ea27816c9111fd7722249310fb1 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Mon, 11 Mar 2024 19:35:45 -0400 Subject: [PATCH 12/12] footerlessSpacerHeight + footerlessSpacerColor to adjust footerless padding. --- .../Templates/ListPageTemplateModel.swift | 8 +++++++ .../Templates/MoleculeListTemplate.swift | 23 +++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift index e1713b01..daf022a8 100644 --- a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift @@ -18,6 +18,8 @@ public var line: LineModel? public var scrollToRowIndex: Int? public var singleCellSelection: Bool = false + public var footerlessSpacerHeight: CGFloat? + public var footerlessSpacerColor: Color? public override var rootMolecules: [MoleculeModelProtocol] { if let molecules = molecules { @@ -60,6 +62,8 @@ case line case scrollToRowIndex case singleCellSelection + case footerlessSpacerHeight + case footerlessSpacerColor } //-------------------------------------------------- @@ -74,6 +78,8 @@ if let singleCellSelection = try typeContainer.decodeIfPresent(Bool.self, forKey: .singleCellSelection) { self.singleCellSelection = singleCellSelection } + footerlessSpacerColor = try typeContainer.decodeIfPresent(Color.self, forKey: .footerlessSpacerColor) + footerlessSpacerHeight = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .footerlessSpacerHeight) try super.init(from: decoder) try validateModelHasContent() } @@ -85,5 +91,7 @@ try container.encode(line, forKey: .line) try container.encode(singleCellSelection, forKey: .singleCellSelection) try container.encodeIfPresent(scrollToRowIndex, forKey: .scrollToRowIndex) + try container.encodeIfPresent(footerlessSpacerColor, forKey: .footerlessSpacerColor) + try container.encodeIfPresent(footerlessSpacerHeight, forKey: .footerlessSpacerHeight) } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index c00e5181..6f4d945e 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -69,16 +69,21 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol return molecule } - override open func viewForBottom() -> UIView { - guard let footerModel = templateModel?.footer, - let molecule = generateMoleculeView(from: footerModel) - else { - let view = super.viewForBottom() - view.backgroundColor = templateModel?.backgroundColor?.uiColor ?? .clear - return view + open override func viewForBottom() -> UIView { + // If there is a footer molecule return the molecule. + if let footerModel = templateModel?.footer, + let molecule = generateMoleculeView(from: footerModel) { + return molecule } - - return molecule + // Otherwise setup a bottom spacer view. + let view: UIView + if let footerlessSpacerHeight = templateModel?.footerlessSpacerHeight { + view = MVMCoreUICommonViewsUtility.getView(with: footerlessSpacerHeight <= 0.5 ? 0.5 : footerlessSpacerHeight) + } else { + view = super.viewForBottom() + } + view.backgroundColor = templateModel?.footerlessSpacerColor?.uiColor ?? templateModel?.backgroundColor?.uiColor ?? .clear + return view } open override func handleNewData() {