From d7c472b667d9bb0eb3d6f9d193e4c7651e628a6c Mon Sep 17 00:00:00 2001 From: Krishna Kishore Bandaru Date: Fri, 15 Sep 2023 01:07:20 +0530 Subject: [PATCH 01/77] added accessibilitytraits, value, label dynamically from modelJSON --- .../Device/ListDeviceComplexButtonMedium.swift | 1 + .../Device/ListDeviceComplexButtonSmall.swift | 1 + .../ListLeftVariableIconAllTextLinks.swift | 2 +- .../ListLeftVariableIconWithRightCaret.swift | 2 +- ...ariableIconWithRightCaretAllTextLinks.swift | 2 +- ...eftVariableIconWithRightCaretBodyText.swift | 2 +- ...ftVariableNumberedListAllTextAndLinks.swift | 2 +- .../ListLeftVariableNumberedListBodyText.swift | 2 +- .../List/ListProgressBarThin.swift | 2 +- .../List/Miscellaneous/ListStoreLocator.swift | 2 +- ...OneColumnFullWidthTextAllTextAndLinks.swift | 2 +- .../ListOneColumnFullWidthTextBodyText.swift | 2 +- .../List/RightVariable/ListRVWheel.swift | 2 +- ...istRightVariableButtonAllTextAndLinks.swift | 2 +- .../ListRightVariablePayments.swift | 2 +- ...ghtVariablePriceChangeAllTextAndLinks.swift | 2 +- .../ListRightVariablePriceChangeBodyText.swift | 2 +- ...ightVariableRightCaretAlltextAndLinks.swift | 4 ++-- ...tRightVariableTextLinkAllTextAndLinks.swift | 2 +- .../ListRightVariableTotalData.swift | 2 +- .../Atomic/Molecules/Items/ListItemModel.swift | 14 +++++++++++++- .../AccessibilityModelProtocol.swift | 18 ++++++++++++++++++ .../ModelProtocols/ListItemModelProtocol.swift | 2 +- MVMCoreUI/BaseClasses/TableViewCell.swift | 9 +++++++++ 24 files changed, 62 insertions(+), 21 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift index 7a9e8b7e..3dae857d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift @@ -75,6 +75,7 @@ import Foundation delegateObject, additionalData) rightImageView.set(with: model.image, delegateObject, additionalData) updateAccessibilityLabel() + accessibilityTraits.update(with: model.accessibilityTraits ?? button.accessibilityTraits) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift index 7f47929f..b2981158 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift @@ -73,6 +73,7 @@ delegateObject, additionalData) rightImageView.set(with: model.image, delegateObject, additionalData) updateAccessibilityLabel() + accessibilityTraits.update(with: model.accessibilityTraits ?? button.accessibilityTraits) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift index 728d8464..ac3d2681 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift @@ -77,7 +77,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none + accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 8ffbf06c..2edda50e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -91,6 +91,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift index 0c09e9e3..e062fa53 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift @@ -99,7 +99,7 @@ func updateAccessibilityLabel() { let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none + accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift index 6174fc4b..d050574c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift @@ -109,6 +109,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift index 75096854..d133b035 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift @@ -87,7 +87,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none + accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift index 1fff77d1..1cad67b4 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift @@ -89,7 +89,7 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift index 9b85dc4f..d612ef48 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -131,6 +131,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift index 1e271e87..47f37250 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift @@ -147,7 +147,7 @@ override public var accessibilityTraits: UIAccessibilityTraits { get { if (accessoryView != nil) { - return .button + return listItemModel?.accessibilityTraits ?? .button } else if (!(horizontalStack.stackModel?.molecules[1].gone ?? true)) { return heart.accessibilityTraits } else { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 6e5a7245..bc715483 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -95,7 +95,7 @@ import Foundation // Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return (accessoryView != nil) ? .button : .none + return (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } set {} } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift index 7a17dd1b..764a60f2 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift @@ -46,7 +46,7 @@ import Foundation /// Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return (accessoryView != nil) ? .button : .none + return (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } set {} } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index 46c11747..0c08b71b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -91,6 +91,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinks.swift index bca4696a..999f2e40 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinks.swift @@ -47,7 +47,7 @@ stack.restack() accessibilityValue = button.accessibilityValue accessibilityHint = button.accessibilityHint - accessibilityTraits = .button + accessibilityTraits = (listItemModel?.accessibilityTraits ?? .button) } //----------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index ae482d8d..565b5c4d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -83,6 +83,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index d0b2ff70..e5de7b41 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -100,7 +100,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none + accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index a03b676d..d7f90345 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -98,6 +98,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift index 12f11b9e..51fd0378 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift @@ -97,8 +97,8 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none - + accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + if !linkShowing { // Make whole cell focusable if no link. accessibilityLabel = getAccessibilityMessage() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTextLinkAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTextLinkAllTextAndLinks.swift index e47cae46..d7851519 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTextLinkAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTextLinkAllTextAndLinks.swift @@ -89,7 +89,7 @@ func updateAccessibilityLabel() { let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 - accessibilityTraits = .button + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button if !linkShowing && accessoryView == nil { // Make whole cell focusable if one action diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift index a749041a..407eeacf 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift @@ -95,6 +95,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? .button : .none + accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift index a5320ad2..177550d2 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift @@ -18,7 +18,10 @@ public var hideArrow: Bool? public var line: LineModel? public var style: ListItemStyle? - + public var accessibilityTraits: UIAccessibilityTraits? + public var accessibilityText: String? + public var accessibilityValue: String? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -29,6 +32,9 @@ case hideArrow case line case style + case accessibilityTraits + case accessibilityText + case accessibilityValue } //-------------------------------------------------- @@ -102,6 +108,9 @@ hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) style = try typeContainer.decodeIfPresent(ListItemStyle.self, forKey: .style) + accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) + accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) + accessibilityValue = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityValue) try super.init(from: decoder) } @@ -113,5 +122,8 @@ try container.encodeIfPresent(hideArrow, forKey: .hideArrow) try container.encodeIfPresent(line, forKey: .line) try container.encodeIfPresent(style, forKey: .style) + try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits) + try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) + try container.encodeIfPresent(accessibilityValue, forKey: .accessibilityValue) } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift index a7508e39..809334d8 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift @@ -12,6 +12,9 @@ import Foundation public protocol AccessibilityModelProtocol { var accessibilityIdentifier: String? { get set } + var accessibilityTraits: UIAccessibilityTraits? { get set } + var accessibilityText: String? { get set } + var accessibilityValue: String? { get set } } public extension AccessibilityModelProtocol { @@ -20,4 +23,19 @@ public extension AccessibilityModelProtocol { get { nil } set { } } + + var accessibilityTraits: UIAccessibilityTraits? { + get { nil } + set { } + } + + var accessibilityText: String? { + get { nil } + set { } + } + + var accessibilityValue: String? { + get { nil } + set { } + } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ListItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ListItemModelProtocol.swift index 3c64fdb4..b3b7be7e 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ListItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ListItemModelProtocol.swift @@ -15,7 +15,7 @@ public enum ListItemStyle: String, Codable { case none } -public protocol ListItemModelProtocol: ContainerModelProtocol { +public protocol ListItemModelProtocol: ContainerModelProtocol, AccessibilityModelProtocol { var line: LineModel? { get set } var action: ActionModelProtocol? { get set } var hideArrow: Bool? { get set } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index c21e2c49..f5bb8bf1 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -163,6 +163,15 @@ import UIKit // align if needed. containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol) + + if let traits = model.accessibilityTraits { + accessibilityTraits.update(with: traits) + } + if let accessibilityText = model.accessibilityText { + accessibilityLabel = accessibilityText + isAccessibilityElement = true + } + accessibilityValue = model.accessibilityValue } open func reset() { From eb9ec0086618709faf73c85268ace4eeb092ca8a Mon Sep 17 00:00:00 2001 From: Krishna Kishore Bandaru Date: Fri, 15 Sep 2023 01:17:53 +0530 Subject: [PATCH 02/77] updated button traits dynamically --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift | 4 ++++ MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift | 4 +++- MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift | 6 ++++-- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index 08afefde..ce5a846e 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -73,6 +73,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat _backgroundColor = newValue } } + public var accessibilityTraits: UIAccessibilityTraits? //-------------------------------------------------- // MARK: - Methods @@ -195,6 +196,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat case disabledTextColor case disabledBorderColor case width + case accessibilityTraits } //-------------------------------------------------- @@ -263,6 +265,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width) + accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) } open func encode(to encoder: Encoder) throws { @@ -286,5 +289,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat try container.encodeIfPresent(size, forKey: .size) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(width, forKey: .width) + try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits) } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift index 323236a7..394f7d86 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift @@ -33,7 +33,9 @@ import Foundation super.set(with: model, delegateObject, additionalData) FormValidator.setupValidation(for: castModel, delegate: delegateObject?.formHolderDelegate) - + if let traits = model.accessibilityTraits { + accessibilityTraits = traits + } } public func setState() { diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift index a61ec150..75b6c923 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift @@ -24,7 +24,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro public var enabled: Bool = true public var enabledTintColor: Color? public var disabledTintColor: Color? - + public var accessibilityTraits: UIAccessibilityTraits? public var groupName: String = "" public var updateUI: ActionBlock? @@ -45,6 +45,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro case groupName case enabledTintColor case disabledTintColor + case accessibilityTraits } //-------------------------------------------------- @@ -59,7 +60,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) action = try typeContainer.decodeModel(codingKey: .action) - + accessibilityTraits = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityTraits) if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } @@ -90,5 +91,6 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(enabledTintColor, forKey: .enabledTintColor) try container.encodeIfPresent(disabledTintColor, forKey: .disabledTintColor) + try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits) } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index e578fa51..71d5c332 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -173,6 +173,9 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { } FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) + if let traits = model.accessibilityTraits { + accessibilityTraits = traits + } } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { From 14ac43d0eaedcf3f478e7936fe33dc7664f7e089 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Fri, 15 Sep 2023 16:34:28 +0530 Subject: [PATCH 03/77] Update ImageButtonModel.swift --- MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift index 75b6c923..74325d85 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift @@ -60,7 +60,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) action = try typeContainer.decodeModel(codingKey: .action) - accessibilityTraits = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityTraits) + accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } From 170da5f47725374946271718b85369a9a5522eee Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 15 Sep 2023 09:10:39 -0500 Subject: [PATCH 04/77] refactored to use buttongroup Signed-off-by: Matt Bruce --- .../TwoButtonView.swift | 149 +++++------------- 1 file changed, 41 insertions(+), 108 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 9a70c12e..debd2c8d 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -9,144 +9,70 @@ import UIKit import VDS -@objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol { +@objcMembers open class TwoButtonView: VDS.View, VDSMoleculeViewProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - open var primaryButton: PillButton = PillButton() - open var secondaryButton: PillButton = PillButton() - private var stack = UIStackView() - - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - private var equalWidthConstraint: NSLayoutConstraint? - + 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() + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- - public func setDefaultAppearance() { - primaryButton.use = .primary - secondaryButton.use = .secondary - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - - primaryButton.updateView(size) - secondaryButton.updateView(size) - } - - open override func setupView() { - super.setupView() - - stack.translatesAutoresizingMaskIntoConstraints = false + open override func setup() { + super.setup() isAccessibilityElement = false - addSubview(stack) - stack.addArrangedSubview(secondaryButton) - stack.addArrangedSubview(primaryButton) - NSLayoutConstraint.constraintPinSubview(toSuperview: stack) - stack.axis = .horizontal - stack.spacing = Padding.Component.gutterForApplicationWidth - equalWidthConstraint = secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1) - equalWidthConstraint?.isActive = true + addSubview(buttonGroup) + buttonGroup.pinToSuperView() + buttonGroup.alignment = .center + buttonGroup.rowQuantityPhone = 2 + buttonGroup.rowQuantityTablet = 2 + buttonGroup.childWidth = .percentage(50) } - - //-------------------------------------------------- - // MARK: - Stack Manipulation - //-------------------------------------------------- - - public func showPrimaryButton() { - if !stack.arrangedSubviews.contains(primaryButton) { - stack.addArrangedSubview(primaryButton) - primaryButton.isHidden = false - } - - if secondaryButton.superview != nil { - equalWidthConstraint?.isActive = true - } - - primaryButton.isAccessibilityElement = true - } - - public func showSecondaryButton() { - - if !stack.arrangedSubviews.contains(secondaryButton) { - stack.insertArrangedSubview(secondaryButton, at: 0) - secondaryButton.isHidden = false - } - - if primaryButton.superview != nil { - equalWidthConstraint?.isActive = true - } - - secondaryButton.isAccessibilityElement = true - } - - public func hidePrimaryButton() { - - if primaryButton.superview != nil { - stack.removeArrangedSubview(primaryButton) - primaryButton.isHidden = true - } - - primaryButton.isAccessibilityElement = false - equalWidthConstraint?.isActive = false - } - - public func hideSecondaryButton() { - - if secondaryButton.superview != nil { - stack.removeArrangedSubview(secondaryButton) - secondaryButton.isHidden = true - } - - secondaryButton.isAccessibilityElement = false - equalWidthConstraint?.isActive = false - } - //-------------------------------------------------- // MARK: - MoleculeViewProtocol //-------------------------------------------------- open override func reset() { super.reset() - - setDefaultAppearance() + primaryButton.reset() + secondaryButton.reset() + primaryButton.use = .primary + secondaryButton.use = .secondary + buttonGroup.reset() } - public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { guard let model = model as? TwoButtonViewModel, let buttonModel = model.primaryButton ?? model.secondaryButton else { return 0 } return PillButton.estimatedHeight(with: buttonModel, delegateObject) } - - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - - guard let model = model as? TwoButtonViewModel else { return } - - if let secondaryModel = model.secondaryButton { - showSecondaryButton() + + public func viewModelDidUpdate() { + var buttons = [PillButton]() + if let secondaryModel = viewModel.secondaryButton { secondaryButton.set(with: secondaryModel, delegateObject, additionalData) - } else { - hideSecondaryButton() + buttons.append(secondaryButton) } - if let primaryModel = model.primaryButton { - showPrimaryButton() + if let primaryModel = viewModel.primaryButton { primaryButton.set(with: primaryModel, delegateObject, additionalData) - } else { - hidePrimaryButton() + buttons.append(primaryButton) } + + buttonGroup.buttons = buttons } + //-------------------------------------------------- // MARK: - MVMCoreUIViewConstrainingProtocol //-------------------------------------------------- @@ -154,4 +80,11 @@ import VDS open func horizontalAlignment() -> UIStackView.Alignment { return .center } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + public func updateView(_ size: CGFloat) { + setNeedsUpdate() + } } From c972597a117a01bc333b138f3e7f4df2041e3d5a Mon Sep 17 00:00:00 2001 From: Keerthy Date: Fri, 13 Oct 2023 23:31:18 +0530 Subject: [PATCH 05/77] Addressed review comments --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift | 8 ++++++++ MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 8 ++++---- .../LeftVariable/ListLeftVariableIconWithRightCaret.swift | 2 +- .../ListLeftVariableIconWithRightCaretAllTextLinks.swift | 2 +- .../ListLeftVariableIconWithRightCaretBodyText.swift | 2 +- .../ListLeftVariableNumberedListAllTextAndLinks.swift | 2 +- .../ListLeftVariableNumberedListBodyText.swift | 2 +- .../DesignedComponents/List/ListProgressBarThin.swift | 2 +- .../ListOneColumnFullWidthTextAllTextAndLinks.swift | 2 +- .../OneColumn/ListOneColumnFullWidthTextBodyText.swift | 2 +- .../List/RightVariable/ListRVWheel.swift | 2 +- .../List/RightVariable/ListRightVariablePayments.swift | 2 +- .../ListRightVariablePriceChangeAllTextAndLinks.swift | 2 +- .../ListRightVariablePriceChangeBodyText.swift | 2 +- .../ListRightVariableRightCaretAlltextAndLinks.swift | 2 +- .../List/RightVariable/ListRightVariableTotalData.swift | 2 +- 17 files changed, 27 insertions(+), 19 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index ce5a846e..e455589b 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -74,6 +74,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat } } public var accessibilityTraits: UIAccessibilityTraits? + public var disabledAccessibilityTraits: UIAccessibilityTraits? + public var isAccessibilityElement: Bool? //-------------------------------------------------- // MARK: - Methods @@ -197,6 +199,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat case disabledBorderColor case width case accessibilityTraits + case disabledAccessibilityTraits + case isAccessibilityElement } //-------------------------------------------------- @@ -266,6 +270,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width) accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) + disabledAccessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .disabledAccessibilityTraits) + isAccessibilityElement = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAccessibilityElement) } open func encode(to encoder: Encoder) throws { @@ -290,5 +296,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(width, forKey: .width) try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits) + try container.encodeIfPresent(disabledAccessibilityTraits, forKey: .disabledAccessibilityTraits) + try container.encodeIfPresent(isAccessibilityElement, forKey: .isAccessibilityElement) } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift index 74325d85..8f4bb522 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift @@ -60,7 +60,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) action = try typeContainer.decodeModel(codingKey: .action) - accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) + accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) ?? .button if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 71d5c332..f4b3e257 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -101,7 +101,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { #if DEBUG // Useful to detect with isHittable when performing UI testing. - isAccessibilityElement = isEnabled + isAccessibilityElement = model?.isAccessibilityElement ?? isEnabled #endif if isEnabled { @@ -134,6 +134,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { case .standard: verticalPadding = Padding.Three horizontalPadding = Padding.Five + break case .small: verticalPadding = Padding.Two @@ -173,9 +174,8 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { } FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - if let traits = model.accessibilityTraits { - accessibilityTraits = traits - } + accessibilityTraits = isEnabled ? (model.accessibilityTraits ?? .button) : (model.disabledAccessibilityTraits ?? .none) + } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 2edda50e..2a2adb27 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -91,6 +91,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift index e062fa53..d65e35e5 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift @@ -99,7 +99,7 @@ func updateAccessibilityLabel() { let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift index d050574c..70c8ea60 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift @@ -109,6 +109,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift index d133b035..cf119b33 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift @@ -87,7 +87,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift index 1cad67b4..4a6667df 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift @@ -89,7 +89,7 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift index d612ef48..ab8eee78 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -131,6 +131,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index bc715483..0fece30a 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -95,7 +95,7 @@ import Foundation // Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + return listItemModel?.accessibilityTraits ?? .button } set {} } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift index da77d173..e62ce891 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift @@ -46,7 +46,7 @@ import Foundation /// Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + return listItemModel?.accessibilityTraits ?? .button } set {} } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index 0c08b71b..cbd9741d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -91,6 +91,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 565b5c4d..eeb09ee5 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -83,6 +83,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index e5de7b41..6ed847a9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -100,7 +100,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index d7f90345..7fafd3f0 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -98,6 +98,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift index 51fd0378..6b059dbc 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift @@ -97,7 +97,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift index 407eeacf..cd7a6db9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift @@ -95,6 +95,6 @@ } accessibilityLabel = message - accessibilityTraits = (accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = listItemModel?.accessibilityTraits ?? .button } } From fb760bf91e84f4519923995ba18895f7f60999da Mon Sep 17 00:00:00 2001 From: Keerthy Date: Fri, 20 Oct 2023 00:18:29 +0530 Subject: [PATCH 06/77] Added dynamic trait for ListStoreLocator --- .../List/Miscellaneous/ListStoreLocator.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift index 47f37250..3c69d6a4 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift @@ -146,13 +146,7 @@ // Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - if (accessoryView != nil) { - return listItemModel?.accessibilityTraits ?? .button - } else if (!(horizontalStack.stackModel?.molecules[1].gone ?? true)) { - return heart.accessibilityTraits - } else { - return .none - } + return listItemModel?.accessibilityTraits ?? .button } set { } } From 43f1c64151005291522509a570ad5489739a48bd Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 26 Oct 2023 18:44:51 +0530 Subject: [PATCH 07/77] updated logic --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift | 4 ---- MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift | 6 +++--- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 4 ++-- .../LeftVariable/ListLeftVariableIconAllTextLinks.swift | 2 +- .../LeftVariable/ListLeftVariableIconWithRightCaret.swift | 2 +- .../ListLeftVariableIconWithRightCaretAllTextLinks.swift | 2 +- .../ListLeftVariableIconWithRightCaretBodyText.swift | 2 +- .../ListLeftVariableNumberedListAllTextAndLinks.swift | 2 +- .../LeftVariable/ListLeftVariableNumberedListBodyText.swift | 2 +- .../DesignedComponents/List/ListProgressBarThin.swift | 2 +- .../List/Miscellaneous/ListStoreLocator.swift | 2 +- .../ListOneColumnFullWidthTextAllTextAndLinks.swift | 3 ++- .../List/OneColumn/ListOneColumnFullWidthTextBodyText.swift | 2 +- .../DesignedComponents/List/RightVariable/ListRVWheel.swift | 2 +- .../List/RightVariable/ListRightVariablePayments.swift | 2 +- .../ListRightVariablePriceChangeAllTextAndLinks.swift | 2 +- .../ListRightVariablePriceChangeBodyText.swift | 2 +- .../ListRightVariableRightCaretAlltextAndLinks.swift | 2 +- .../List/RightVariable/ListRightVariableTotalData.swift | 2 +- .../NavigationController/NavigationController.swift | 4 ++++ .../MVMCoreUISplitViewController+Extension.swift | 4 ++++ MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 4 ++++ 22 files changed, 34 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index e455589b..c06d31fc 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -75,7 +75,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat } public var accessibilityTraits: UIAccessibilityTraits? public var disabledAccessibilityTraits: UIAccessibilityTraits? - public var isAccessibilityElement: Bool? //-------------------------------------------------- // MARK: - Methods @@ -200,7 +199,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat case width case accessibilityTraits case disabledAccessibilityTraits - case isAccessibilityElement } //-------------------------------------------------- @@ -271,7 +269,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width) accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits) disabledAccessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .disabledAccessibilityTraits) - isAccessibilityElement = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAccessibilityElement) } open func encode(to encoder: Encoder) throws { @@ -297,6 +294,5 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat try container.encodeIfPresent(width, forKey: .width) try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits) try container.encodeIfPresent(disabledAccessibilityTraits, forKey: .disabledAccessibilityTraits) - try container.encodeIfPresent(isAccessibilityElement, forKey: .isAccessibilityElement) } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift index 394f7d86..f3dc2798 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift @@ -33,9 +33,6 @@ import Foundation super.set(with: model, delegateObject, additionalData) FormValidator.setupValidation(for: castModel, delegate: delegateObject?.formHolderDelegate) - if let traits = model.accessibilityTraits { - accessibilityTraits = traits - } } public func setState() { @@ -49,6 +46,9 @@ import Foundation } else if let disabledTintColor = castModel.disabledTintColor { image.imageView.tintColor = disabledTintColor.uiColor } + if let traits = model?.accessibilityTraits { + accessibilityTraits = traits + } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index f4b3e257..579236e9 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -101,7 +101,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { #if DEBUG // Useful to detect with isHittable when performing UI testing. - isAccessibilityElement = model?.isAccessibilityElement ?? isEnabled + isAccessibilityElement = isEnabled #endif if isEnabled { @@ -121,6 +121,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { self.borderColor = borderColor } } + accessibilityTraits = isEnabled ? (model?.accessibilityTraits ?? .button) : (model?.disabledAccessibilityTraits ?? .none) } private func getInnerPadding() -> CGFloat { @@ -174,7 +175,6 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { } FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - accessibilityTraits = isEnabled ? (model.accessibilityTraits ?? .button) : (model.disabledAccessibilityTraits ?? .none) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift index ac3d2681..b9d234bb 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinks.swift @@ -77,7 +77,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? (listItemModel?.accessibilityTraits ?? .button) : .none + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((isAccessibilityElement && accessoryView != nil) ? .button : .none) if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 2a2adb27..cd1b20d9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -91,6 +91,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift index d65e35e5..48d4affe 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinks.swift @@ -99,7 +99,7 @@ func updateAccessibilityLabel() { let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((isAccessibilityElement && accessoryView != nil) ? .button : .none) if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift index 70c8ea60..cf83dcd9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretBodyText.swift @@ -109,6 +109,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift index cf119b33..d4e9b6ce 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListAllTextAndLinks.swift @@ -87,7 +87,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((isAccessibilityElement && accessoryView != nil) ? .button : .none) if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift index 4a6667df..ea81bc55 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableNumberedListBodyText.swift @@ -89,7 +89,7 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift index ab8eee78..b3861703 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -131,6 +131,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift index 3c69d6a4..d1ccd921 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Miscellaneous/ListStoreLocator.swift @@ -146,7 +146,7 @@ // Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return listItemModel?.accessibilityTraits ?? .button + return (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } set { } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 0fece30a..d2177ede 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -95,7 +95,8 @@ import Foundation // Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return listItemModel?.accessibilityTraits ?? .button + return (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) + } set {} } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift index e62ce891..ff14df7f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextBodyText.swift @@ -46,7 +46,7 @@ import Foundation /// Ensures voice over does not read "selected" after user triggers action on cell. override public var accessibilityTraits: UIAccessibilityTraits { get { - return listItemModel?.accessibilityTraits ?? .button + return (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } set {} } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index cbd9741d..be3f7370 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -91,6 +91,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index eeb09ee5..a662a587 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -83,6 +83,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index 6ed847a9..f11c7278 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -100,7 +100,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((isAccessibilityElement && accessoryView != nil) ? .button : .none) if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index 7fafd3f0..b13a389e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -98,6 +98,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift index 6b059dbc..37af1350 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableRightCaretAlltextAndLinks.swift @@ -97,7 +97,7 @@ let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 isAccessibilityElement = !linkShowing - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((isAccessibilityElement && accessoryView != nil) ? .button : .none) if !linkShowing { // Make whole cell focusable if no link. diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift index cd7a6db9..345feca1 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift @@ -95,6 +95,6 @@ } accessibilityLabel = message - accessibilityTraits = listItemModel?.accessibilityTraits ?? .button + accessibilityTraits = (listItemModel?.accessibilityTraits) ?? ((accessoryView != nil) ? .button : .none) } } diff --git a/MVMCoreUI/Containers/NavigationController/NavigationController.swift b/MVMCoreUI/Containers/NavigationController/NavigationController.swift index 8f72a792..5226ee87 100644 --- a/MVMCoreUI/Containers/NavigationController/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController/NavigationController.swift @@ -83,6 +83,10 @@ import Combine } extension NavigationController: MVMCoreViewManagerProtocol { + public func getAccessibilityElements() -> [Any]? { + return [] + } + public func getCurrentViewController() -> UIViewController? { guard let topViewController = topViewController else { return nil } return MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index 20f4449c..b15a90aa 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -249,6 +249,10 @@ public extension MVMCoreUISplitViewController { } extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol { + public func getAccessibilityElements() -> [Any]? { + return [] + } + public func getCurrentViewController() -> UIViewController? { navigationController?.getCurrentViewController() } diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 458c0169..32ded335 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -10,6 +10,10 @@ import Foundation import MVMCore open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, TabsDelegate, MVMCorePresentationDelegateProtocol, SubNavSwipeNavigationProtocol { + public func getAccessibilityElements() -> [Any]? { + return [] + } + /// The current managed view controller private var viewController: UIViewController From 1e5578a66cfc7934066f0a3482977287146a9372 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 26 Oct 2023 22:06:55 +0530 Subject: [PATCH 08/77] discarded unwanted changes --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 32ded335..458c0169 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -10,10 +10,6 @@ import Foundation import MVMCore open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, TabsDelegate, MVMCorePresentationDelegateProtocol, SubNavSwipeNavigationProtocol { - public func getAccessibilityElements() -> [Any]? { - return [] - } - /// The current managed view controller private var viewController: UIViewController From d65df06934ac1726ae6bba899af3f34859b52f60 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Wed, 22 Nov 2023 18:07:13 +0530 Subject: [PATCH 09/77] Updated textView to have label text for accessibility behavior --- .../Atoms/FormFields/TextFields/TextViewEntryField.swift | 7 ++++++- MVMCoreUI/BaseClasses/TextView.swift | 1 - .../SupportingFiles/Strings/en.lproj/Localizable.strings | 1 + .../Strings/es-MX.lproj/Localizable.strings | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift index 3221f043..e92e7127 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift @@ -281,6 +281,11 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele if model.hideBorders { adjustMarginConstraints(constant: 0) } - + setAccessibilityString(model.title) + } + + override func setAccessibilityString(_ accessibilityString: String?) { + let accessibilityString = accessibilityString ?? "" + textView.accessibilityLabel = "\(String(describing: accessibilityString)) \(self.textView.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")" } } diff --git a/MVMCoreUI/BaseClasses/TextView.swift b/MVMCoreUI/BaseClasses/TextView.swift index 8d09ca35..5e4f1c07 100644 --- a/MVMCoreUI/BaseClasses/TextView.swift +++ b/MVMCoreUI/BaseClasses/TextView.swift @@ -98,7 +98,6 @@ import UIKit smartInsertDeleteType = .no inputAccessoryView = nil isAccessibilityElement = true - accessibilityTraits = .staticText font = fontStyle.getFont() keyboardType = .default isEditable = true diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index 0b736bf9..05cadbf5 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -27,6 +27,7 @@ // MARK: Textfield "textfield_today_string" = "Today"; "textfield_error_message" = "%@.\n The error message.\n %@"; +"textView_error_message" = "%@.\n The error message.\n %@"; "textfield_picker_item" = " picker item"; "textfield_regular" = " regular"; "textfield_disabled_state" = "disabled"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings index b279ccdb..60cc1677 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings @@ -23,6 +23,7 @@ // Textfield "textfield_today_string" = "Hoy"; "textfield_error_message" = "%@.\n El mensaje de error.\n %@"; +"textView_error_message" = "%@.\n El mensaje de error.\n %@"; "textfield_picker_item" = " artículo de selector"; "textfield_regular" = " regular"; "textfield_disabled_state" = "inactivo"; From 8de78987f88a851cea33a75500841496e0d9df3a Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Fri, 1 Dec 2023 14:32:44 +0530 Subject: [PATCH 10/77] Setting accessibility label if available before text for eyebrow, headline, body labels in EyebrowHeadlineBodyLink molecule's accessibility label --- .../VerticalCombinationViews/EyebrowHeadlineBodyLink.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index a25426d7..da5e959e 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -88,15 +88,15 @@ var message = "" - if let eyebrowLabel = eyebrow.text { + if let eyebrowLabel = eyebrow.accessibilityLabel ?? eyebrow.text { message += eyebrowLabel + ", " } - if let headlineLabel = headline.text { + if let headlineLabel = headline.accessibilityLabel ?? headline.text { message += headlineLabel + ", " } - if let bodyLabel = body.text { + if let bodyLabel = body.accessibilityLabel ?? body.text { message += bodyLabel } From 6e5980af64c51c1e0998b06d5d8e1b2b56c1b9c9 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Fri, 1 Dec 2023 14:12:04 -0500 Subject: [PATCH 11/77] Index check before switching tabs. --- .../HorizontalCombinationViews/TabBar.swift | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift index 605acc3d..01e71db8 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift @@ -84,16 +84,22 @@ import VDSColorTokens // MARK: - TabBarProtocol @MainActor public func highlightTab(at index: Int) { - guard let newSelectedItem = items?[index] else { return } + guard let items = items, index < items.count else { + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available (\(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) + return + } tabModel.selectedTab = index - selectedItem = newSelectedItem + selectedItem = items[index] } @MainActor public func selectTab(at index: Int) { - guard let newSelectedItem = items?[index] else { return } - selectedItem = newSelectedItem - tabBar(self, didSelect: newSelectedItem) + guard let items = items, index < items.count else { + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available (\(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) + return + } + selectedItem = items[index] + tabBar(self, didSelect: items[index]) } public func currentTabIndex() -> Int { tabModel.selectedTab } From 21f24b2c9b339e8d5232383caedbd0ffc67694b9 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Fri, 1 Dec 2023 14:16:00 -0500 Subject: [PATCH 12/77] remove extra paranthesis --- .../Atomic/Molecules/HorizontalCombinationViews/TabBar.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift index 01e71db8..d0252419 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift @@ -85,7 +85,7 @@ import VDSColorTokens @MainActor public func highlightTab(at index: Int) { guard let items = items, index < items.count else { - MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available (\(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available \(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) return } tabModel.selectedTab = index @@ -95,7 +95,7 @@ import VDSColorTokens @MainActor public func selectTab(at index: Int) { guard let items = items, index < items.count else { - MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available (\(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available \(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) return } selectedItem = items[index] From 8b64b2b52a458fb7ed7d23bb0de24e353dbb85a9 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Fri, 1 Dec 2023 14:32:33 -0500 Subject: [PATCH 13/77] Ensure index > 0 for those tricky ones. --- .../Molecules/HorizontalCombinationViews/TabBar.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift index d0252419..65b116f5 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift @@ -84,8 +84,8 @@ import VDSColorTokens // MARK: - TabBarProtocol @MainActor public func highlightTab(at index: Int) { - guard let items = items, index < items.count else { - MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available \(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) + guard let items = items, index >= 0, index < items.count else { + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Invalid tab index \(index). \(items?.count ?? 0) tabs available .", code: 0, domain: ErrorDomainSystem, location: #function)!) return } tabModel.selectedTab = index @@ -94,8 +94,8 @@ import VDSColorTokens @MainActor public func selectTab(at index: Int) { - guard let items = items, index < items.count else { - MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Tab index \(index) is greater than the number of tabs available \(items?.count ?? 0).", code: 0, domain: ErrorDomainSystem, location: #function)!) + guard let items = items, index >= 0, index < items.count else { + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Invalid tab index \(index). \(items?.count ?? 0) tabs available.", code: 0, domain: ErrorDomainSystem, location: #function)!) return } selectedItem = items[index] From 938a5d119249a0c8abd809f6fcd3f55d3968c696 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 5 Dec 2023 15:46:22 -0600 Subject: [PATCH 14/77] first cut for the conversion Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Buttons/CaretLink.swift | 179 +++++------------- .../Atomic/Atoms/Buttons/CaretLinkModel.swift | 43 ++--- .../Atomic/Extensions/VDS-Enums+Codable.swift | 4 +- 3 files changed, 62 insertions(+), 164 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index 702c3238..e4d74c93 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -6,152 +6,61 @@ // Created by Christiano, Kevin on 3/18/19. // Copyright © 2019 Verizon Wireless. All rights reserved. // +import VDS +open class CaretLink: VDS.TextLinkCaret, VDSMoleculeViewProtocol { -open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { - //------------------------------------------------------ - // MARK: - Constants - //------------------------------------------------------ + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + open var viewModel: CaretLinkModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? - private let CARET_VIEW_HEIGHT: Float = 10.5 - private let CARET_VIEW_WIDTH: Float = 6.5 - - //------------------------------------------------------ - // MARK: - Properties - //------------------------------------------------------ - - @objc public var rightView: UIView? - @objc public var rightViewHeight: NSNumber? - @objc public var rightViewWidth: NSNumber? - - @objc public var enabledColor: UIColor = .mvmBlack { - didSet { changeCaretColor() } - } - - @objc public var disabledColor: UIColor = .mvmCoolGray3 { - didSet { changeCaretColor() } - } - - private var caretSpacingConstraint: NSLayoutConstraint? - - //------------------------------------------------------ - // MARK: - Inits - //------------------------------------------------------ - - // Default values for view. - public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.init(frame: .zero) - backgroundColor = .clear - translatesAutoresizingMaskIntoConstraints = false - setTitleColor(enabledColor, for: .normal) - setTitleColor(disabledColor, for: .disabled) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - super.init(coder: coder) - } - - //------------------------------------------------------ - // MARK: - Lifecycle - //------------------------------------------------------ - - override public var isEnabled: Bool { - didSet { changeCaretColor() } - } - - public override func updateView(_ size: CGFloat) { - titleLabel?.font = MFStyler.fontBoldBodySmall() - } - - //------------------------------------------------------ - // MARK: - Methods - //------------------------------------------------------ - - private func changeCaretColor() { - - setTitleColor(enabledColor, for: .normal) - setTitleColor(disabledColor, for: .disabled) - - if let rightCaretView = rightView as? CaretView { - rightCaretView.enabledColor = enabledColor - rightCaretView.disabledColor = disabledColor - rightCaretView.isEnabled = isEnabled + //-------------------------------------------------- + // MARK: - Public Functions + //-------------------------------------------------- + open func viewModelDidUpdate() { + isEnabled = viewModel.enabled + iconPosition = viewModel.iconPosition + text = viewModel.title + surface = viewModel.surface + onClick = { [weak self] control in + guard let self else { return } + MVMCoreUIActionHandler.performActionUnstructured(with: self.viewModel.action, + sourceModel: self.viewModel, + additionalData: self.additionalData, + delegateObject: self.delegateObject) } } - - private func createCaretView() -> CaretView { - let caret = CaretView() - caret.lineWidth = 1.5 - return caret - } - - private func addCaretImageView() { + + //-------------------------------------------------- + // MARK: - Overrides + //-------------------------------------------------- + open override func updateAccessibility() { + super.updateAccessibility() - rightView?.removeFromSuperview() - - let width = CGFloat(rightViewWidth?.floatValue ?? CARET_VIEW_WIDTH) - let height = CGFloat(rightViewHeight?.floatValue ?? CARET_VIEW_HEIGHT) - - contentEdgeInsets.right = 4 + width - - let caretView: UIView = rightView ?? createCaretView() - rightView = caretView - rightView?.translatesAutoresizingMaskIntoConstraints = false - addSubview(caretView) - - caretView.widthAnchor.constraint(equalToConstant: width).isActive = true - caretView.heightAnchor.constraint(equalToConstant: height).isActive = true - - let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 7) - caretLabelSpacing.isActive = true - caretSpacingConstraint = caretLabelSpacing - - caretView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true - trailingAnchor.constraint(greaterThanOrEqualTo: caretView.trailingAnchor).isActive = true - caretView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: caretView.bottomAnchor).isActive = true - contentHorizontalAlignment = .left - - // Set correct color after layout - changeCaretColor() - } - - public func updateCaretSpacing(_ spacing: CGFloat) { - caretSpacingConstraint?.constant = spacing - } - - //------------------------------------------------------ - // MARK: - Atomization - //------------------------------------------------------ - - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - addCaretImageView() - guard let model = model as? CaretLinkModel else { return } - - if let color = model.backgroundColor { - backgroundColor = color.uiColor + guard let viewModel = viewModel else { return } + if let accessibilityText = viewModel.accessibilityText { + self.accessibilityLabel = accessibilityText } - enabledColor = (model.inverted ? model.enabledColor_inverted : model.enabledColor).uiColor - disabledColor = (model.inverted ? model.disabledColor_inverted : model.disabledColor).uiColor - - isEnabled = model.enabled - set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) - setTitle(model.title, for: .normal) - } - - open override func reset() { - super.reset() - rightView?.removeFromSuperview() + if let accessibilityIdentifier = viewModel.accessibilityIdentifier { + self.accessibilityIdentifier = accessibilityIdentifier + } } + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + public func updateView(_ size: CGFloat) {} + + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 10.5 } +} + +// MARK: - MVMCoreUIViewConstrainingProtocol +extension CaretLink: MVMCoreUIViewConstrainingProtocol { public func needsToBeConstrained() -> Bool { true } open func horizontalAlignment() -> UIStackView.Alignment { .leading } - - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 10.5 } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift index 3a5429e1..6b184bac 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLinkModel.swift @@ -8,7 +8,7 @@ import Foundation import MVMCore - +import VDS public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- @@ -20,13 +20,11 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea public var backgroundColor: Color? public var accessibilityIdentifier: String? public var title: String + public var accessibilityText: String? public var action: ActionModelProtocol - public var enabledColor: Color = Color(uiColor: .mvmBlack) - public var disabledColor: Color = Color(uiColor: .mvmCoolGray6) - public var enabledColor_inverted: Color = Color(uiColor: .mvmWhite) - public var disabledColor_inverted: Color = Color(uiColor: .mvmCoolGray10) public var enabled = true public var inverted = false + public var iconPosition: TextLinkCaret.IconPosition = .right //-------------------------------------------------- // MARK: - Initializer @@ -45,12 +43,10 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea case id case backgroundColor case accessibilityIdentifier + case accessibilityText + case iconPosition case title case action - case enabledColor_inverted - case disabledColor_inverted - case enabledColor - case disabledColor case enabled case inverted case moleculeName @@ -66,22 +62,11 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) + accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) title = try typeContainer.decode(String.self, forKey: .title) - - if let enabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor_inverted) { - self.enabledColor_inverted = enabledColor_inverted - } - - if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) { - self.disabledColor_inverted = disabledColor_inverted - } - - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) { - enabledColor = color - } - - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) { - disabledColor = color + + if let iconPosition = try typeContainer.decodeIfPresent(TextLinkCaret.IconPosition.self, forKey: .iconPosition) { + self.iconPosition = iconPosition } if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { @@ -99,15 +84,17 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(iconPosition, forKey: .iconPosition) try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) + try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeModel(action, forKey: .action) - try container.encode(enabledColor, forKey: .enabledColor) - try container.encodeIfPresent(disabledColor, forKey: .disabledColor) try container.encode(enabled, forKey: .enabled) - try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted) - try container.encode(disabledColor_inverted, forKey: .disabledColor_inverted) try container.encode(inverted, forKey: .inverted) } } + +extension CaretLinkModel { + public var surface: Surface { inverted ? .dark : .light } +} diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 1d24a0bd..b27124bd 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -13,6 +13,7 @@ extension Surface: Codable {} extension Badge.FillColor: Codable {} extension Icon.Name: Codable {} extension Icon.Size: Codable {} +extension TextLinkCaret.IconPosition: Codable {} extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} @@ -20,7 +21,8 @@ extension TextLink.Size: Codable {} extension VDS.Line.Style: Codable {} extension VDS.Line.Orientation: Codable {} extension Use: Codable {} + extension VDS.Button.Size: RawRepresentableCodable { public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } public static var defaultValue: VDS.Button.Size? { nil } -} \ No newline at end of file +} From cf0e3086cf3e7534fceb8dad27193a8a79e22010 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 5 Dec 2023 15:46:34 -0600 Subject: [PATCH 15/77] added accessibilityText Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift | 7 +++---- MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index 5ca77679..9aea7b17 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -11,7 +11,7 @@ import VDSColorTokens import VDS open class Link: VDS.TextLink, VDSMoleculeViewProtocol { - + //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- @@ -36,7 +36,7 @@ open class Link: VDS.TextLink, VDSMoleculeViewProtocol { delegateObject: self.delegateObject) } } - + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -57,10 +57,9 @@ open class Link: VDS.TextLink, VDSMoleculeViewProtocol { // MARK: - MVMCoreViewProtocol //-------------------------------------------------- open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 } - + open func updateView(_ size: CGFloat) { } - open func setupView() {} } // MARK: - MVMCoreUIViewConstrainingProtocol diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift index 7e9a4640..14e041e5 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/LinkModel.swift @@ -92,6 +92,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) + try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeModel(action, forKey: .action) try container.encode(inverted, forKey: .inverted) try container.encode(enabled, forKey: .enabled) From 6a8e45fc9e2290cabb94643c3b9f895788a61446 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 6 Dec 2023 14:39:46 -0600 Subject: [PATCH 16/77] initial cut for VDS Loader Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/LoadingSpinner.swift | 223 ++---------------- .../Atoms/Views/LoadingSpinnerModel.swift | 24 +- 2 files changed, 35 insertions(+), 212 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift index 2d58c8f4..04128e90 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift @@ -7,207 +7,30 @@ // import UIKit +import VDS +open class LoadingSpinner: VDS.Loader, VDSMoleculeViewProtocol { + + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + open var viewModel: LoadingSpinnerModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + + //-------------------------------------------------- + // MARK: - Public Functions + //-------------------------------------------------- + open func viewModelDidUpdate() { + size = Int(viewModel.diameter) + surface = viewModel.surface + } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 40.0 } -open class LoadingSpinner: View { - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - - public var strokeColor: UIColor = .mvmBlack - - public var lineWidth: CGFloat = 4.0 - - public var speed: Float = 1.5 - - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - public var heightConstraint: NSLayoutConstraint? - public var widthConstraint: NSLayoutConstraint? - - //-------------------------------------------------- - // MARK: - Lifecycle - //-------------------------------------------------- - - override open var layer: CAShapeLayer { - get { return super.layer as! CAShapeLayer } - } - - override open class var layerClass: AnyClass { - return CAShapeLayer.self - } - - open override func setupView() { - super.setupView() - - heightConstraint = heightAnchor.constraint(equalToConstant: 0) - widthConstraint = widthAnchor.constraint(equalToConstant: 0) - } - - override open func layoutSubviews() { - super.layoutSubviews() + open func updateView(_ size: CGFloat) { } - layer.fillColor = nil - layer.strokeColor = strokeColor.cgColor - layer.lineWidth = lineWidth - layer.lineCap = .butt - layer.speed = speed - let halfWidth = lineWidth / 2 - let radius = (bounds.width - lineWidth) / 2 - layer.path = UIBezierPath(arcCenter: CGPoint(x: radius + halfWidth, - y: radius + halfWidth), - radius: radius, - startAngle: -CGFloat.pi / 2, - endAngle: 2 * CGFloat.pi, - clockwise: true).cgPath - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - - layer.removeAllAnimations() - animate() - } - - public override func reset() { - super.reset() - - layer.removeAllAnimations() - heightConstraint?.isActive = false - widthConstraint?.isActive = false - } - - //-------------------------------------------------- - // MARK: - Animation - //-------------------------------------------------- - - override open func didMoveToWindow() { - animate() - } - - struct Pose { - /// Delayed time (in seconds) to execute after the previous Pose. - let delay: CFTimeInterval - /// The time into the animation to begin drawing. - let startTime: CGFloat - /// The length of the drawn line. - let length: CGFloat - } - - // TODO: This needs more attention to improve frame smoothness. - class var poses: [Pose] { - get { - return [ - Pose(delay: 0.0, startTime: 0.000, length: 0.7), - Pose(delay: 0.7, startTime: 0.500, length: 0.5), - Pose(delay: 0.6, startTime: 1.000, length: 0.3), - Pose(delay: 0.5, startTime: 1.500, length: 0.2), - Pose(delay: 0.5, startTime: 1.875, length: 0.2), - Pose(delay: 0.3, startTime: 2.250, length: 0.3), - Pose(delay: 0.2, startTime: 2.600, length: 0.5), - Pose(delay: 0.2, startTime: 3.000, length: 0.7) - ] - } - } - - private func animate() { - var time: CFTimeInterval = 0 - var times = [CFTimeInterval]() - var start: CGFloat = 0 - var rotations = [CGFloat]() - var strokeEnds = [CGFloat]() - - let poses = Self.poses - var totalSeconds: CFTimeInterval = poses.reduce(0) { $0 + $1.delay } - - for pose in poses { - time += pose.delay - times.append(time / totalSeconds) - start = pose.startTime - rotations.append(start * 2 * CGFloat.pi) - strokeEnds.append(pose.length) - } - - totalSeconds += 0.3 - - animateKeyPath(keyPath: "strokeEnd", duration: totalSeconds, times: times, values: strokeEnds) - animateKeyPath(keyPath: "transform.rotation", duration: totalSeconds, times: times, values: rotations) - } - - private func animateKeyPath(keyPath: String, duration: CFTimeInterval, times: [CFTimeInterval], values: [CGFloat]) { - - let animation = CAKeyframeAnimation(keyPath: keyPath) - animation.keyTimes = times as [NSNumber]? - animation.values = values - animation.calculationMode = .linear - animation.timingFunction = CAMediaTimingFunction(name: .linear) - animation.duration = duration - animation.rotationMode = .rotateAuto - animation.fillMode = .forwards - animation.isRemovedOnCompletion = false - animation.repeatCount = .infinity - layer.add(animation, forKey: animation.keyPath) - } - - //-------------------------------------------------- - // MARK: - Methods - //-------------------------------------------------- - - func resumeSpinnerAfterDelay() { - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in - self?.resumeAnimations() - } - } - - func pauseAnimations() { - - let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil) - layer.speed = 0 - isHidden = true - layer.timeOffset = pausedTime - } - - func resumeAnimations() { - - let pausedTime = layer.timeOffset - isHidden = false - layer.speed = speed - layer.timeOffset = 0 - let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime - layer.beginTime = timeSincePause - } - - func stopAllAnimations() { - - layer.removeAllAnimations() - } - - func pinWidthAndHeight(diameter: CGFloat) { - - let dimension = diameter + lineWidth - heightConstraint?.constant = dimension - widthConstraint?.constant = dimension - heightConstraint?.isActive = true - widthConstraint?.isActive = true - } - - //-------------------------------------------------- - // MARK: - MoleculeViewProtocol - //-------------------------------------------------- - - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - guard let model = model as? LoadingSpinnerModel else { return } - - strokeColor = model.strokeColor.uiColor - lineWidth = model.lineWidth - pinWidthAndHeight(diameter: model.diameter) - } - - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 40.0 - } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift index b74807fb..6959bc8f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinnerModel.swift @@ -8,6 +8,7 @@ import Foundation import MVMCore +import VDS open class LoadingSpinnerModel: MoleculeModelProtocol { //-------------------------------------------------- @@ -17,8 +18,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { public var id: String = UUID().uuidString public var backgroundColor: Color? - public var strokeColor = Color(uiColor: .mvmBlack) - public var lineWidth: CGFloat = 4 + public var inverted: Bool = false public var diameter: CGFloat = 40 //-------------------------------------------------- @@ -28,10 +28,9 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { private enum CodingKeys: String, CodingKey { case id case moleculeName - case backgroundColor case strokeColor - case lineWidth case diameter + case inverted } //-------------------------------------------------- @@ -48,18 +47,17 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) { self.diameter = diameter } - if let strokeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .strokeColor) { - self.strokeColor = strokeColor + if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + self.inverted = inverted } - if let lineWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .lineWidth) { - self.lineWidth = lineWidth + if let strokeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .strokeColor) { + self.inverted = !strokeColor.uiColor.isDark() } } @@ -67,9 +65,11 @@ open class LoadingSpinnerModel: MoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(diameter, forKey: .diameter) - try container.encode(strokeColor, forKey: .strokeColor) - try container.encode(lineWidth, forKey: .lineWidth) + try container.encodeIfPresent(inverted, forKey: .inverted) } } + +extension LoadingSpinnerModel { + public var surface: Surface { inverted ? .dark : .light } +} From 9f2a1cb6d1f8a68c401f662b4eb4a03b2725fe87 Mon Sep 17 00:00:00 2001 From: Sureshkumar Ramachandran Date: Fri, 8 Dec 2023 14:42:50 +0530 Subject: [PATCH 17/77] Hamberg menu fix --- .../MVMCoreUISplitViewController+Extension.swift | 2 +- .../SplitViewController/MVMCoreUISplitViewController.h | 2 +- .../SplitViewController/MVMCoreUISplitViewController.m | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index 55e1071c..d407fdc3 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -263,7 +263,7 @@ extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol { } public func willDisplay(_ viewController: UIViewController) { - setupPanels() + setupPanels(viewController) updateState(with: viewController) } diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h index a5c1577f..ac057f10 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h @@ -99,7 +99,7 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) { - (void)setNavigationIconColor:(nullable UIColor *)color; /// Updates the panels that are used. -- (void)setupPanels; +- (void)setupPanels:(nullable UIViewController*)viewController; /// Returns if the left panel is staying extended (usually do to screen size threshold) - (BOOL)leftPanelStaysExtended; diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index c43d17d9..462bb6af 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -723,9 +723,9 @@ CGFloat const PanelAnimationDuration = 0.2; [panel removeFromParentViewController]; } -- (void)setupLeftPanel { +- (void)setupLeftPanel:(nullable UIViewController*)viewController { UIViewController *panel = nil; - UIViewController *currentViewController = [self getCurrentDetailViewController]; + UIViewController *currentViewController = viewController ? viewController : [self getCurrentDetailViewController]; if ([currentViewController respondsToSelector:@selector(overrideLeftPanel)]) { panel = [((UIViewController *)currentViewController) overrideLeftPanel]; } else { @@ -795,9 +795,9 @@ CGFloat const PanelAnimationDuration = 0.2; } } -- (void)setupPanels { +- (void)setupPanels:(nullable UIViewController*)viewController { [self forceHideBothDrawers]; - [self setupLeftPanel]; + [self setupLeftPanel:viewController]; [self setupRightPanel]; self.explictlyShowingPanel = nil; [self.view layoutIfNeeded]; @@ -968,7 +968,7 @@ CGFloat const PanelAnimationDuration = 0.2; [NSLayoutConstraint constraintWithItem:coverView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:coverView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0].active = YES; - [self setupPanels]; + [self setupPanels:nil]; } - (void)viewDidLoad { From fed441360678cea38d9b6b8e008b59780d06472f Mon Sep 17 00:00:00 2001 From: Sureshkumar Ramachandran Date: Fri, 8 Dec 2023 17:33:44 +0530 Subject: [PATCH 18/77] To avoid display on the hamberg menu at discover screen(Homescreen) --- .../SplitViewController/MVMCoreUISplitViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index 462bb6af..79c81b8d 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -735,6 +735,7 @@ CGFloat const PanelAnimationDuration = 0.2; if (!panel) { [self removePanel:self.leftPanel]; + self.leftPanel = nil; } else if (panel && panel != self.leftPanel) { [self removePanel:self.leftPanel]; [self addPanel:panel]; From cac849fadc48c192761d0656b21ae0ac4e4cdbba Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Mon, 11 Dec 2023 10:48:37 -0500 Subject: [PATCH 19/77] text field Spanish localization for optional --- MVMCoreUI/Atomic/Atoms/Views/Label/FormLabelModel.swift | 2 +- MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings | 2 +- .../SupportingFiles/Strings/es-MX.lproj/Localizable.strings | 1 + MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/FormLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/FormLabelModel.swift index c7552047..aee432e8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/FormLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/FormLabelModel.swift @@ -64,7 +64,7 @@ public class FormLabelModel: EnableableModelProtocol { if enabled { required.attributes = [LabelAttributeColorModel(FormLabelModel.defaultRequiredTextColor, model.text.count + 1, 8)] } - required.text = "\(model.text) Optional" + required.text = "\(model.text) \(MVMCoreUIUtility.hardcodedString(withKey: "textfield_optional") ?? "")" return required } diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index 0b736bf9..c5b9478e 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -30,7 +30,7 @@ "textfield_picker_item" = " picker item"; "textfield_regular" = " regular"; "textfield_disabled_state" = "disabled"; - +"textfield_optional" = "Optional"; // MARK: MDNTextfield "textfield_contacts_barbutton" = "My Contacts"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings index b279ccdb..b68dd624 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings @@ -26,6 +26,7 @@ "textfield_picker_item" = " artículo de selector"; "textfield_regular" = " regular"; "textfield_disabled_state" = "inactivo"; +"textfield_optional" = "Opcional"; //MDNTextfield "textfield_contacts_barbutton" = "Mis contactos"; "textfield_phone_format_error_message" = "Formato de número de teléfono inválido."; diff --git a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings index 150ac167..7eb53fa7 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings @@ -26,6 +26,7 @@ "textfield_picker_item" = " artículo de selector"; "textfield_regular" = " regular"; "textfield_disabled_state" = "inactivo"; +"textfield_optional" = "Opcional"; //MDNTextfield "textfield_contacts_barbutton" = "Mis contactos"; "textfield_phone_format_error_message" = "Formato de número de teléfono inválido."; From 8a90a8ce4abcd3dd2de3216cea83709f10253ced Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Dec 2023 14:18:44 -0600 Subject: [PATCH 20/77] added new codable from vds Signed-off-by: Matt Bruce --- .../Atomic/Extensions/VDS-Enums+Codable.swift | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 1d24a0bd..9b8f08ef 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -9,18 +9,23 @@ import Foundation import VDS -extension Surface: Codable {} -extension Badge.FillColor: Codable {} -extension Icon.Name: Codable {} -extension Icon.Size: Codable {} -extension TileContainer.BackgroundColor: Codable {} -extension TileContainer.Padding: Codable {} -extension TileContainer.AspectRatio: Codable {} -extension TextLink.Size: Codable {} +extension VDS.Surface: Codable {} +extension VDS.Badge.FillColor: Codable {} +extension VDS.Icon.Name: Codable {} +extension VDS.Icon.Size: Codable {} +extension VDS.TileContainer.BackgroundColor: Codable {} +extension VDS.TileContainer.Padding: Codable {} +extension VDS.TileContainer.AspectRatio: Codable {} +extension VDS.TextLink.Size: Codable {} extension VDS.Line.Style: Codable {} extension VDS.Line.Orientation: Codable {} -extension Use: Codable {} +extension VDS.Use: Codable {} +extension VDS.Tabs.Orientation: Codable {} +extension VDS.Tabs.IndicatorPosition: Codable {} +extension VDS.Tabs.Overflow: Codable {} +extension VDS.Tabs.Size: Codable {} + extension VDS.Button.Size: RawRepresentableCodable { public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } public static var defaultValue: VDS.Button.Size? { nil } -} \ No newline at end of file +} From 7c0e8bb106562201a946bcf91bcd4b6d3a35919e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Dec 2023 14:19:00 -0600 Subject: [PATCH 21/77] updated tabsModel and Tabs Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/Tabs.swift | 375 ++---------------- .../TabsModel.swift | 103 ++--- 2 files changed, 66 insertions(+), 412 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index e6689f3d..26c4cc3f 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -8,379 +8,64 @@ import UIKit import VDSColorTokens +import VDS @objc public protocol TabsDelegate { func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) } -@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol { +@objcMembers open class Tabs: VDS.Tabs, VDSMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol { - public var tabsModel: TabsModel? { - get { return model as? TabsModel } - } - - var delegateObject: MVMCoreUIDelegateObject? - var additionalData: [AnyHashable: Any]? - - let layout = UICollectionViewFlowLayout() - public var collectionView: CollectionView? - - let bottomScrollView = UIScrollView(frame: .zero) - let bottomContentView = View() - let bottomLine = Line() - let selectionLine = View() - var selectionLineLeftConstraint: NSLayoutConstraint? - var selectionLineWidthConstraint: NSLayoutConstraint? - - private var widthLabel = Label() + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + open var viewModel: TabsModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? //delegate weak public var delegate: TabsDelegate? - - //control var - public var selectedIndex: Int = 0 - public var paddingBeforeFirstTab: Bool = true - - //constant - let TabCellId = "TabCell" - public let itemSpacing: CGFloat = 20.0 - public let cellHeight: CGFloat = 28.0 - public let selectionLineHeight: CGFloat = 4.0 - public let minimumItemWidth: CGFloat = 32.0 - public let selectionLineMovingTime: TimeInterval = 0.2 - + //------------------------------------------------- // MARK: - Layout Views //------------------------------------------------- - open override func reset() { - super.reset() - selectedIndex = 0 - paddingBeforeFirstTab = true - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - collectionView?.updateView(size) - } - - open override func setupView() { - super.setupView() - backgroundColor = VDSColor.backgroundPrimaryLight - addSubview(bottomLine) - setupCollectionView() - setupSelectionLine() - setupConstraints() - } - - func setupCollectionView () { - layout.scrollDirection = .horizontal - layout.minimumLineSpacing = 0 + open func updateView(_ size: CGFloat) {} - let collectionView = CollectionView(frame: .zero, collectionViewLayout: layout) - collectionView.translatesAutoresizingMaskIntoConstraints = false - collectionView.register(TabItemCell.self, forCellWithReuseIdentifier: TabCellId) - collectionView.backgroundColor = .clear - collectionView.showsVerticalScrollIndicator = false - collectionView.showsHorizontalScrollIndicator = false - collectionView.dataSource = self - collectionView.delegate = self - addSubview(collectionView) - self.collectionView = collectionView - } - - func setupSelectionLine() { - bottomScrollView.translatesAutoresizingMaskIntoConstraints = false - bottomScrollView.delegate = self - addSubview(bottomScrollView) - bottomScrollView.addSubview(bottomContentView) - selectionLine.backgroundColor = VDSColor.paletteRed - bottomContentView.addSubview(selectionLine) - bringSubviewToFront(bottomScrollView) - } - - func setupConstraints() { - //collection view - NSLayoutConstraint.constraintPinSubview(collectionView, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) - collectionView?.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true - - //selection line - bottomScrollView.topAnchor.constraint(equalTo: collectionView!.bottomAnchor).isActive = true; - NSLayoutConstraint.constraintPinSubview(bottomScrollView, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true) - bottomScrollView.heightAnchor.constraint(equalToConstant: selectionLineHeight).isActive = true - NSLayoutConstraint.constraintPinSubview(selectionLine, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) - selectionLine.heightAnchor.constraint(equalToConstant: selectionLineHeight).isActive = true - selectionLineLeftConstraint = selectionLine.leftAnchor.constraint(equalTo: bottomContentView.leftAnchor) - selectionLineLeftConstraint?.isActive = true - selectionLineWidthConstraint = selectionLine.widthAnchor.constraint(equalToConstant: minimumItemWidth) - selectionLineWidthConstraint?.isActive = true - NSLayoutConstraint.constraintPinSubview(toSuperview: bottomContentView) - - //bottom line - bottomLine.topAnchor.constraint(equalTo: bottomScrollView.bottomAnchor).isActive = true; - NSLayoutConstraint.constraintPinSubview(bottomLine, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) - } - - open override func layoutSubviews() { - super.layoutSubviews() - // Accounts for any collection size changes - DispatchQueue.main.async { - self.layoutCollection() - } - } - - /// Invalidates the layout and ensures we are paged to the correct cell. - open func layoutCollection() { - collectionView?.collectionViewLayout.invalidateLayout() - - // 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. - DispatchQueue.main.async { - self.collectionView?.scrollToItem(at: IndexPath(row: self.selectedIndex, section: 0), at: .left, animated: false) - self.collectionView?.layoutIfNeeded() - } - } - //------------------------------------------------- // MARK: - Control Methods //------------------------------------------------- public func selectIndex(_ index: Int, animated: Bool) { - guard let _ = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { - selectedIndex = index - tabsModel?.selectedIndex = index - return - } - MVMCoreDispatchUtility.performBlock(onMainThread: { - let currentIndex = self.selectedIndex - self.selectedIndex = index - self.tabsModel?.selectedIndex = index - self.deselect(indexPath: IndexPath(row: currentIndex, section: 0)) - self.selectItem(atIndexPath: IndexPath(row: index, section: 0), animated: animated) - }) + self.selectedIndex = index } - public func reloadData() { - collectionView?.reloadData() - } + public func reloadData() { setNeedsUpdate() } //------------------------------------------------- // MARK: - Molecule Setup //------------------------------------------------- - override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.set(with: model, delegateObject, additionalData) - self.delegateObject = delegateObject - self.additionalData = additionalData - selectedIndex = tabsModel?.selectedIndex ?? 0 - selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor - let lineModel = bottomLine.viewModel ?? LineModel(type: .secondary) - lineModel.inverted = tabsModel?.style == .dark - bottomLine.set(with: lineModel, delegateObject, additionalData) - reloadData() - } -} - -//------------------------------------------------- -// MARK: - Collection View Methods -//------------------------------------------------- - -extension Tabs: UICollectionViewDataSource { - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return tabsModel?.tabs.count ?? 0 - } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else { - return UICollectionViewCell() - } - cell.updateCell(indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel) - updateView(collectionView.bounds.width) - return cell - } -} - -extension Tabs: UICollectionViewDelegateFlowLayout { - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - guard self.collectionView(collectionView, numberOfItemsInSection: indexPath.section) != 2 else { - // If two tabs, take up the screen - let insets = self.collectionView(collectionView, layout: collectionViewLayout, insetForSectionAt: indexPath.section) - let width = (collectionView.bounds.width / 2.0) - insets.left - insets.right - return CGSize(width: width, height: cellHeight) - } - guard let labelModel = tabsModel?.tabs[indexPath.row].label else { - return .zero - } - return CGSize(width: max(minimumItemWidth, getLabelWidth(labelModel).width), height: cellHeight) - } - - //pre calculate the width of the collection cell - //when user select tabs, it will reload related collectionview, if we use autosize, it would relayout the width, need to keep the cell width constant. - func getLabelWidth(_ labelModel: LabelModel?) -> CGSize { - guard let labelModel = labelModel else { return .zero} - widthLabel.set(with: labelModel, nil, nil) - let cgSize = widthLabel.intrinsicContentSize - widthLabel.reset() - return cgSize - } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { - guard section == 0 else { - return UIEdgeInsets(top: 0, left: itemSpacing, bottom: 0, right: 0) - } - guard paddingBeforeFirstTab else { - return .zero - } - return UIEdgeInsets(top: 0, left: Padding.Component.horizontalPaddingForApplicationWidth, bottom: 0, right: 0) - } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { - // If two tabs, take up the screen, no space between items - guard self.collectionView(collectionView, numberOfItemsInSection: section) != 2 else { - return 0 - } - return itemSpacing - } - - public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - return delegate?.shouldSelectItem(indexPath, tabs: self) ?? true - } - - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - selectIndex(indexPath.row, animated: true) - } - - public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { - guard let tabCell = cell as? TabItemCell else { return } - if indexPath.row == selectedIndex { - DispatchQueue.main.async { - self.moveSelectionLine(toIndex: indexPath, animated: false, cell: tabCell) + open func viewModelDidUpdate() { + orientation = viewModel.orientation + indicatorPosition = viewModel.indicatorPosition + overflow = viewModel.overflow + size = viewModel.size + selectedIndex = viewModel.selectedIndex + surface = viewModel.style ?? .light + tabModels = viewModel.tabs.compactMap { TabModel(text: $0.label.text) } + + if let delegate { + onTabChange = { [weak self] index in + guard let self else { return } + delegate.didSelectItem(.init(row: index, section: 0), tabs: self) + } + + onTabShouldSelect = { [weak self] index in + guard let self else { return true } + return delegate.shouldSelectItem(.init(row: index, section: 0), tabs: self) } } } - - func deselect(indexPath:IndexPath) { - collectionView?.deselectItem(at: indexPath, animated: false) - collectionView?.reloadItems(at: [indexPath]) - } - - func selectItem(atIndexPath indexPath: IndexPath, animated: Bool) { - - guard let collect = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { return } - - collect.selectItem(at: indexPath, animated: animated, scrollPosition: .centeredHorizontally) - guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = tabsModel else { return } - moveSelectionLine(toIndex: indexPath, animated: animated, cell: tabCell) - tabCell.label.textColor = tabsModel.selectedColor.uiColor - tabCell.updateAccessibility(indexPath: indexPath, selected: true, tabsModel: tabsModel) - tabCell.setNeedsDisplay() - tabCell.setNeedsLayout() - tabCell.layoutIfNeeded() - if let delegate = delegate { - delegate.didSelectItem(indexPath, tabs: self) - } else if let action = tabsModel.tabs[selectedIndex].action { - MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: tabsModel, additionalData: nil, delegateObject: delegateObject) - } - if UIAccessibility.isVoiceOverRunning { - UIAccessibility.post(notification: .layoutChanged, argument: tabCell) - } - } } - - -extension Tabs: UIScrollViewDelegate { - public func scrollViewDidScroll(_ scrollView: UIScrollView) { - /*bottomScrollview is subview of self, it's not belongs to collectionview. - When collectionview is scrolling, bottomScrollView will stay without moving - Adding collectionview's offset to bottomScrollView, will make the bottomScrollview looks like scrolling with the selected tab item. - */ - guard let offsetX = collectionView?.contentOffset.x else { return } - bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false) - } -} - - -//------------------------------------------------- -// MARK: - Bottom Line Methods -//------------------------------------------------- -extension Tabs { - func moveSelectionLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) { - guard let collect = collectionView else {return} - - let size = collectionView(collect, layout: layout, sizeForItemAt: indexPath) - let animationBlock = { - [weak self] in - self?.selectionLineWidthConstraint?.constant = size.width - self?.selectionLineLeftConstraint?.constant = cell.frame.origin.x - self?.bottomContentView.layoutIfNeeded() - } - if animated { - UIView.animate(withDuration: selectionLineMovingTime, animations: animationBlock) - } else { - animationBlock() - } - } - - /// Adjust the line based on the percentage - func progress(from index: Int, toIndex: Int, percentage: CGFloat) { - let fromIndexPath = IndexPath(row: index, section: 0) - let toIndexPath = IndexPath(row: toIndex, section: 0) - guard let collection = collectionView, - let fromCell = collection.cellForItem(at: fromIndexPath), - let toCell = collection.cellForItem(at: toIndexPath) else { return } - - // setting the width for percentage - selectionLineWidthConstraint?.constant = (toCell.bounds.width - fromCell.bounds.width) * percentage + fromCell.bounds.width - - // setting the x for percentage - let originalX = fromCell.frame.origin.x - let toX = toCell.frame.origin.x - let xDifference = toX - originalX - let finalX = (xDifference * percentage) + originalX - selectionLineLeftConstraint?.constant = finalX - - bottomContentView.layoutIfNeeded() - } -} - -@objcMembers public class TabItemCell: CollectionViewCell { - public let label = Label() - - public override func setupView() { - super.setupView() - contentView.addSubview(label) - NSLayoutConstraint.constraintPinSubview(label, pinTop: false, topConstant: 0, pinBottom: true, bottomConstant: 6, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0) - label.baselineAdjustment = .alignCenters - } - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - label.updateView(size) - } - - public func updateCell(indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) { - guard let tabsModel = tabsModel else { return } - label.reset() - label.set(with: tabsModel.tabs[indexPath.row].label, delegateObject, additionalData) - if selected { - label.textColor = tabsModel.selectedColor.uiColor - } else { - label.textColor = tabsModel.unselectedColor.uiColor - } - updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel) - } - - public func updateAccessibility(indexPath: IndexPath, selected: Bool, tabsModel: TabsModel?) { - //Accessibility - isAccessibilityElement = false - contentView.isAccessibilityElement = true - let accKey = selected ? "toptabbar_tab_selected" : "AccTab" - let accLabel = "\(label.text ?? "") \(MVMCoreUIUtility.hardcodedString(withKey: accKey) ?? "")" - let accOrder = String(format: MVMCoreUIUtility.hardcodedString(withKey: "AccTabIndex") ?? "", indexPath.row + 1, tabsModel?.tabs.count ?? 0) - contentView.accessibilityLabel = "\(accLabel) \(accOrder)" - contentView.accessibilityHint = selected ? nil : MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint") - } -} - - diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 3671e5e1..648357b3 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -8,67 +8,22 @@ import UIKit import VDSColorTokens - +import VDS open class TabsModel: MoleculeModelProtocol { + public static var identifier: String = "tabs" public var id: String = UUID().uuidString open var tabs: [TabItemModel] - open var style: NavigationItemStyle? - - private var _backgroundColor: Color? - open var backgroundColor: Color? { - get { - if let backgroundColor = _backgroundColor { return backgroundColor } - if let style = style, - style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) } - return Color(uiColor: VDSColor.backgroundPrimaryLight) - } - set { - _backgroundColor = newValue - } - } - - private var _selectedColor: Color? - open var selectedColor: Color { - get { - if let selectedColor = _selectedColor { return selectedColor } - if let style = style, - style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) } - return Color(uiColor: VDSColor.elementsPrimaryOnlight) - } - set { - _selectedColor = newValue - } - } - - private var _unselectedColor: Color? - open var unselectedColor: Color { - get { - if let unselectedColor = _unselectedColor { return unselectedColor } - if let style = style, - style == .dark { return Color(uiColor: VDSColor.elementsSecondaryOndark) } - return Color(uiColor: VDSColor.elementsSecondaryOnlight) - } - set { - _unselectedColor = newValue - } - } - - private var _selectedBarColor: Color? - open var selectedBarColor: Color { - get { - if let selectedBarColor = _selectedBarColor { return selectedBarColor } - if let style = style, - style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) } - return Color(uiColor: VDSColor.paletteRed) - } - set { - _selectedBarColor = newValue - } - } - + open var style: Surface? + + open var orientation: Tabs.Orientation = .horizontal + open var indicatorPosition: Tabs.IndicatorPosition = .bottom + open var overflow: Tabs.Overflow = .scroll + open var size: Tabs.Size = .medium + public var backgroundColor: Color? + // Must be capped to 0...(tabs.count - 1) open var selectedIndex: Int = 0 @@ -77,10 +32,11 @@ open class TabsModel: MoleculeModelProtocol { case moleculeName case tabs case backgroundColor - case selectedColor - case unselectedColor - case selectedBarColor case selectedIndex + case orientation + case indicatorPosition + case overflow + case size case style } @@ -92,14 +48,26 @@ open class TabsModel: MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - _selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) - _unselectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .unselectedColor) - _selectedBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedBarColor) - style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) + style = try typeContainer.decodeIfPresent(Surface.self, forKey: .style) if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { selectedIndex = index } + + if let orientation = try typeContainer.decodeIfPresent(VDS.Tabs.Orientation.self, forKey: .orientation) { + self.orientation = orientation + } + + if let indicatorPosition = try typeContainer.decodeIfPresent(VDS.Tabs.IndicatorPosition.self, forKey: .indicatorPosition) { + self.indicatorPosition = indicatorPosition + } + + if let overflow = try typeContainer.decodeIfPresent(VDS.Tabs.Overflow.self, forKey: .overflow) { + self.overflow = overflow + } + + if let size = try typeContainer.decodeIfPresent(VDS.Tabs.Size.self, forKey: .orientation) { + self.size = size + } } open func encode(to encoder: Encoder) throws { @@ -107,12 +75,13 @@ open class TabsModel: MoleculeModelProtocol { try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) - try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(_selectedColor, forKey: .selectedColor) - try container.encodeIfPresent(_unselectedColor, forKey: .unselectedColor) - try container.encodeIfPresent(_selectedBarColor, forKey: .selectedBarColor) try container.encode(selectedIndex, forKey: .selectedIndex) try container.encodeIfPresent(style, forKey: .style) + try container.encode(orientation, forKey: .orientation) + try container.encode(overflow, forKey: .overflow) + try container.encode(size, forKey: .size) + try container.encode(indicatorPosition, forKey: .indicatorPosition) + } } From 18372f9ed6020ac0be7735d27ef5984e1bef3b34 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Dec 2023 14:19:29 -0600 Subject: [PATCH 22/77] fixed bug Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift index becb0106..aca15eba 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsListItemModel.swift @@ -81,7 +81,9 @@ extension TabsListItemModel: PageBehaviorProtocolRequirer { extension TabsListItemModel: AddMolecules { public func moleculesToAdd() -> AddMolecules.AddParameters? { guard addedMolecules == nil else { return nil } - let addedMolecules = molecules[tabs.selectedIndex] + let index = tabs.selectedIndex + guard molecules.count >= index else { return nil } + let addedMolecules = molecules[index] self.addedMolecules = addedMolecules return (addedMolecules, .below) } From 49a385c12a738a217ec0c72bbc06d14b097a8b22 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Dec 2023 14:19:49 -0600 Subject: [PATCH 23/77] removed legacy properties Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift index e904707e..26d5b7d4 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift @@ -19,10 +19,8 @@ import UIKit // MARK: - MFViewProtocol override public func setupView() { super.setupView() - tabs.paddingBeforeFirstTab = false tabs.translatesAutoresizingMaskIntoConstraints = false tabs.delegate = self - tabs.bottomLine.setStyle(.none) contentView.addSubview(tabs) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values)) @@ -47,7 +45,6 @@ import UIKit public override func reset() { super.reset() tabs.reset() - tabs.paddingBeforeFirstTab = false } public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 46 } From 7baa6d31a0b2f5c524e021468f0e1a24e331a5e4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Dec 2023 14:20:06 -0600 Subject: [PATCH 24/77] pointed to new property Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index c7f0f869..85e487ae 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -157,7 +157,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, /// Logs the action for the selected tab. open func trackSelectTab() { - guard let action = tabs.tabsModel?.tabs[tabs.selectedIndex].action else { return } + guard let action = tabs.viewModel?.tabs[tabs.selectedIndex].action else { return } MVMCoreUIActionHandler.shared()?.logAction(with: action.toJSON(), additionalData: getAdditionalDataForNewTabLoad(indexPath: IndexPath(row: tabs.selectedIndex, section: 0)), delegateObject: delegateObjectIVar) } @@ -276,7 +276,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, Task(priority: .userInitiated) { await NavigationHandler.shared().replace(viewController: controller, navigationController:subNavigationController, delegateObject:delegateObject(), tryToReplace: false, animated: true) } - } else if let tabsModel = tabs.tabsModel, + } else if let tabsModel = tabs.viewModel, let action = tabsModel.tabs[indexPath.row].action { // Perform the tab action MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: tabsModel, additionalData: getAdditionalDataForNewTabLoad(indexPath: indexPath), delegateObject: delegateObject()) @@ -329,7 +329,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, // MARK: - MVMCoreUISwipeNavigationProtocol public func swipeLeft() { - guard tabs.selectedIndex < (tabs.tabsModel?.tabs.count ?? 0) - 1 else { return } + guard tabs.selectedIndex < (tabs.viewModel?.tabs.count ?? 0) - 1 else { return } _ = shouldSelectItem(IndexPath(row: tabs.selectedIndex + 1, section: 0), tabs: tabs) } @@ -341,6 +341,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, public func update(percentage: CGFloat) { guard customInteractor?.interactive == true, let index = index else { return } - tabs.progress(from: tabs.selectedIndex, toIndex: index, percentage: percentage) +// tabs.progress(from: tabs.selectedIndex, toIndex: index, percentage: percentage) } } From 71e291ccb52af45024ef3bdc8af81b21b0452af9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 13 Dec 2023 14:39:01 -0600 Subject: [PATCH 25/77] updated api Signed-off-by: Matt Bruce --- .../Atomic/Molecules/HorizontalCombinationViews/Tabs.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 26c4cc3f..178e9c3d 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -57,7 +57,7 @@ import VDS tabModels = viewModel.tabs.compactMap { TabModel(text: $0.label.text) } if let delegate { - onTabChange = { [weak self] index in + onTabDidSelect = { [weak self] index in guard let self else { return } delegate.didSelectItem(.init(row: index, section: 0), tabs: self) } From 6c3092a1f6b2bd8f7d46de04deff72bf5d32f1d8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Dec 2023 15:12:16 -0600 Subject: [PATCH 26/77] added more codables and default codable property wrappers Signed-off-by: Matt Bruce --- .../Atomic/Extensions/VDS-Enums+Codable.swift | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 1d24a0bd..050952b8 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -8,7 +8,11 @@ import Foundation import VDS +import VDSColorTokens +//-------------------------------------------------- +// MARK: - Codable Extensions +//-------------------------------------------------- extension Surface: Codable {} extension Badge.FillColor: Codable {} extension Icon.Name: Codable {} @@ -20,7 +24,31 @@ extension TextLink.Size: Codable {} extension VDS.Line.Style: Codable {} extension VDS.Line.Orientation: Codable {} extension Use: Codable {} + extension VDS.Button.Size: RawRepresentableCodable { public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } public static var defaultValue: VDS.Button.Size? { nil } -} \ No newline at end of file +} + +//-------------------------------------------------- +// MARK: - Decodable Defaults +//-------------------------------------------------- +extension DecodableDefault.Sources { + public struct Surface: DecodableDefaultSource { + public static var defaultValue: VDS.Surface { .light } + } + + public struct IconSize: DecodableDefaultSource { + public static var defaultValue: VDS.Icon.Size { .medium } + } + + public struct BlackColor: DecodableDefaultSource { + public static var defaultValue: Color { .init(uiColor: VDSColor.paletteBlack) } + } +} + +extension DecodableDefault { + public typealias IconSize = Wrapper + public typealias BlackColor = Wrapper + public typealias Surface = Wrapper +} From d92973dc551e52338116c1791a2244c8e05bf68b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Dec 2023 15:12:38 -0600 Subject: [PATCH 27/77] updated decoder to look for VDS Color name as well as hex Signed-off-by: Matt Bruce --- MVMCoreUI/CustomPrimitives/Color.swift | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/CustomPrimitives/Color.swift b/MVMCoreUI/CustomPrimitives/Color.swift index b251f778..9245153d 100644 --- a/MVMCoreUI/CustomPrimitives/Color.swift +++ b/MVMCoreUI/CustomPrimitives/Color.swift @@ -84,10 +84,17 @@ public final class Color: Codable { required public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let colorString = try container.decode(String.self) - let components = try Color.getColorComponents(for: colorString) - self.uiColor = components.color - hex = components.hex - name = components.name ?? "" + + if let vdsColor = UIColor.VDSColor(rawValue: colorString) { + self.uiColor = vdsColor.uiColor + hex = uiColor.hexString ?? "" + } else { + let components = try Color.getColorComponents(for: colorString) + self.uiColor = components.color + hex = components.hex + name = components.name ?? "" + } + determineRGBA() } From c25c3ec9abc8a1b240772a3e3a150aeb54218aff Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Dec 2023 15:13:08 -0600 Subject: [PATCH 28/77] added initial cut for icon, iconModel and registered it within the system. Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 14 ++++- MVMCoreUI/Atomic/Atoms/Views/Icon.swift | 60 +++++++++++++++++++ MVMCoreUI/Atomic/Atoms/Views/IconModel.swift | 38 ++++++++++++ .../OtherHandlers/CoreUIModelMapping.swift | 1 + 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Icon.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/IconModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8619ce46..f5aa5924 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -298,8 +298,8 @@ AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; }; AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; }; AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; }; - B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; }; + B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -574,10 +574,12 @@ EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; }; EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; }; EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; }; + EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; }; + EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81612B2B6E7F00D29F9E /* IconModel.swift */; }; EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; }; EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; }; - EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; }; + EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; }; EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; }; EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; }; @@ -890,8 +892,8 @@ AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = ""; }; AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = ""; }; AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; - B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = ""; }; + B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1167,6 +1169,8 @@ EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = ""; }; EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = ""; }; EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = ""; }; + EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; + EA7D81612B2B6E7F00D29F9E /* IconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModel.swift; sourceTree = ""; }; EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = ""; }; EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = ""; }; EA985C3D2970938F00F2FF2E /* Tilelet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tilelet.swift; sourceTree = ""; }; @@ -2242,6 +2246,8 @@ B4CC8FBC29DF34680005D28B /* Badge.swift */, EA985C3F2970939A00F2FF2E /* TileletModel.swift */, EA985C3D2970938F00F2FF2E /* Tilelet.swift */, + EA7D81612B2B6E7F00D29F9E /* IconModel.swift */, + EA7D815F2B2B6E6800D29F9E /* Icon.swift */, ); path = Views; sourceTree = ""; @@ -2963,6 +2969,7 @@ C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */, BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */, D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, + EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */, 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */, BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */, 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */, @@ -3134,6 +3141,7 @@ D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */, BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */, C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, + EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */, D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */, D2B9D0E4265EEE9D0084735C /* MoleculeListProtocol.swift in Sources */, D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Icon.swift b/MVMCoreUI/Atomic/Atoms/Views/Icon.swift new file mode 100644 index 00000000..a01c6b12 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Icon.swift @@ -0,0 +1,60 @@ +// +// Icon.swift +// MVMCoreUI +// +// Created by Matt Bruce on 12/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +/** + This class expects its height and width to be equal. + */ +open class Icon: VDS.Icon, VDSMoleculeViewProtocol{ + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var viewModel: IconModel! + public var delegateObject: MVMCoreUIDelegateObject? + public var additionalData: [AnyHashable: Any]? + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public convenience required init() { + self.init(frame: .zero) + } + + //-------------------------------------------------- + // MARK: - Public + //-------------------------------------------------- + public func viewModelDidUpdate() { + surface = viewModel.surface + color = viewModel.color.uiColor + size = viewModel.size + customSize = viewModel.customSize + name = viewModel.name + } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open func updateView(_ size: CGFloat) {} + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + //since this is a class func, we can't reference it directly + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + VDS.Icon.Size.medium.dimensions.height + } +} + +extension Icon: MVMCoreUIViewConstrainingProtocol { + + public func needsToBeConstrained() -> Bool { true } + + public func horizontalAlignment() -> UIStackView.Alignment { .leading } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift b/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift new file mode 100644 index 00000000..a1339cf3 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift @@ -0,0 +1,38 @@ +// +// IconModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 12/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS +import VDSColorTokens + +open class IconModel: MoleculeModelProtocol { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "icon" + + @DecodableDefault.UUIDString public var id: String + + public var backgroundColor: Color? + + /// A representation that will be used to render the icon with corresponding name. + public var name: Icon.Name + + /// Color of the icon. + @DecodableDefault.BlackColor() public var color: Color + + /// Enum for a preset height and width for the icon. + @DecodableDefault.IconSize public var size: VDS.Icon.Size + + /// surface of the object + @DecodableDefault.Surface public var surface: VDS.Surface + + /// A custom size of the icon. + public var customSize: Int? +} diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index b339cf94..3beff265 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -73,6 +73,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: Video.self, for: VideoModel.self) ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self) ModelRegistry.register(handler: Badge.self, for: BadgeModel.self) + ModelRegistry.register(handler: Icon.self, for: IconModel.self) // MARK:- Horizontal Combination Molecules ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self) From c191066523879839cf0934170b1aa0d208754ca1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Dec 2023 16:04:08 -0600 Subject: [PATCH 29/77] added enum codables for tooltip Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 1d24a0bd..0e455cd0 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -19,8 +19,10 @@ extension TileContainer.AspectRatio: Codable {} extension TextLink.Size: Codable {} extension VDS.Line.Style: Codable {} extension VDS.Line.Orientation: Codable {} +extension VDS.Tooltip.FillColor: Codable {} +extension VDS.Tooltip.Size: Codable {} extension Use: Codable {} extension VDS.Button.Size: RawRepresentableCodable { public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } public static var defaultValue: VDS.Button.Size? { nil } -} \ No newline at end of file +} From 61cb8b300b009a844420aed9e6d4a320bfa52e72 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Dec 2023 16:04:24 -0600 Subject: [PATCH 30/77] added tooltip view and model Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 14 ++- MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift | 66 +++++++++++++ .../Atomic/Atoms/Views/TooltipModel.swift | 98 +++++++++++++++++++ 3 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8619ce46..58eddd71 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -298,8 +298,8 @@ AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; }; AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; }; AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; }; - B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; }; + B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -574,10 +574,12 @@ EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; }; EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; }; EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; }; + EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */; }; + EA7D81662B2BABD200D29F9E /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81652B2BABD200D29F9E /* Tooltip.swift */; }; EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; }; EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; }; - EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; }; + EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; }; EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; }; EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; }; @@ -890,8 +892,8 @@ AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = ""; }; AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = ""; }; AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; - B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = ""; }; + B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1167,6 +1169,8 @@ EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = ""; }; EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = ""; }; EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = ""; }; + EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = ""; }; + EA7D81652B2BABD200D29F9E /* Tooltip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tooltip.swift; sourceTree = ""; }; EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = ""; }; EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = ""; }; EA985C3D2970938F00F2FF2E /* Tilelet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tilelet.swift; sourceTree = ""; }; @@ -2242,6 +2246,8 @@ B4CC8FBC29DF34680005D28B /* Badge.swift */, EA985C3F2970939A00F2FF2E /* TileletModel.swift */, EA985C3D2970938F00F2FF2E /* Tilelet.swift */, + EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */, + EA7D81652B2BABD200D29F9E /* Tooltip.swift */, ); path = Views; sourceTree = ""; @@ -2936,7 +2942,9 @@ 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */, D23118B325124E18001C8440 /* NotificationMoleculeView.swift in Sources */, + EA7D81662B2BABD200D29F9E /* Tooltip.swift in Sources */, AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */, + EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */, AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift b/MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift new file mode 100644 index 00000000..92692265 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift @@ -0,0 +1,66 @@ +// +// Tooltip.swift +// MVMCoreUI +// +// Created by Matt Bruce on 12/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class Tooltip: VDS.Tooltip, VDSMoleculeViewProtocol{ + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var viewModel: MVMCoreUI.TooltipModel! + public var delegateObject: MVMCoreUIDelegateObject? + public var additionalData: [AnyHashable: Any]? + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public convenience required init() { + self.init(frame: .zero) + } + + //-------------------------------------------------- + // MARK: - Public + //-------------------------------------------------- + public func viewModelDidUpdate() { + surface = viewModel.surface + fillColor = viewModel.fillColor + size = viewModel.size + closeButtonText = viewModel.closeButtonText + title = viewModel.title + content = viewModel.content + + if let moleculeModel = viewModel.molecule { + if contentView != nil { + (contentView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData) + } else if let molecule = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { + contentView = molecule + } + } + } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open func updateView(_ size: CGFloat) {} + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + //since this is a class func, we can't reference it directly + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + VDS.Icon.Size.medium.dimensions.height + } +} + +extension Tooltip: MVMCoreUIViewConstrainingProtocol { + + public func needsToBeConstrained() -> Bool { true } + + public func horizontalAlignment() -> UIStackView.Alignment { .leading } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift new file mode 100644 index 00000000..713e18ea --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift @@ -0,0 +1,98 @@ +// +// TooltipModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 12/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS +import VDSColorTokens +import MVMCore + +open class TooltipModel: MoleculeModelProtocol { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "tooltip" + + @DecodableDefault.UUIDString public var id: String + + public var backgroundColor: Color? + + public var size: VDS.Tooltip.Size = .medium + + public var fillColor: VDS.Tooltip.FillColor = .primary + + public var closeButtonText: String = "Close" + + public var title: String? + + public var content: String? + + public var molecule: MoleculeModelProtocol? + + /// surface of the object + public var surface: VDS.Surface = .light + + private enum CodingKeys: String, CodingKey { + case id + case moleculeName + case backgroundColor + case closeButtonText + case title + case content + case contentView + case size + case fillColor + case surface + } + + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + self.backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor) + + self.title = try container.decodeIfPresent(String.self, forKey: .title) + self.content = try container.decodeIfPresent(String.self, forKey: .content) + + self.molecule = try container.decodeModelIfPresent(codingKey: .contentView) + + if let closeButtonText = try container.decodeIfPresent(String.self, forKey: .closeButtonText) { + self.closeButtonText = closeButtonText + } + + if let surface = try container.decodeIfPresent(VDS.Surface.self, forKey: .surface) { + self.surface = surface + } + + if let size = try container.decodeIfPresent(VDS.Tooltip.Size.self, forKey: .size) { + self.size = size + } + + if let fillColor = try container.decodeIfPresent(VDS.Tooltip.FillColor.self, forKey: .fillColor) { + self.fillColor = fillColor + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(id, forKey: .id) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(surface, forKey: .surface) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + + try container.encodeIfPresent(size, forKey: .size) + try container.encodeIfPresent(fillColor, forKey: .fillColor) + + try container.encodeIfPresent(closeButtonText, forKey: .closeButtonText) + try container.encodeIfPresent(title, forKey: .title) + try container.encodeIfPresent(content, forKey: .content) + + try container.encodeModelIfPresent(molecule, forKey: .contentView) + } + +} From 51f9f2eba29f1c45966347ab465968e8dfb23020 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Dec 2023 16:04:31 -0600 Subject: [PATCH 31/77] registered view Signed-off-by: Matt Bruce --- MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index b339cf94..4c0f3f70 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -73,6 +73,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: Video.self, for: VideoModel.self) ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self) ModelRegistry.register(handler: Badge.self, for: BadgeModel.self) + ModelRegistry.register(handler: Tooltip.self, for: TooltipModel.self) // MARK:- Horizontal Combination Molecules ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self) From 83b2cb80ad702f7c63ba3d1fdaed5681c49f06b7 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 15 Dec 2023 16:17:36 -0600 Subject: [PATCH 32/77] refactored two link view Signed-off-by: Matt Bruce --- .../TwoLinkView.swift | 119 +++++++++--------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift index 09a09dcd..cd15066e 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift @@ -7,79 +7,81 @@ // import Foundation +import VDS - -@objcMembers open class TwoLinkView: View, MVMCoreUIViewConstrainingProtocol { +@objcMembers open class TwoLinkView: VDS.View, VDSMoleculeViewProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - + open var viewModel: TwoLinkViewModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + open var leftLink = Link() open var rightLink = Link() - private var stack = UIStackView() + private var buttonGroup = VDS.ButtonGroup() + private var buttons: [Link] = [] + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + open override func setup() { + super.setup() + isAccessibilityElement = false + addSubview(buttonGroup) + buttonGroup.pinToSuperView() + buttonGroup.alignment = .center + buttonGroup.rowQuantityPhone = 2 + buttonGroup.rowQuantityTablet = 2 + buttonGroup.childWidth = .percentage(50) + } + //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - stack.updateView(size) + open override func reset() { + super.reset() + leftLink.reset() + rightLink.reset() + buttonGroup.reset() } - - open override func setupView() { - super.setupView() - - stack.translatesAutoresizingMaskIntoConstraints = false - addSubview(stack) - stack.addArrangedSubview(leftLink) - stack.addArrangedSubview(rightLink) - NSLayoutConstraint.constraintPinSubview(toSuperview: stack) - stack.axis = .horizontal - stack.spacing = 8 - } - + + open func updateView(_ size: CGFloat) { } + //-------------------------------------------------- // MARK: - Stack Manipulation //-------------------------------------------------- public func showRightLink() { - if !stack.arrangedSubviews.contains(rightLink) { - stack.addArrangedSubview(rightLink) - rightLink.isHidden = false + if !buttons.contains(rightLink) { + buttons.insert(rightLink, at: buttons.count) } + buttonGroup.buttons = buttons } public func showLeftLink() { - if !stack.arrangedSubviews.contains(leftLink) { - stack.insertArrangedSubview(leftLink, at: 0) - leftLink.isHidden = false + if !buttons.contains(leftLink) { + buttons.insert(leftLink, at: 0) } + buttonGroup.buttons = buttons } public func hideRightLink() { - if rightLink.superview != nil { - stack.removeArrangedSubview(rightLink) - rightLink.isHidden = true + if let index = buttons.firstIndex(of: rightLink) { + buttons.remove(at: index) } + buttonGroup.buttons = buttons } public func hideLeftLink() { - if leftLink.superview != nil { - stack.removeArrangedSubview(leftLink) - leftLink.isHidden = true + if let index = buttons.firstIndex(of: leftLink) { + buttons.remove(at: index) } + buttonGroup.buttons = buttons } - - //-------------------------------------------------- - // MARK: - MoleculeViewProtocol - //-------------------------------------------------- - - open override func reset() { - super.reset() - stack.reset() - } - + //-------------------------------------------------- // MARK: - MVMCoreUIViewConstrainingProtocol //-------------------------------------------------- @@ -92,27 +94,26 @@ import Foundation // MARK: - MoleculeViewProtocol //-------------------------------------------------- - public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 16 + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? TwoButtonViewModel, + let buttonModel = model.primaryButton ?? model.secondaryButton + else { return 0 } + + return PillButton.estimatedHeight(with: buttonModel, delegateObject) } - - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - - guard let model = model as? TwoLinkViewModel else { return } - - if let model = model.leftLink { - showLeftLink() + + public func viewModelDidUpdate() { + if let model = viewModel.leftLink { leftLink.set(with: model, delegateObject, additionalData) - } else { - hideLeftLink() + buttons.append(leftLink) } - if let model = model.rightLink { - showRightLink() + if let model = viewModel.rightLink { rightLink.set(with: model, delegateObject, additionalData) - } else { - hideRightLink() + buttons.append(rightLink) } + + buttonGroup.buttons = buttons } + } From ad48df224219425fee72b33c3dad483aec756b01 Mon Sep 17 00:00:00 2001 From: "Rajendran, Nandhini" Date: Thu, 21 Dec 2023 16:28:22 +0000 Subject: [PATCH 33/77] story: ONEAPP-4156 LoggingHandler Swift migration --- MVMCoreUI.xcodeproj/project.pbxproj | 14 +++++------ .../Atomic/Atoms/Views/Label/Label.swift | 10 +++----- .../Atomic/Atoms/Views/Video/Video.swift | 2 +- .../OtherContainers/ModuleMolecule.swift | 2 +- .../Protocols/MoleculeViewProtocol.swift | 2 +- .../BaseControllers/ViewController.swift | 2 +- .../PageBehaviorHandlerProtocol.swift | 2 +- MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- MVMCoreUI/MVMCoreUI.h | 1 - .../Notification/NotificationHandler.swift | 2 +- .../OtherHandlers/MVMCoreUILoggingHandler.h | 24 ------------------- .../OtherHandlers/MVMCoreUILoggingHandler.m | 23 ------------------ .../MVMCoreUILoggingHandler.swift | 21 ++++++++++++++++ MVMCoreUI/Utility/MFFonts.m | 7 ++++-- 14 files changed, 42 insertions(+), 72 deletions(-) delete mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h delete mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m create mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8619ce46..e8c2d064 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -168,8 +168,10 @@ 526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */; }; 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */; }; 52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */; }; + 608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; }; 7199C8162A4F3A64001568B7 /* AccessibilityHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */; }; 71BE969E2AD96BE6000B5DB7 /* RotorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */; }; + 608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; }; 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */; }; 8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */; }; 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */; }; @@ -473,8 +475,6 @@ D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */; }; D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF26F21E6AA0B003B2FB9 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF26B21E6AA0B003B2FB9 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */; }; D29DF27921E7A533003B2FB9 /* MVMCoreUISession.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */; }; D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF27F21E7AA50003B2FB9 /* MVMCoreUIDetailViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -760,8 +760,10 @@ 526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnCompareChanges.swift; sourceTree = ""; }; 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethod.swift; sourceTree = ""; }; 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethodModel.swift; sourceTree = ""; }; + 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityHandler.swift; sourceTree = ""; }; 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = ""; }; + 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = ""; }; 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = ""; }; 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = ""; }; @@ -1073,8 +1075,6 @@ D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = ""; }; D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = ""; }; D29DF26B21E6AA0B003B2FB9 /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImageView.h; sourceTree = ""; }; - D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUILoggingHandler.h; sourceTree = ""; }; - D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUILoggingHandler.m; sourceTree = ""; }; D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUISession.h; sourceTree = ""; }; D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISession.m; sourceTree = ""; }; D29DF27F21E7AA50003B2FB9 /* MVMCoreUIDetailViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIDetailViewProtocol.h; sourceTree = ""; }; @@ -2291,8 +2291,7 @@ D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */, D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */, D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */, - D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */, - D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */, + 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */, AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */, D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */, D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */, @@ -2530,7 +2529,6 @@ D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */, D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */, D29DF2CE21E7C104003B2FB9 /* MFLoadingViewController.h in Headers */, - D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */, D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */, D20492A424329A2800A5EED6 /* MVMCoreUIPagingProtocol.h in Headers */, D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */, @@ -2755,6 +2753,7 @@ D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */, D28BA74D248589C800B75CB8 /* TabPageModelProtocol.swift in Sources */, + 608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */, 014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */, 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */, BBAA4F04243D8E3B005AAD5F /* RadioBoxModel.swift in Sources */, @@ -2762,7 +2761,6 @@ D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */, AAA905E124D1759A00D1EFAB /* ListThreeColumnBillHistory.swift in Sources */, C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */, - D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D2ED27EC254B0CE700A1C293 /* UIAlertControllerStyle+Extension.swift in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 9af907e1..59611756 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -231,7 +231,7 @@ public typealias ActionBlock = () -> () documentAttributes: nil) } catch { if let coreErrorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "LabelHTMLParse") { - MVMCoreUILoggingHandler.addError(toLog: coreErrorObject) + MVMCoreUILoggingHandler.shared()?.addError(toLog: coreErrorObject) } } } @@ -1013,17 +1013,13 @@ extension Label { func validateAttribute(range: NSRange, in string: NSAttributedString, type: String = "") -> NSRange? { guard range.location >= 0 && range.location <= string.length else { - if let loggingHandler = MVMCoreLoggingHandler.shared(), loggingHandler.responds(to: #selector(MVMCoreLoggingHandler.addError(toLog:))) { - loggingHandler.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Attribute starting location \(range.lowerBound) is out of bounds for '\(string.string)'. Attribute is discarded.", code: ErrorCode.default.rawValue, domain: ErrorDomainNative, location: "\(#file): \(#function)")!) - } + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Attribute starting location \(range.lowerBound) is out of bounds for '\(string.string)'. Attribute is discarded.", code: ErrorCode.default.rawValue, domain: ErrorDomainNative, location: "\(#file): \(#function)")!) return nil } if type != "image" && range.upperBound > string.length { let newRange = NSRange(location: range.location, length: string.length - range.location) - if let loggingHandler = MVMCoreLoggingHandler.shared(), loggingHandler.responds(to: #selector(MVMCoreLoggingHandler.addError(toLog:))) { - loggingHandler.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Attribute ending location \(range.upperBound) is out of bounds for '\(string)'. Adjusting to \(newRange.upperBound).", code: ErrorCode.default.rawValue, domain: ErrorDomainNative, location: "\(#file): \(#function)")!) - } + MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Attribute ending location \(range.upperBound) is out of bounds for '\(string)'. Adjusting to \(newRange.upperBound).", code: ErrorCode.default.rawValue, domain: ErrorDomainNative, location: "\(#file): \(#function)")!) return newRange } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift index a378b854..baee04f6 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift @@ -89,7 +89,7 @@ open class Video: View { }) case .failed: if let errorObject = item.loadFailedError { - MVMCoreLoggingHandler.addError(toLog: errorObject) + MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject) } default: break diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift index 6083ac5e..ce76d379 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift @@ -75,7 +75,7 @@ open class ModuleMolecule: Container { let _ = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { if let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) { error?.pointee = errorObject - MVMCoreUILoggingHandler.addError(toLog: errorObject) + MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) } return nil } diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift index 7dd4fa26..c3c07b6a 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift @@ -77,7 +77,7 @@ public extension ModelRegistry { return type } catch { if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) { - MVMCoreLoggingHandler.addError(toLog: errorObject) + MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject) } return nil } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index d91e776e..d3d7c3c0 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -115,7 +115,7 @@ import MVMCore }) } catch { if let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: "updateJSON for pageType: \(String(describing: pageType))") { - MVMCoreLoggingHandler.addError(toLog: coreError) + MVMCoreLoggingHandler.shared()?.addError(toLog: coreError) } } } diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift index 9e5c6a6d..325f8927 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift @@ -33,7 +33,7 @@ public extension PageBehaviorHandlerProtocol { behaviors.append(behavior) } catch { if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) { - MVMCoreLoggingHandler.addError(toLog: errorObject) + MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject) } } } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index ec06542c..3aa50030 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -95,7 +95,7 @@ import MVMCore groupValid = try validateGroup(group) } catch { if let err = MVMCoreErrorObject.createErrorObject(for: error, location: "FormValidator"){ - MVMCoreLoggingHandler.addError(toLog: err) + MVMCoreLoggingHandler.shared()?.addError(toLog: err) fatalError(err.description) } } diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index fa2aaf0b..23e40209 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -17,7 +17,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import #pragma mark - OtherHandlers #import -#import #import #import diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index 9ecc2efb..1c7504ee 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -399,7 +399,7 @@ open class NotificationHandler { try await showNotification(for: json, delegateObject: delegateObject) } catch { if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") { - MVMCoreUILoggingHandler.addError(toLog: errorObject) + MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) } } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h deleted file mode 100644 index a4b66ef9..00000000 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// MVMCoreUILoggingHandler.h -// MVMCoreUI -// -// Created by Scott Pfeil on 1/10/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -@import MVMCore.MVMCoreLoggingHandler; - -NS_ASSUME_NONNULL_BEGIN - -@interface MVMCoreUILoggingHandler : MVMCoreLoggingHandler - -// Page State Logging -- (void)defaultLogPageStateForController:(nonnull id )controller; - -// Action Logging -- (void)defaultLogActionForController:(nullable id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; -- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nullable id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; - -@end - -NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m deleted file mode 100644 index 45a13acf..00000000 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// MVMCoreUILoggingHandler.m -// MVMCoreUI -// -// Created by Scott Pfeil on 1/10/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreUILoggingHandler.h" - -@implementation MVMCoreUILoggingHandler - -- (void)defaultLogPageStateForController:(nonnull id )controller { -} - -- (void)defaultLogActionForController:(nullable id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData { -} - -- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nullable id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData { - return nil; -} - -@end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift new file mode 100644 index 00000000..edad1b5d --- /dev/null +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift @@ -0,0 +1,21 @@ +// +// MVMCoreUILoggingHandler.swift +// MVMCoreUI +// +// Created by Nandhini Rajendran on 29/09/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +@objc open class MVMCoreUILoggingHandler: MVMCoreLoggingHandler { + + // Page State Logging + @objc open func defaultLogPageState(forController controller: MVMCoreViewControllerProtocol) { } + + // Action Logging + @objc open func defaultLogAction(forController controller: MVMCoreViewControllerProtocol?, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { } + + @objc open func defaultGetActionTrackDataDictionary(forController controller: MVMCoreViewControllerProtocol?, actionInformation: NSDictionary?, additionalData: NSDictionary?) -> NSDictionary? { + return nil + } +} + diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index d16f15ec..30ee68f0 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -9,8 +9,11 @@ #import "MFFonts.h" #import #import "MVMCoreUIUtility.h" -@import MVMCore.MVMCoreLoggingHandler; +#import +@import MVMCore.Swift; @import MVMCore.MVMCoreErrorConstants; +@import MVMCore.MVMCoreLoadHandler; +@import MVMCore.MVMCoreErrorObject; NSString * const DSBold = @"VerizonNHGeDS-Bold"; NSString * const DSRegular = @"VerizonNHGeDS-Regular"; @@ -108,7 +111,7 @@ NSString * const TXRegular = @"VerizonNHGeTX-Regular"; + (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]; + [[MVMCoreLoggingHandler sharedLoggingHandler]addErrorToLog:errorObject]; } } @end From 72358966bc1cee9fd46df39dd6fe4c299a5c4739 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 21 Dec 2023 12:32:08 -0500 Subject: [PATCH 34/77] Remove unused stub. --- MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift index edad1b5d..e74bc580 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift @@ -13,9 +13,4 @@ // Action Logging @objc open func defaultLogAction(forController controller: MVMCoreViewControllerProtocol?, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { } - - @objc open func defaultGetActionTrackDataDictionary(forController controller: MVMCoreViewControllerProtocol?, actionInformation: NSDictionary?, additionalData: NSDictionary?) -> NSDictionary? { - return nil - } } - From 8306f901bdc095a20c602a87cd66ade936902915 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 21 Dec 2023 22:19:45 -0500 Subject: [PATCH 35/77] Open up progress bar atom for subclassing. --- MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift | 4 ++-- MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift index a68cdc99..c806ce4b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBar.swift @@ -54,7 +54,7 @@ import Foundation // MARK: - Lifecycle //-------------------------------------------------- - public func setupView() { + open func setupView() { clipsToBounds = true translatesAutoresizingMaskIntoConstraints = false @@ -70,7 +70,7 @@ import Foundation // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let progressBarModel = model as? ProgressBarModel else { return } diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift index 439fad3d..c69e73e4 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift @@ -8,8 +8,8 @@ import Foundation -@objcMembers public class ProgressBarModel: MoleculeModelProtocol { - public static var identifier: String = "progressBar" +@objcMembers open class ProgressBarModel: MoleculeModelProtocol { + open class var identifier: String { "progressBar" } public var id: String = UUID().uuidString @Percent public var percent: CGFloat From c2c4e0f1f4cebb8ea1f844e1c4843050f59d2f3b Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Tue, 2 Jan 2024 17:24:42 -0500 Subject: [PATCH 36/77] indexing safety --- MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift | 2 +- MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 6b360120..2ad92343 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -87,7 +87,7 @@ open class Carousel: View { showPeaking(false) // 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, + 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) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift index 5bfd8d0f..04e98287 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift @@ -8,7 +8,6 @@ import UIKit - @objcMembers public class CarouselModel: ParentMoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- @@ -57,14 +56,14 @@ import UIKit guard selectable else { // Use visible item value, else index - if let fieldValue = molecules[index].formFieldValue() { + if let fieldValue = molecules[safe: index]?.formFieldValue() { return fieldValue } return index } // Use selected item value, else index guard let selectedIndex = selectedIndex else { return nil } - guard let fieldValue = molecules[selectedIndex].formFieldValue() else { return selectedIndex } + guard let fieldValue = molecules[safe: selectedIndex]?.formFieldValue() else { return selectedIndex } return fieldValue } From c03e04069abe60053ded75da63cb58134ed4a0b9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Jan 2024 14:04:30 -0600 Subject: [PATCH 37/77] refactored loader Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 10 +- .../Atomic/Atoms/Views/LoadImageView.swift | 6 +- MVMCoreUI/Atomic/Atoms/Views/WebView.swift | 4 +- .../Legacy/Views/MFLoadingSpinner+VDS.swift | 42 ++++++ MVMCoreUI/Legacy/Views/MFLoadingSpinner.h | 11 -- MVMCoreUI/Legacy/Views/MFLoadingSpinner.m | 138 ++---------------- 6 files changed, 68 insertions(+), 143 deletions(-) create mode 100644 MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8619ce46..09c333cb 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -298,8 +298,8 @@ AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; }; AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; }; AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; }; - B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; }; + B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -576,8 +576,8 @@ EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; }; EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; }; EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; }; - EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; }; + EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; }; EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; }; EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; }; @@ -587,6 +587,7 @@ EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */; }; EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */; }; EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */; }; + EAA482CE2B45F2F300978105 /* MFLoadingSpinner+VDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA482CD2B45F2F300978105 /* MFLoadingSpinner+VDS.swift */; }; EAA78020290081320057DFDF /* VDSMoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */; }; EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */; }; EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; }; @@ -890,8 +891,8 @@ AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = ""; }; AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = ""; }; AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; - B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = ""; }; + B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1180,6 +1181,7 @@ EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldEffectProtocol.swift; sourceTree = ""; }; EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideFormFieldEffectModel.swift; sourceTree = ""; }; EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableFormFieldEffectModel.swift; sourceTree = ""; }; + EAA482CD2B45F2F300978105 /* MFLoadingSpinner+VDS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFLoadingSpinner+VDS.swift"; sourceTree = ""; }; EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDSMoleculeViewProtocol.swift; sourceTree = ""; }; EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleCompareModelProtocol.swift; sourceTree = ""; }; EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = ""; }; @@ -1635,6 +1637,7 @@ D20492A324329A2800A5EED6 /* MVMCoreUIPagingProtocol.h */, D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */, D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */, + EAA482CD2B45F2F300978105 /* MFLoadingSpinner+VDS.swift */, D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */, D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */, ); @@ -2689,6 +2692,7 @@ 0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */, AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */, AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */, + EAA482CE2B45F2F300978105 /* MFLoadingSpinner+VDS.swift in Sources */, D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */, D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */, 0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift index 780f8829..e7601015 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift @@ -117,7 +117,7 @@ spinnerHeight = constraint.constant loadingSpinnerHeightConstraint?.constant = 0 loadingSpinnerHeightConstraint?.isActive = true - loadingSpinner.pause() + loadingSpinner.pauseSpinner() } } @@ -326,7 +326,7 @@ guard let self = self, let loadingImageName = self.currentImageName, loadingImageName == imageName else { return } self.isFallbackImage = isFallbackImage - self.loadingSpinner.pause() + self.loadingSpinner.pauseSpinner() let layoutWillChange = self.shouldNotifyDelegateOnUpdate ? self.layoutWillChange(width: self.currentImageWidth, height: self.currentImageHeight, size: image?.size) : false self.addConstraints(width: width, height: height, size: image?.size) self.loadingSpinnerHeightConstraint?.constant = 0 @@ -359,7 +359,7 @@ return } self?.loadingSpinnerHeightConstraint?.constant = 0 - self?.loadingSpinner.pause() + self?.loadingSpinner.pauseSpinner() if flipImage, let cgImage = image.cgImage { self?.imageView.image = UIImage(cgImage: cgImage, scale: image.scale, orientation: UIImage.Orientation.upMirrored) } else { diff --git a/MVMCoreUI/Atomic/Atoms/Views/WebView.swift b/MVMCoreUI/Atomic/Atoms/Views/WebView.swift index d3a91920..8e2923be 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/WebView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WebView.swift @@ -122,7 +122,7 @@ extension WebView : WKUIDelegate { public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // hide loading overLayer.isHidden = true - loadingSpinner.pause() + loadingSpinner.pauseSpinner() //update webview's heigth when webview is ready if !dynamicHeight { @@ -159,7 +159,7 @@ extension WebView : WKUIDelegate { //actually no error handle page show in webview. We can handle the error display view by our self. //or stop loading by default overLayer.isHidden = true - loadingSpinner.pause() + loadingSpinner.pauseSpinner() } } diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift b/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift new file mode 100644 index 00000000..f058699c --- /dev/null +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift @@ -0,0 +1,42 @@ +// +// MFLoadingSpinner+VDS.swift +// MVMCoreUI +// +// Created by Matt Bruce on 1/3/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +extension MFLoadingSpinner { + var loader: Loader? { + subviews.first as? Loader + } + + @objc(setUpCircle:) + open func setUpCircle(strokeColor: UIColor?) { + if let strokeColor { + loader?.surface = strokeColor.isDark() ? .light : .dark + } + } + + @objc open func pauseSpinner() { + loader?.isActive = false + } + + @objc open func resumeSpinner() { + loader?.isActive = true + } + + @objc open func resumeSpinnerAfterDelay() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in + self?.loader?.isActive = true + } + } + + @objc open func pinWidthAndHeight() -> NSDictionary? { + guard let size = loader?.size else { return nil } + return NSLayoutConstraint.constraintPinView(self, heightConstraint: true, heightConstant: CGFloat(size), widthConstraint: true, widthConstant: CGFloat(size)) as NSDictionary? + } +} diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h index 6a44f743..6e4bb55c 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h @@ -12,17 +12,6 @@ -(void)setUpCircle; --(void)setUpCircle:(nullable UIColor *)strokeColor; - -(void)changeColor:(nullable UIColor *)strokeColor; -- (void)pauseSpinner; - -- (void)resumeSpinner; - -// Starts the spinner after a slight delay. -- (void)resumeSpinnerAfterDelay; - -- (nullable NSDictionary *)pinWidthAndHeight; - @end diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m index 7b354dca..07a254d6 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m @@ -7,143 +7,33 @@ // #import "MFLoadingSpinner.h" -#import "UIColor+MFConvenience.h" #import "NSLayoutConstraint+MFConvenience.h" +#import +#import @interface MFLoadingSpinner () - -@property (strong, nonatomic) CAShapeLayer *myCircle; -@property (strong, nonatomic) CADisplayLink *myDisplay; -@property (weak, nonatomic) dispatch_block_t resumeBlock; - -@property (nonatomic) double prevFrame; - -@property (nonatomic) BOOL isFast; - +@property (strong, nonatomic) VDSLoader *loader; @end @implementation MFLoadingSpinner - - - -const float radius = 19; -const float lineWidth = 3.0; -const float slowSpeed = 0.5; -const float fastSpeed = 2.0; -const float startSpeed = 1.0; -const float fastDistance = .45; -const float slowDistance = 0.1; - - --(void)finalize { - [self.myDisplay invalidate]; - self.myDisplay = nil; +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.loader = [[VDSLoader alloc] init]; + [self addSubview: self.loader]; + [NSLayoutConstraint pinViewToSuperview:self.loader useMargins:false]; + } + return self; } -(void)setUpCircle { - [self setUpCircle:[UIColor blackColor]]; -} - --(void)setUpCircle:(UIColor *)strokeColor { - if(self.myCircle) - { - return; - } - - CAShapeLayer *circle = [CAShapeLayer layer]; - circle.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius + lineWidth/2, radius + lineWidth/2) radius:radius startAngle:-M_PI_2 endAngle:3.5*M_PI clockwise:YES].CGPath; - circle.lineWidth = lineWidth; - circle.fillColor = [UIColor clearColor].CGColor; - circle.strokeColor = strokeColor.CGColor; - circle.lineCap = kCALineCapButt; - circle.strokeStart = 0; - circle.strokeEnd = 0+.05; - [self.layer addSublayer:circle]; - self.myCircle = circle; - - self.isFast = YES; - - NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"strokeStart", - [NSNull null], @"strokeEnd", - [NSNull null], @"strokeColor", - nil]; - circle.actions = newActions; - - self.myDisplay = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateSpinner)]; - [self.myDisplay addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - self.myDisplay.frameInterval = 2; - self.prevFrame = CACurrentMediaTime(); + [self setUpCircle:[UIColor blackColor]]; } -(void)changeColor:(UIColor *)strokeColor { - self.myCircle.strokeColor = strokeColor.CGColor; -} - --(void)updateSpinner { - double currentTime = CACurrentMediaTime(); - double renderTime = currentTime - self.prevFrame; - self.prevFrame = currentTime; - - if(self.myCircle.strokeStart > 0.5 && self.myCircle.strokeEnd > 0.5) { - self.myCircle.strokeStart -= 0.5; - self.myCircle.strokeEnd -= 0.5; - } - - float distanceToStart = self.myCircle.strokeEnd - self.myCircle.strokeStart; - if(distanceToStart < slowDistance && !self.isFast) { - self.isFast = YES; - } - else if(distanceToStart > fastDistance && self.isFast) { - self.isFast = NO; - } - self.myCircle.strokeEnd += (self.isFast ? fastSpeed : slowSpeed) * renderTime; - self.myCircle.strokeStart+= startSpeed * renderTime; - -} - -- (void)pauseSpinner { - if (self.resumeBlock) { - // Cancel the current resume block if it hasn't run. dispatch our pause into the same queue incase the resume block is already running. - dispatch_block_cancel(self.resumeBlock); - self.resumeBlock = nil; - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_main_queue(), ^{ - weakSelf.myDisplay.paused = YES; - weakSelf.hidden = YES; - }); - } else { - self.myDisplay.paused = YES; - self.hidden = YES; - } -} - -- (void)resumeSpinner { - self.hidden = NO; - if (!self.myCircle) { - [self setUpCircle]; - return; - } - - self.myDisplay.paused = NO; - self.prevFrame = CACurrentMediaTime(); -} - -- (void)resumeSpinnerAfterDelay { - if (!self.resumeBlock) { - __weak typeof(self) weakSelf = self; - dispatch_block_t resume = dispatch_block_create(0, ^{ - [weakSelf resumeSpinner]; - weakSelf.resumeBlock = nil; - }); - self.resumeBlock = resume; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), resume); - } -} - -- (nullable NSDictionary *)pinWidthAndHeight { - CGFloat diameter = radius*2 + lineWidth; - return [NSLayoutConstraint constraintPinView:self heightConstraint:YES heightConstant:diameter widthConstraint:YES widthConstant:diameter]; + [self setUpCircle: strokeColor]; } @end From eb8ea989ec6e7e28727099ae0a4c27bb906be0ec Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Jan 2024 15:13:39 -0600 Subject: [PATCH 38/77] refactored back in the obj-c interface to interact with swift extension Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/LoadImageView.swift | 6 ++--- MVMCoreUI/Atomic/Atoms/Views/WebView.swift | 4 +-- .../Legacy/Views/MFLoadingSpinner+VDS.swift | 11 ++++---- MVMCoreUI/Legacy/Views/MFLoadingSpinner.h | 11 ++++++++ MVMCoreUI/Legacy/Views/MFLoadingSpinner.m | 27 ++++++++++++++++--- 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift index e7601015..780f8829 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift @@ -117,7 +117,7 @@ spinnerHeight = constraint.constant loadingSpinnerHeightConstraint?.constant = 0 loadingSpinnerHeightConstraint?.isActive = true - loadingSpinner.pauseSpinner() + loadingSpinner.pause() } } @@ -326,7 +326,7 @@ guard let self = self, let loadingImageName = self.currentImageName, loadingImageName == imageName else { return } self.isFallbackImage = isFallbackImage - self.loadingSpinner.pauseSpinner() + self.loadingSpinner.pause() let layoutWillChange = self.shouldNotifyDelegateOnUpdate ? self.layoutWillChange(width: self.currentImageWidth, height: self.currentImageHeight, size: image?.size) : false self.addConstraints(width: width, height: height, size: image?.size) self.loadingSpinnerHeightConstraint?.constant = 0 @@ -359,7 +359,7 @@ return } self?.loadingSpinnerHeightConstraint?.constant = 0 - self?.loadingSpinner.pauseSpinner() + self?.loadingSpinner.pause() if flipImage, let cgImage = image.cgImage { self?.imageView.image = UIImage(cgImage: cgImage, scale: image.scale, orientation: UIImage.Orientation.upMirrored) } else { diff --git a/MVMCoreUI/Atomic/Atoms/Views/WebView.swift b/MVMCoreUI/Atomic/Atoms/Views/WebView.swift index 8e2923be..d3a91920 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/WebView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/WebView.swift @@ -122,7 +122,7 @@ extension WebView : WKUIDelegate { public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // hide loading overLayer.isHidden = true - loadingSpinner.pauseSpinner() + loadingSpinner.pause() //update webview's heigth when webview is ready if !dynamicHeight { @@ -159,7 +159,7 @@ extension WebView : WKUIDelegate { //actually no error handle page show in webview. We can handle the error display view by our self. //or stop loading by default overLayer.isHidden = true - loadingSpinner.pauseSpinner() + loadingSpinner.pause() } } diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift b/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift index f058699c..f58a1395 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner+VDS.swift @@ -14,28 +14,27 @@ extension MFLoadingSpinner { subviews.first as? Loader } - @objc(setUpCircle:) - open func setUpCircle(strokeColor: UIColor?) { + @objc open func setSurface(_ strokeColor: UIColor?) { if let strokeColor { loader?.surface = strokeColor.isDark() ? .light : .dark } } - @objc open func pauseSpinner() { + @objc open func pause() { loader?.isActive = false } - @objc open func resumeSpinner() { + @objc open func resume() { loader?.isActive = true } - @objc open func resumeSpinnerAfterDelay() { + @objc open func resumeAfterDelay() { DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in self?.loader?.isActive = true } } - @objc open func pinWidthAndHeight() -> NSDictionary? { + @objc open func pin() -> NSDictionary? { guard let size = loader?.size else { return nil } return NSLayoutConstraint.constraintPinView(self, heightConstraint: true, heightConstant: CGFloat(size), widthConstraint: true, widthConstant: CGFloat(size)) as NSDictionary? } diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h index 6e4bb55c..6a44f743 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.h @@ -12,6 +12,17 @@ -(void)setUpCircle; +-(void)setUpCircle:(nullable UIColor *)strokeColor; + -(void)changeColor:(nullable UIColor *)strokeColor; +- (void)pauseSpinner; + +- (void)resumeSpinner; + +// Starts the spinner after a slight delay. +- (void)resumeSpinnerAfterDelay; + +- (nullable NSDictionary *)pinWidthAndHeight; + @end diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m index 07a254d6..97a88518 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m @@ -7,7 +7,6 @@ // #import "MFLoadingSpinner.h" -#import "NSLayoutConstraint+MFConvenience.h" #import #import @@ -29,11 +28,31 @@ } -(void)setUpCircle { - [self setUpCircle:[UIColor blackColor]]; + [self setSurface: UIColor.blackColor]; } --(void)changeColor:(UIColor *)strokeColor { - [self setUpCircle: strokeColor]; +-(void)setUpCircle:(nullable UIColor *)strokeColor { + [self setSurface: strokeColor]; } +-(void)changeColor:(nullable UIColor *)strokeColor { + [self setSurface: strokeColor]; +} + +- (void)pauseSpinner { + [self pause]; +} + +- (void)resumeSpinner { + [self resume]; +} + +// Starts the spinner after a slight delay. +- (void)resumeSpinnerAfterDelay { + [self resumeAfterDelay]; +} + +- (nullable NSDictionary *)pinWidthAndHeight { + return [self pin]; +} @end From 71a10f1055c694d06c722f6186e21c0b7c1a79bf Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Jan 2024 11:19:18 -0600 Subject: [PATCH 39/77] added buttonGroup Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++-- .../Atomic/Atoms/Buttons/ButtonGroup.swift | 68 +++++++++++++++++ .../Atoms/Buttons/ButtonGroupModel.swift | 73 +++++++++++++++++++ .../Atomic/Extensions/VDS-Enums+Codable.swift | 4 +- 4 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e8c2d064..569b13cb 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -171,7 +171,6 @@ 608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; }; 7199C8162A4F3A64001568B7 /* AccessibilityHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */; }; 71BE969E2AD96BE6000B5DB7 /* RotorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */; }; - 608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; }; 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */; }; 8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */; }; 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */; }; @@ -300,8 +299,8 @@ AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; }; AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; }; AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; }; - B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; }; + B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -574,10 +573,12 @@ EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; }; EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; }; EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; }; + EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B942B504A43000139B4 /* ButtonGroup.swift */; }; + EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; }; EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; }; EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; }; - EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; }; + EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; }; EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; }; EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; }; @@ -763,7 +764,6 @@ 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityHandler.swift; sourceTree = ""; }; 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = ""; }; - 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = ""; }; 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = ""; }; 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = ""; }; @@ -892,8 +892,8 @@ AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = ""; }; AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = ""; }; AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; - B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = ""; }; + B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1167,6 +1167,8 @@ EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = ""; }; EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = ""; }; EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = ""; }; + EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; + EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = ""; }; EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = ""; }; EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = ""; }; EA985C3D2970938F00F2FF2E /* Tilelet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tilelet.swift; sourceTree = ""; }; @@ -2198,6 +2200,8 @@ DBC4391A224421A0001AB423 /* CaretLink.swift */, D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */, D2E2A99E23E07F8A000B42E6 /* PillButton.swift */, + EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */, + EA6E8B942B504A43000139B4 /* ButtonGroup.swift */, ); path = Buttons; sourceTree = ""; @@ -2663,6 +2667,7 @@ BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */, 01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */, 0AE277EC25D2EE310048A38D /* MultiItemDropdownEntryFieldModel.swift in Sources */, + EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */, 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, 3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */, AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */, @@ -2940,6 +2945,7 @@ D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */, + EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, 526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */, B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift new file mode 100644 index 00000000..8fe15acb --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift @@ -0,0 +1,68 @@ +// +// ButtonGroup.swift +// MVMCoreUI +// +// Created by Matt Bruce on 1/11/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import UIKit +import VDS + +@objcMembers open class ButtonGroup: VDS.ButtonGroup, VDSMoleculeViewProtocol { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + open var viewModel: ButtonGroupModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? ButtonGroupModel, + let buttonModel = model.buttons.first + else { return 0 } + + return PillButton.estimatedHeight(with: buttonModel, delegateObject) + } + + public func viewModelDidUpdate() { + var buttonBases = [ButtonBase]() + viewModel.buttons.forEach { buttonModel in + if let buttonBaseType = try? ModelRegistry.getHandler(buttonModel) as? MoleculeViewProtocol.Type, + let button = buttonBaseType.init(model: buttonModel, delegateObject, additionalData) as? VDS.ButtonBase { + buttonBases.append(button) + } + } + surface = viewModel.surface + alignment = viewModel.alignment + rowQuantityPhone = viewModel.rowQuantityPhone + rowQuantityTablet = viewModel.rowQuantityTablet + if let childWidthValue = viewModel.childWidthValue { + childWidth = .value(childWidthValue) + } else if let childWidthPercentage = viewModel.childWidthPercentage { + childWidth = .percentage(childWidthPercentage) + } + buttons = buttonBases + } + + //-------------------------------------------------- + // MARK: - MVMCoreUIViewConstrainingProtocol + //-------------------------------------------------- + + open func horizontalAlignment() -> UIStackView.Alignment { + return .center + } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + public func updateView(_ size: CGFloat) { + setNeedsUpdate() + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift new file mode 100644 index 00000000..060c11af --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift @@ -0,0 +1,73 @@ +// +// ButtonGroupModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 1/11/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +public class ButtonGroupModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "buttonGroup" + public var id: String = UUID().uuidString + public var backgroundColor: Color? + + public var buttons: [ButtonModelProtocol & MoleculeModelProtocol] + public var alignment: VDS.ButtonGroup.Alignment = .center + public var rowQuantityPhone: Int = 0 + public var rowQuantityTablet: Int = 0 + public var childWidthValue: CGFloat? + public var childWidthPercentage: CGFloat? + public var surface: VDS.Surface = .light + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case id + case moleculeName + case backgroundColor + case buttons + case alignment + case rowQuantityPhone + case rowQuantityTablet + case childWidthValue + case childWidthPercentage + case surface + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + surface = try typeContainer.decodeIfPresent(Surface.self, forKey: .surface) ?? .light + buttons = try typeContainer.decodeModels(codingKey: .buttons) + alignment = try typeContainer.decodeIfPresent(VDS.ButtonGroup.Alignment.self, forKey: .alignment) ?? .center + rowQuantityPhone = try typeContainer.decodeIfPresent(Int.self, forKey: .rowQuantityPhone) ?? 0 + rowQuantityTablet = try typeContainer.decodeIfPresent(Int.self, forKey: .rowQuantityTablet) ?? 0 + childWidthValue = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .childWidthValue) ?? 0.0 + childWidthPercentage = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .childWidthPercentage) ?? 0.0 + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeModels(buttons, forKey: .buttons) + try container.encode(alignment, forKey: .alignment) + try container.encode(rowQuantityPhone, forKey: .rowQuantityPhone) + try container.encode(rowQuantityTablet, forKey: .rowQuantityTablet) + try container.encodeIfPresent(childWidthValue, forKey: .childWidthValue) + try container.encodeIfPresent(childWidthPercentage, forKey: .childWidthPercentage) + } +} diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 1d24a0bd..a9666cba 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -11,6 +11,7 @@ import VDS extension Surface: Codable {} extension Badge.FillColor: Codable {} +extension VDS.ButtonGroup.Alignment: Codable {} extension Icon.Name: Codable {} extension Icon.Size: Codable {} extension TileContainer.BackgroundColor: Codable {} @@ -23,4 +24,5 @@ extension Use: Codable {} extension VDS.Button.Size: RawRepresentableCodable { public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } public static var defaultValue: VDS.Button.Size? { nil } -} \ No newline at end of file +} + From 8ba25bb6611bdd2646d3bef39360f8acb803d908 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Jan 2024 11:31:58 -0600 Subject: [PATCH 40/77] registered ButtonGroup Atom Signed-off-by: Matt Bruce --- MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index b339cf94..8b3d5529 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -36,7 +36,8 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: ExternalLink.self, for: ExternalLinkModel.self) ModelRegistry.register(handler: Link.self, for: LinkModel.self) ModelRegistry.register(handler: CaretLink.self, for: CaretLinkModel.self) - + ModelRegistry.register(handler: ButtonGroup.self, for: ButtonGroupModel.self) + // MARK:- Entry Field ModelRegistry.register(handler: TextEntryField.self, for: TextEntryFieldModel.self) ModelRegistry.register(handler: MdnEntryField.self, for: MdnEntryFieldModel.self) From ea3ee2addab585d0682b2d906c0a68df147c98a7 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Jan 2024 11:42:53 -0600 Subject: [PATCH 41/77] added comments Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift index 060c11af..0ee3b68e 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift @@ -18,6 +18,9 @@ public class ButtonGroupModel: MoleculeModelProtocol { public var id: String = UUID().uuidString public var backgroundColor: Color? + //-------------------------------------------------- + // MARK: - VDS Properties + //-------------------------------------------------- public var buttons: [ButtonModelProtocol & MoleculeModelProtocol] public var alignment: VDS.ButtonGroup.Alignment = .center public var rowQuantityPhone: Int = 0 @@ -55,8 +58,8 @@ public class ButtonGroupModel: MoleculeModelProtocol { alignment = try typeContainer.decodeIfPresent(VDS.ButtonGroup.Alignment.self, forKey: .alignment) ?? .center rowQuantityPhone = try typeContainer.decodeIfPresent(Int.self, forKey: .rowQuantityPhone) ?? 0 rowQuantityTablet = try typeContainer.decodeIfPresent(Int.self, forKey: .rowQuantityTablet) ?? 0 - childWidthValue = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .childWidthValue) ?? 0.0 - childWidthPercentage = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .childWidthPercentage) ?? 0.0 + childWidthValue = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .childWidthValue) + childWidthPercentage = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .childWidthPercentage) } public func encode(to encoder: Encoder) throws { From 1f74c88ce6602699e553a25b4fa7fb402e8c9e28 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Jan 2024 12:07:42 -0600 Subject: [PATCH 42/77] added enabled Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift | 1 + MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift index 8fe15acb..53c0a476 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift @@ -40,6 +40,7 @@ import VDS } } surface = viewModel.surface + isEnabled = viewModel.enabled alignment = viewModel.alignment rowQuantityPhone = viewModel.rowQuantityPhone rowQuantityTablet = viewModel.rowQuantityTablet diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift index 0ee3b68e..4921d0f0 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift @@ -28,7 +28,7 @@ public class ButtonGroupModel: MoleculeModelProtocol { public var childWidthValue: CGFloat? public var childWidthPercentage: CGFloat? public var surface: VDS.Surface = .light - + public var enabled: Bool = true //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -44,6 +44,7 @@ public class ButtonGroupModel: MoleculeModelProtocol { case childWidthValue case childWidthPercentage case surface + case enabled } //-------------------------------------------------- @@ -54,6 +55,7 @@ public class ButtonGroupModel: MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString surface = try typeContainer.decodeIfPresent(Surface.self, forKey: .surface) ?? .light + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true buttons = try typeContainer.decodeModels(codingKey: .buttons) alignment = try typeContainer.decodeIfPresent(VDS.ButtonGroup.Alignment.self, forKey: .alignment) ?? .center rowQuantityPhone = try typeContainer.decodeIfPresent(Int.self, forKey: .rowQuantityPhone) ?? 0 @@ -66,6 +68,8 @@ public class ButtonGroupModel: MoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(surface, forKey: .surface) + try container.encode(enabled, forKey: .enabled) try container.encodeModels(buttons, forKey: .buttons) try container.encode(alignment, forKey: .alignment) try container.encode(rowQuantityPhone, forKey: .rowQuantityPhone) From 8a62065ade07030bc19dd092818ec309360a99a2 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 11 Jan 2024 18:17:06 -0500 Subject: [PATCH 43/77] open encoder --- MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift index c69e73e4..5e6a42c1 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ProgressBarModel.swift @@ -46,7 +46,7 @@ import Foundation thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) From d5a9710b6c1e5848e78bf464a30512b42608ae9d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 18 Jan 2024 14:47:13 -0600 Subject: [PATCH 44/77] added other initiliazers Signed-off-by: Matt Bruce --- MVMCoreUI/Legacy/Views/MFLoadingSpinner.m | 26 ++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m index 07a254d6..4cb309c2 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m @@ -17,17 +17,37 @@ @implementation MFLoadingSpinner +- (instancetype)init { + self = [super init]; + if (self) { + [self setup]; + } + return self; +} + - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.loader = [[VDSLoader alloc] init]; - [self addSubview: self.loader]; - [NSLayoutConstraint pinViewToSuperview:self.loader useMargins:false]; + [self setup]; } return self; } +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder: coder]; + if (self) { + [self setup]; + } + return self; +} + +-(void) setup { + self.loader = [[VDSLoader alloc] init]; + [self addSubview: self.loader]; + [NSLayoutConstraint pinViewToSuperview:self.loader useMargins:false]; +} + -(void)setUpCircle { [self setUpCircle:[UIColor blackColor]]; } From 2f80ee891d510732496908929c947d481f85c3a9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 18 Jan 2024 15:25:50 -0600 Subject: [PATCH 45/77] added text to use string file Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift index 713e18ea..f6627dd3 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift @@ -26,7 +26,7 @@ open class TooltipModel: MoleculeModelProtocol { public var fillColor: VDS.Tooltip.FillColor = .primary - public var closeButtonText: String = "Close" + public var closeButtonText: String = { MVMCoreUIUtility.hardcodedString(withKey: "AccCloseButton") ?? "Close" }() public var title: String? From 1965920710b4bdc9e8d0f52e45fc064b0fa468a3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 19 Jan 2024 14:50:30 -0600 Subject: [PATCH 46/77] fixed delegate bug Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/Tabs.swift | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 178e9c3d..dae0e818 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -25,7 +25,21 @@ import VDS open var additionalData: [AnyHashable : Any]? //delegate - weak public var delegate: TabsDelegate? + weak public var delegate: TabsDelegate? { + didSet { + if let delegate { + onTabDidSelect = { [weak self] index in + guard let self else { return } + delegate.didSelectItem(.init(row: index, section: 0), tabs: self) + } + + onTabShouldSelect = { [weak self] index in + guard let self else { return true } + return delegate.shouldSelectItem(.init(row: index, section: 0), tabs: self) + } + } + } + } //------------------------------------------------- // MARK: - Layout Views @@ -55,17 +69,5 @@ import VDS selectedIndex = viewModel.selectedIndex surface = viewModel.style ?? .light tabModels = viewModel.tabs.compactMap { TabModel(text: $0.label.text) } - - if let delegate { - onTabDidSelect = { [weak self] index in - guard let self else { return } - delegate.didSelectItem(.init(row: index, section: 0), tabs: self) - } - - onTabShouldSelect = { [weak self] index in - guard let self else { return true } - return delegate.shouldSelectItem(.init(row: index, section: 0), tabs: self) - } - } } } From 91eb0a5636192988ea3116668257d0b4e71f1038 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 19 Jan 2024 16:02:21 -0600 Subject: [PATCH 47/77] added fillContainer and backgroundColor Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 85e487ae..30585d46 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -8,6 +8,7 @@ import Foundation import MVMCore +import VDSColorTokens open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, TabsDelegate, MVMCorePresentationDelegateProtocol, SubNavSwipeNavigationProtocol { @@ -29,6 +30,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, private var tabsModel: TabsModel public lazy var tabs: Tabs = { let tabs = Tabs(model: tabsModel, delegateObjectIVar, nil) + tabs.fillContainer = true tabs.delegate = self return tabs }() @@ -109,6 +111,9 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, open override func pageShown() { // Currently not calling super until we can decouple page shown logics for managers. hideNavigationBarLine(true) + + //set the tabs backgroundColor + tabs.backgroundColor = (viewController as? PageProtocol)?.pageModel?.navigationBar?.backgroundColor?.uiColor ?? VDSColor.backgroundPrimaryLight } open override func viewWillDisappear(_ animated: Bool) { From 0351a0620d2e786ff30b9bab2c691b9d5c2c08b4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 19 Jan 2024 16:44:36 -0600 Subject: [PATCH 48/77] put backgroundcolor in init for tabs Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 30585d46..c5da68c7 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -30,6 +30,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, private var tabsModel: TabsModel public lazy var tabs: Tabs = { let tabs = Tabs(model: tabsModel, delegateObjectIVar, nil) + tabs.backgroundColor = (viewController as? PageProtocol)?.pageModel?.navigationBar?.backgroundColor?.uiColor ?? VDSColor.backgroundPrimaryLight tabs.fillContainer = true tabs.delegate = self return tabs @@ -111,9 +112,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, open override func pageShown() { // Currently not calling super until we can decouple page shown logics for managers. hideNavigationBarLine(true) - - //set the tabs backgroundColor - tabs.backgroundColor = (viewController as? PageProtocol)?.pageModel?.navigationBar?.backgroundColor?.uiColor ?? VDSColor.backgroundPrimaryLight } open override func viewWillDisappear(_ animated: Bool) { From eb5d3593228cc556ee48af6bdf84ae9c23c1c661 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Mon, 22 Jan 2024 23:29:47 +0530 Subject: [PATCH 49/77] Addressed review comments Added accessibilityHint to AccessibilityModelProtocol --- .../ModelProtocols/AccessibilityModelProtocol.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift index 809334d8..b233c71d 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/AccessibilityModelProtocol.swift @@ -15,6 +15,7 @@ public protocol AccessibilityModelProtocol { var accessibilityTraits: UIAccessibilityTraits? { get set } var accessibilityText: String? { get set } var accessibilityValue: String? { get set } + var accessibilityHint: String? { get set } } public extension AccessibilityModelProtocol { @@ -38,4 +39,9 @@ public extension AccessibilityModelProtocol { get { nil } set { } } + + var accessibilityHint: String? { + get { nil } + set {} + } } From d1ee6e7f3ae2323ada0f1d630c75f51397c6e40c Mon Sep 17 00:00:00 2001 From: Keerthy Date: Wed, 24 Jan 2024 16:18:35 +0530 Subject: [PATCH 50/77] Addressed code review comments --- .../TextFields/TextViewEntryField.swift | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift index e92e7127..46e4e233 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift @@ -161,7 +161,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele bottomConstraint?.isActive = true heightConstraint = textView.heightAnchor.constraint(equalToConstant: 0) - accessibilityElements = [titleLabel, textView, feedbackLabel] + accessibilityElements = [textView] } open override func updateView(_ size: CGFloat) { @@ -281,11 +281,25 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele if model.hideBorders { adjustMarginConstraints(constant: 0) } - setAccessibilityString(model.title) + updateAccessibility(model: model) } - override func setAccessibilityString(_ accessibilityString: String?) { - let accessibilityString = accessibilityString ?? "" - textView.accessibilityLabel = "\(String(describing: accessibilityString)) \(self.textView.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")" + func updateAccessibility(model: TextViewEntryFieldModel) { + + var message = "" + + if let titleText = model.accessibilityText ?? model.title { + message += "\(titleText) \( model.enabled ? String(format: (MVMCoreUIUtility.hardcodedString(withKey: "textfield_optional")) ?? "") : "" ) \(self.textView.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")" + } + + if let feedback = model.feedback { + message += ", " + feedback + } + + if let errorMessage = errorLabel.text { + message += ", " + errorMessage + } + + textView.accessibilityLabel = message } } From 648bfdc76bd6d7f21e16db160b0896abf94f560c Mon Sep 17 00:00:00 2001 From: Keerthy Date: Wed, 24 Jan 2024 21:41:46 +0530 Subject: [PATCH 51/77] Missed file --- MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings index 7eb53fa7..24a6d8db 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings @@ -23,6 +23,7 @@ // Textfield "textfield_today_string" = "Hoy"; "textfield_error_message" = "%@.\n El mensaje de error.\n %@"; +"textView_error_message" = "%@.\n El mensaje de error.\n %@"; "textfield_picker_item" = " artículo de selector"; "textfield_regular" = " regular"; "textfield_disabled_state" = "inactivo"; From 75729fd4141d7357106d46ced4e75c62df577e32 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Wed, 24 Jan 2024 23:33:57 +0530 Subject: [PATCH 52/77] defect: CXTDT-458975 Removing button text in the accessibility label. --- MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index b42f7d92..52a718df 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -63,7 +63,7 @@ // MARK: Switch / Toggle "mfswitch_buttonlabel" = "Switch Button"; -"Toggle_buttonlabel" = "Toggle Button"; +"Toggle_buttonlabel" = "Toggle"; "AccOn" = "on"; "AccOff" = "off"; "AccToggleHint" = "double tap to toggle"; From fef1e0f9ffbb1928656f5aa2466478822fdccf82 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Jan 2024 13:35:59 -0600 Subject: [PATCH 53/77] CXTDT-511155 - VDS_Cancel and Delete CTAs are missing in Edit All Calls and Edit Missed Calls screen Signed-off-by: Matt Bruce --- MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index a6d6c7b5..bd369276 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -237,6 +237,10 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController, Rotor // if footer already exists, use the same y location to avoid strange moving animation let y = tableView.tableFooterView?.frame.minY ?? 0.0 + //force footerView to redraw + footerView.setNeedsLayout() + footerView.layoutIfNeeded() + // This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout. MVMCoreUIUtility.sizeView(toFit: footerView) let tableFooterView = UIView(frame: CGRect(x: 0, y: y, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height)) From cdc8b7310d8eddaa49b12a950058c9eb4ad036cd Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 12:57:32 -0600 Subject: [PATCH 54/77] added ParewntMoleculeModelProtocol Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/TwoLinkViewModel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift index c9ae177b..893d2753 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkViewModel.swift @@ -8,7 +8,7 @@ import Foundation -public class TwoLinkViewModel: MoleculeModelProtocol { +public class TwoLinkViewModel: ParentMoleculeModelProtocol { public static var identifier: String = "twoLinkView" public var id: String = UUID().uuidString @@ -16,6 +16,8 @@ public class TwoLinkViewModel: MoleculeModelProtocol { public var rightLink: LinkModel? public var leftLink: LinkModel? + public var children: [MoleculeModelProtocol] { [rightLink, leftLink].compactMap{ $0 } } + private enum CodingKeys: String, CodingKey { case id case moleculeName From f99d4e3c4df650af3a17f3a7b3dfef6b2f79f6c3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 12:58:07 -0600 Subject: [PATCH 55/77] added fillContainer: Bool to deal with updating if the buttonGroup fills or not Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/TwoButtonViewModel.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index a7b4055c..f43f2265 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -19,10 +19,9 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { public var backgroundColor: Color? public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? + public var fillContainer: Bool = false - public var children: [MoleculeModelProtocol] { - return [primaryButton, secondaryButton].compactMap { $0 } - } + public var children: [MoleculeModelProtocol] { [primaryButton, secondaryButton].compactMap { $0 } } //-------------------------------------------------- // MARK: - Keys From 1932fd72318a4280fd443f485cc1c333ee1afaad Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 12:58:23 -0600 Subject: [PATCH 56/77] fixed bug for removing old references in array Signed-off-by: Matt Bruce --- .../Molecules/HorizontalCombinationViews/TwoLinkView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift index cd15066e..330563bd 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift @@ -103,6 +103,8 @@ import VDS } public func viewModelDidUpdate() { + buttons.removeAll() + if let model = viewModel.leftLink { leftLink.set(with: model, delegateObject, additionalData) buttons.append(leftLink) From d81daf1df30a2dbc39c08232baf8d4071a3ec57f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 12:58:55 -0600 Subject: [PATCH 57/77] not resetting if the current count is correct Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/TwoButtonView.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index debd2c8d..58ac0f6e 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -34,7 +34,6 @@ import VDS buttonGroup.alignment = .center buttonGroup.rowQuantityPhone = 2 buttonGroup.rowQuantityTablet = 2 - buttonGroup.childWidth = .percentage(50) } //-------------------------------------------------- @@ -69,8 +68,12 @@ import VDS primaryButton.set(with: primaryModel, delegateObject, additionalData) buttons.append(primaryButton) } + + buttonGroup.childWidth = viewModel.fillContainer ? .percentage(100) : nil - buttonGroup.buttons = buttons + if buttons.count != buttonGroup.buttons.count { + buttonGroup.buttons = buttons + } } //-------------------------------------------------- @@ -84,6 +87,7 @@ import VDS //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- + public func updateView(_ size: CGFloat) { setNeedsUpdate() } From 38907c7ac1781dec552322c1a72f23539fb0a53c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 12:59:25 -0600 Subject: [PATCH 58/77] updating the model to set the TwoButtonModel to fillContainer if needed Signed-off-by: Matt Bruce --- .../Atomic/Molecules/HeadersAndFooters/FooterModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift index 93e296f2..853af399 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/FooterModel.swift @@ -29,8 +29,8 @@ if let _ = molecule as? ButtonModel { horizontalAlignment = .fill - } else if let model = molecule as? TwoButtonViewModel, - model.primaryButton == nil || model.secondaryButton == nil { + } else if let model = molecule as? TwoButtonViewModel { + model.fillContainer = true horizontalAlignment = .fill } } From 315a96470b08488aaabe6539ec829cabaf10f2fb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 13:16:07 -0600 Subject: [PATCH 59/77] added ParentMoleculeModelProtocol Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift index 4921d0f0..505e112d 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroupModel.swift @@ -9,7 +9,8 @@ import Foundation import VDS -public class ButtonGroupModel: MoleculeModelProtocol { +public class ButtonGroupModel: ParentMoleculeModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -17,7 +18,8 @@ public class ButtonGroupModel: MoleculeModelProtocol { public static var identifier: String = "buttonGroup" public var id: String = UUID().uuidString public var backgroundColor: Color? - + public var children: [MoleculeModelProtocol] { buttons } + //-------------------------------------------------- // MARK: - VDS Properties //-------------------------------------------------- From fbcf881535f52485df119a37bbc0351694f87f2b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 13:16:37 -0600 Subject: [PATCH 60/77] added nameForReuse check refactored buttons to either create or set Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Buttons/ButtonGroup.swift | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift index 53c0a476..9e33ac7a 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift @@ -18,6 +18,7 @@ import VDS open var viewModel: ButtonGroupModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? + open var previousModel: ButtonGroupModel? //-------------------------------------------------- // MARK: - MoleculeViewProtocol @@ -31,25 +32,45 @@ import VDS return PillButton.estimatedHeight(with: buttonModel, delegateObject) } - public func viewModelDidUpdate() { - var buttonBases = [ButtonBase]() - viewModel.buttons.forEach { buttonModel in - if let buttonBaseType = try? ModelRegistry.getHandler(buttonModel) as? MoleculeViewProtocol.Type, - let button = buttonBaseType.init(model: buttonModel, delegateObject, additionalData) as? VDS.ButtonBase { - buttonBases.append(button) - } - } + public func viewModelDidUpdate() { surface = viewModel.surface isEnabled = viewModel.enabled alignment = viewModel.alignment rowQuantityPhone = viewModel.rowQuantityPhone rowQuantityTablet = viewModel.rowQuantityTablet + if let childWidthValue = viewModel.childWidthValue { childWidth = .value(childWidthValue) } else if let childWidthPercentage = viewModel.childWidthPercentage { childWidth = .percentage(childWidthPercentage) } - buttons = buttonBases + + // create / set the moleculeViews + if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: viewModel, delegateObject) { + var buttonBases = [ButtonBase]() + viewModel.buttons.forEach { buttonModel in + do { + let buttonBaseType = try ModelRegistry.getHandler(buttonModel) as! MoleculeViewProtocol.Type + let button = buttonBaseType.init(model: buttonModel, delegateObject, additionalData) as! VDS.ButtonBase + buttonBases.append(button) + } catch { + if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) { + MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject) + } + } + } + buttons = buttonBases + + } else { + // only set the molecule views + for (index, buttonBase) in buttons.enumerated() { + if let button = buttonBase as? MoleculeViewProtocol, index < viewModel.buttons.count { + button.set(with: viewModel.buttons[index], delegateObject, additionalData) + } + } + // force redraw + setNeedsUpdate() + } } //-------------------------------------------------- @@ -66,4 +87,22 @@ import VDS public func updateView(_ size: CGFloat) { setNeedsUpdate() } + + public static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { + // This will aggregate names of molecules to make an id. + guard let model = model as? ButtonGroupModel else { + return "buttonGroup<>" + } + var name = "buttonGroup<" + for case let item in model.buttons { + if let moleculeClass = ModelRegistry.getMoleculeClass(item), + let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) { + name.append(nameForReuse + ",") + } else { + name.append(item.moleculeName + ",") + } + } + name.append(">") + return name + } } From 59175c45fc26bc55e41064b15b89f6bd54da1caf Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 14:16:27 -0600 Subject: [PATCH 61/77] added previousModel Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift index 9e33ac7a..ba9f8b56 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift @@ -47,6 +47,7 @@ import VDS // create / set the moleculeViews if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: viewModel, delegateObject) { + previousModel = viewModel var buttonBases = [ButtonBase]() viewModel.buttons.forEach { buttonModel in do { From 9db98a20784ea248a6fd18e333427837dd70aa2c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 15:15:19 -0600 Subject: [PATCH 62/77] added else Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift index ba9f8b56..f864e72f 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift @@ -43,6 +43,8 @@ import VDS childWidth = .value(childWidthValue) } else if let childWidthPercentage = viewModel.childWidthPercentage { childWidth = .percentage(childWidthPercentage) + } else { + childWidth = nil } // create / set the moleculeViews From 3f7fd100f9d26581902012eaff89970f557f3864 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 15:20:18 -0600 Subject: [PATCH 63/77] percentage doesn't matter for Links, only matters for pillbuttons Signed-off-by: Matt Bruce --- .../Molecules/HorizontalCombinationViews/TwoLinkView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift index 330563bd..25cd07ac 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift @@ -35,7 +35,6 @@ import VDS buttonGroup.alignment = .center buttonGroup.rowQuantityPhone = 2 buttonGroup.rowQuantityTablet = 2 - buttonGroup.childWidth = .percentage(50) } //-------------------------------------------------- From 9dc77bd1ed11c35ae2e8d3c14eb0da33c35cc79b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 15:21:47 -0600 Subject: [PATCH 64/77] updated reset Signed-off-by: Matt Bruce --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 4 ---- .../Molecules/HorizontalCombinationViews/TwoLinkView.swift | 2 -- 2 files changed, 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 58ac0f6e..4785cfb9 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -42,10 +42,6 @@ import VDS open override func reset() { super.reset() - primaryButton.reset() - secondaryButton.reset() - primaryButton.use = .primary - secondaryButton.use = .secondary buttonGroup.reset() } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift index 25cd07ac..32c546f9 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift @@ -42,8 +42,6 @@ import VDS //-------------------------------------------------- open override func reset() { super.reset() - leftLink.reset() - rightLink.reset() buttonGroup.reset() } From a81ff55e6ecf6a10214143a18a3e7efcbcdca308 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 15:25:34 -0600 Subject: [PATCH 65/77] updated to not return hardcoded value Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift index 04128e90..9f367691 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift @@ -29,7 +29,10 @@ open class LoadingSpinner: VDS.Loader, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 40.0 } + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? LoadingSpinnerModel else return { 0 } + return model.diameter + } open func updateView(_ size: CGFloat) { } From 8201b8fad4974c8d1ce64303a8192b053b78ed09 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 15:27:52 -0600 Subject: [PATCH 66/77] fixed bug Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift index 9f367691..5b1fbe73 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadingSpinner.swift @@ -30,7 +30,7 @@ open class LoadingSpinner: VDS.Loader, VDSMoleculeViewProtocol { // MARK: - MVMCoreViewProtocol //-------------------------------------------------- open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - guard let model = model as? LoadingSpinnerModel else return { 0 } + guard let model = model as? LoadingSpinnerModel else { return 0 } return model.diameter } From ce66b2466ec0debb56c832f6a6037b83028bb561 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 29 Jan 2024 15:28:02 -0600 Subject: [PATCH 67/77] check to ensure this hasn't been created. Signed-off-by: Matt Bruce --- MVMCoreUI/Legacy/Views/MFLoadingSpinner.m | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m index 388416e0..11b11d79 100644 --- a/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m +++ b/MVMCoreUI/Legacy/Views/MFLoadingSpinner.m @@ -42,6 +42,7 @@ } -(void) setup { + if (self.loader) { return; } self.loader = [[VDSLoader alloc] init]; [self addSubview: self.loader]; [NSLayoutConstraint pinViewToSuperview:self.loader useMargins:false]; From 7469a5249f9a5c224e3028394de91c3b1283bd55 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jan 2024 11:31:06 -0600 Subject: [PATCH 68/77] added fillContainer to model/view Signed-off-by: Matt Bruce --- .../Molecules/HorizontalCombinationViews/Tabs.swift | 1 + .../Molecules/HorizontalCombinationViews/TabsModel.swift | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index dae0e818..e070b8e6 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -68,6 +68,7 @@ import VDS size = viewModel.size selectedIndex = viewModel.selectedIndex surface = viewModel.style ?? .light + fillContainer = viewModel.fillContainer tabModels = viewModel.tabs.compactMap { TabModel(text: $0.label.text) } } } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 648357b3..24933f45 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -21,6 +21,7 @@ open class TabsModel: MoleculeModelProtocol { open var orientation: Tabs.Orientation = .horizontal open var indicatorPosition: Tabs.IndicatorPosition = .bottom open var overflow: Tabs.Overflow = .scroll + open var fillContainer: Bool = false open var size: Tabs.Size = .medium public var backgroundColor: Color? @@ -35,6 +36,7 @@ open class TabsModel: MoleculeModelProtocol { case selectedIndex case orientation case indicatorPosition + case fillContainer case overflow case size case style @@ -49,6 +51,11 @@ open class TabsModel: MoleculeModelProtocol { id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs) style = try typeContainer.decodeIfPresent(Surface.self, forKey: .style) + + if let fillContainer = try typeContainer.decodeIfPresent(Bool.self, forKey: .fillContainer) { + self.fillContainer = fillContainer + } + if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { selectedIndex = index } @@ -76,6 +83,7 @@ open class TabsModel: MoleculeModelProtocol { try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) try container.encode(selectedIndex, forKey: .selectedIndex) + try container.encode(fillContainer, forKey: .fillContainer) try container.encodeIfPresent(style, forKey: .style) try container.encode(orientation, forKey: .orientation) try container.encode(overflow, forKey: .overflow) From d56f34258dd7006feb851f56bc696f778134cc52 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jan 2024 11:31:18 -0600 Subject: [PATCH 69/77] added var to determine fillContainer Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index c5da68c7..6a959440 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -11,7 +11,9 @@ import MVMCore import VDSColorTokens open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, TabsDelegate, MVMCorePresentationDelegateProtocol, SubNavSwipeNavigationProtocol { - + /// The number of tabs count or less that will turn on the fillContainer + public var fillContainerTabsCount = 2 { didSet { tabs.fillContainer = tabsModel.tabs.count <= fillContainerTabsCount }} + /// The current managed view controller private var viewController: UIViewController @@ -31,7 +33,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, public lazy var tabs: Tabs = { let tabs = Tabs(model: tabsModel, delegateObjectIVar, nil) tabs.backgroundColor = (viewController as? PageProtocol)?.pageModel?.navigationBar?.backgroundColor?.uiColor ?? VDSColor.backgroundPrimaryLight - tabs.fillContainer = true tabs.delegate = self return tabs }() @@ -71,6 +72,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, func setup(with loadObject: MVMCoreLoadObject, shouldEnableSwipeGestures: Bool) { self.loadObject = loadObject pageType = loadObject.pageType + tabs.fillContainer = tabsModel.tabs.count <= fillContainerTabsCount if shouldEnableSwipeGestures { customInteractor = SubNavInteractor(viewController: self) } From eb2d6607609073124e73f3145b15f641413630fb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 1 Feb 2024 14:28:01 -0600 Subject: [PATCH 70/77] added a wrapper view for tabs along with constraints so that we can expand and collapse margins based on the tabs configuration Signed-off-by: Matt Bruce --- .../SubNav/SubNavManagerController.swift | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 6a959440..98ca630a 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -22,14 +22,34 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, /// Used to layout the ui. public lazy var stackView: UIStackView = { - let stackView = UIStackView(arrangedSubviews: [tabs, subNavigationController.view]) + let stackView = UIStackView(arrangedSubviews: [tabsWrapper, subNavigationController.view]) stackView.translatesAutoresizingMaskIntoConstraints = false stackView.isAccessibilityElement = false stackView.axis = .vertical return stackView }() + private var tabsLeadingConstraint: NSLayoutConstraint? + private var tabsTrailingConstraint: NSLayoutConstraint? + + private lazy var tabsWrapper: UIView = { + // create the wrapper view for tabs + let tabsWrapper = UIView() + tabsWrapper.translatesAutoresizingMaskIntoConstraints = false + tabsWrapper.addSubview(tabs) + + // tabs constraints on wrapper + tabs.pinTop() + tabs.pinBottom() + tabsLeadingConstraint = tabs.pinLeading(anchor: tabsWrapper.leadingAnchor)?.activate() + tabsTrailingConstraint = tabs.pinTrailing(anchor: tabsWrapper.trailingAnchor)?.activate() + return tabsWrapper + }() + + private var isFillContainer: Bool { tabsModel.tabs.count <= fillContainerTabsCount } + private var tabsModel: TabsModel + public lazy var tabs: Tabs = { let tabs = Tabs(model: tabsModel, delegateObjectIVar, nil) tabs.backgroundColor = (viewController as? PageProtocol)?.pageModel?.navigationBar?.backgroundColor?.uiColor ?? VDSColor.backgroundPrimaryLight @@ -60,7 +80,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, super.init(nibName: nil, bundle: nil) setup(with: loadObject, shouldEnableSwipeGestures: shouldEnableSwipeGestures) } - + public init(viewControllers: [UIViewController], tabsModel: TabsModel, loadObject: MVMCoreLoadObject, shouldEnableSwipeGestures: Bool) { self.tabsModel = tabsModel self.viewControllers = viewControllers @@ -72,7 +92,11 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, func setup(with loadObject: MVMCoreLoadObject, shouldEnableSwipeGestures: Bool) { self.loadObject = loadObject pageType = loadObject.pageType - tabs.fillContainer = tabsModel.tabs.count <= fillContainerTabsCount + + //update the tabs + tabs.fillContainer = isFillContainer + updateTabsMargin() + if shouldEnableSwipeGestures { customInteractor = SubNavInteractor(viewController: self) } @@ -126,6 +150,12 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, super.viewWillAppear(animated) hideNavigationBarLine(true) } + /// ensures margin for tabs are correct + private func updateTabsMargin() { + let tabsGutterSpacing = isFillContainer ? 0 : Padding.Component.horizontalPaddingForSize(stackView.bounds.width) + tabsLeadingConstraint?.constant = tabsGutterSpacing + tabsTrailingConstraint?.constant = tabsGutterSpacing + } /// Hides/Shows the navigation bar for the page. open func hideNavigationBarLine(_ isHidden: Bool) { @@ -143,7 +173,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, open override func updateViews() { super.updateViews() if screenSizeChanged() { - tabs.updateView(view.bounds.size.width) + updateTabsMargin() } } From cf0d42b908239ff034dcfffde259f19878186ce7 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 1 Feb 2024 14:49:48 -0600 Subject: [PATCH 71/77] added negative for trailing Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 98ca630a..bf8fbfc4 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -154,7 +154,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, private func updateTabsMargin() { let tabsGutterSpacing = isFillContainer ? 0 : Padding.Component.horizontalPaddingForSize(stackView.bounds.width) tabsLeadingConstraint?.constant = tabsGutterSpacing - tabsTrailingConstraint?.constant = tabsGutterSpacing + tabsTrailingConstraint?.constant = -tabsGutterSpacing } /// Hides/Shows the navigation bar for the page. From 548bb364f32c139eb3977d7c13c47414d4d12503 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 1 Feb 2024 14:50:38 -0600 Subject: [PATCH 72/77] updated type Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index bf8fbfc4..9bf81fa8 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -42,7 +42,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, tabs.pinTop() tabs.pinBottom() tabsLeadingConstraint = tabs.pinLeading(anchor: tabsWrapper.leadingAnchor)?.activate() - tabsTrailingConstraint = tabs.pinTrailing(anchor: tabsWrapper.trailingAnchor)?.activate() + tabsTrailingConstraint = tabs.pinTrailingLessThanOrEqualTo(anchor: tabsWrapper.trailingAnchor)?.activate() return tabsWrapper }() From cc85cfac79c11017ba987c54ffd8c451cfc5d18c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 1 Feb 2024 16:30:22 -0600 Subject: [PATCH 73/77] updated for the notes scott left Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 9bf81fa8..449dff99 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -42,7 +42,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, tabs.pinTop() tabs.pinBottom() tabsLeadingConstraint = tabs.pinLeading(anchor: tabsWrapper.leadingAnchor)?.activate() - tabsTrailingConstraint = tabs.pinTrailingLessThanOrEqualTo(anchor: tabsWrapper.trailingAnchor)?.activate() + tabsTrailingConstraint = tabsWrapper.pinTrailingGreaterThanOrEqualTo(anchor: tabs.trailingAnchor)?.activate() return tabsWrapper }() @@ -154,7 +154,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, private func updateTabsMargin() { let tabsGutterSpacing = isFillContainer ? 0 : Padding.Component.horizontalPaddingForSize(stackView.bounds.width) tabsLeadingConstraint?.constant = tabsGutterSpacing - tabsTrailingConstraint?.constant = -tabsGutterSpacing + tabsTrailingConstraint?.constant = tabsGutterSpacing } /// Hides/Shows the navigation bar for the page. @@ -173,6 +173,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, open override func updateViews() { super.updateViews() if screenSizeChanged() { + tabs.updateView(view.bounds.size.width) updateTabsMargin() } } From 0a291491eb6c08616164e27e69ecf9c0be466a3d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 1 Feb 2024 16:49:02 -0600 Subject: [PATCH 74/77] fixed constraint Signed-off-by: Matt Bruce --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 449dff99..741fb830 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -42,7 +42,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, tabs.pinTop() tabs.pinBottom() tabsLeadingConstraint = tabs.pinLeading(anchor: tabsWrapper.leadingAnchor)?.activate() - tabsTrailingConstraint = tabsWrapper.pinTrailingGreaterThanOrEqualTo(anchor: tabs.trailingAnchor)?.activate() + tabsTrailingConstraint = tabsWrapper.pinTrailing(anchor: tabs.trailingAnchor)?.activate() return tabsWrapper }() @@ -152,7 +152,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } /// ensures margin for tabs are correct private func updateTabsMargin() { - let tabsGutterSpacing = isFillContainer ? 0 : Padding.Component.horizontalPaddingForSize(stackView.bounds.width) + let tabsGutterSpacing = isFillContainer ? 0 : Padding.Component.horizontalPaddingForSize(view.bounds.size.width) tabsLeadingConstraint?.constant = tabsGutterSpacing tabsTrailingConstraint?.constant = tabsGutterSpacing } From 4634cff455894a16acd0e31692a9647efc0020b3 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Fri, 2 Feb 2024 17:26:23 +0530 Subject: [PATCH 75/77] bugfix: CXTDT-459435 - Removing titleLabel from accessible elements, as the title's text is set as the textfields accessibilityLabel. --- .../Atomic/Atoms/FormFields/TextFields/TextEntryField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift index a40aa56f..a3780846 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift @@ -187,7 +187,7 @@ import UIKit let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing)) entryFieldContainer.addGestureRecognizer(tap) - accessibilityElements = [titleLabel, textField, feedbackLabel] + accessibilityElements = [textField, feedbackLabel] } @objc open override func updateView(_ size: CGFloat) { From 9c848e610c1bb361ca6159f68d2d0cc0225ee8aa Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Thu, 8 Feb 2024 19:58:55 -0500 Subject: [PATCH 76/77] Hold onto selected tab index in the view model. --- MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index e070b8e6..f0d93237 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -30,6 +30,7 @@ import VDS if let delegate { onTabDidSelect = { [weak self] index in guard let self else { return } + viewModel.selectedIndex = index delegate.didSelectItem(.init(row: index, section: 0), tabs: self) } From b267e196fd4369745a59b860e1593d08164e64df Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 9 Feb 2024 08:55:37 -0600 Subject: [PATCH 77/77] added override to set model selectedIndex Signed-off-by: Matt Bruce --- .../HorizontalCombinationViews/Tabs.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index f0d93237..17da8897 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -23,14 +23,13 @@ import VDS open var viewModel: TabsModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - + //delegate weak public var delegate: TabsDelegate? { didSet { if let delegate { onTabDidSelect = { [weak self] index in guard let self else { return } - viewModel.selectedIndex = index delegate.didSelectItem(.init(row: index, section: 0), tabs: self) } @@ -41,7 +40,17 @@ import VDS } } } - + + //-------------------------------------------------- + // MARK: - Public Properties Overrides + //-------------------------------------------------- + open override var selectedIndex: Int { + didSet { + guard let viewModel else { return } + viewModel.selectedIndex = selectedIndex + } + } + //------------------------------------------------- // MARK: - Layout Views //-------------------------------------------------