From 8e35e8036a5bd5a2b5a4bc12c4714d4ecd0a8c41 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 14 Sep 2023 13:55:17 -0400 Subject: [PATCH] Tiny button to small --- .../Atomic/Atoms/Buttons/ButtonModel.swift | 4 +- .../Atomic/Atoms/Buttons/PillButton.swift | 180 +++++++----------- .../Atomic/Extensions/VDS-Enums+Codable.swift | 21 +- .../ListDeviceComplexButtonMediumModel.swift | 2 +- .../ListDeviceComplexButtonSmallModel.swift | 2 +- ...htVariableButtonAllTextAndLinksModel.swift | 2 +- .../TwoButtonViewModel.swift | 6 +- .../NotificationMoleculeModel.swift | 2 +- .../BGImageHeadlineBodyButtonModel.swift | 2 +- .../HeadlineBodyButtonModel.swift | 2 +- 10 files changed, 105 insertions(+), 118 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index 22ee9b8b..b15f8adb 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -32,7 +32,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat setFacade(by: style) } } - public var size: ButtonSize = .large + public var size: VDS.Button.Size = .large public var groupName: String = "" public var inverted: Bool = false @@ -221,7 +221,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat setFacade(by: .primary) } - if let size = try typeContainer.decodeIfPresent(VDS.ButtonSize.self, forKey: .size) { + if let size = try typeContainer.decodeIfPresent(VDS.Button.Size.self, forKey: .size) { self.size = size } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 56df2044..4a812a57 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -9,8 +9,10 @@ import UIKit import VDSColorTokens import VDS +import MVMCore +import Combine -open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol { +open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol, MVMCoreViewProtocol, MFButtonProtocol { //-------------------------------------------------- // MARK: - Properties @@ -21,10 +23,33 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi get { model as? ButtonModel } } + var onClickCancellable: Cancellable? + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- + required public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: .zero) + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + } + + open override func setup() { + super.setup() + setupView() + } + + //-------------------------------------------------- + // MARK: - Convenience + //-------------------------------------------------- + @objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) { let model = ButtonModel(with: "", action: ActionNoopModel()) model.style = isPrimary ? .primary : .secondary @@ -32,8 +57,20 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi self.init(model: model, nil, nil) } + /// The primary styling for a button. Should be used for main buttons + public func stylePrimary() { + let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel()) + use = .primary + } + + /// The secondary styling for a button. Should be used for secondary buttons + public func styleSecondary() { + let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel()) + use = .secondary + } + //-------------------------------------------------- - // MARK: - MVMCoreViewProtocol + // MARK: - MoleculeViewProtocol //-------------------------------------------------- open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { @@ -51,129 +88,60 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeVi isEnabled = model.enabled size = model.size +// if let backgroundColor = model.backgroundColor { +// self.backgroundColor = backgroundColor.uiColor +// } model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - self?.enableField(model.enabled) + self?.isEnabled = model.enabled }) } FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - guard let model = model as? ButtonModelProtocol else { return } - //set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) - } -} - -open func reset() { - backgroundColor = .clear -} - -// MARK: Overridables -// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead. -open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { - model.moleculeName -} - -open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil } - -open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { nil } - -//-------------------------------------------------- -// MARK: - Accessibility -//-------------------------------------------------- - -open override func accessibilityActivate() -> Bool { - guard isEnabled else { return false } - buttonAction?(self) - return buttonAction != nil -} - -} - -// MARK: - MVMCoreViewProtocol -extension Button: MVMCoreViewProtocol { - -open func updateView(_ size: CGFloat) { } - -/// Will be called only once. -open func setupView() { - isAccessibilityElement = true - accessibilityTraits = .button - translatesAutoresizingMaskIntoConstraints = false - insetsLayoutMarginsFromSafeArea = false - titleLabel?.numberOfLines = 0 - titleLabel?.lineBreakMode = .byWordWrapping -} -} - -// MARK: AppleGuidelinesProtocol -extension Button: AppleGuidelinesProtocol { - -override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - Self.acceptablyOutsideBounds(point: point, bounds: bounds) -} -} - - - open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return (model as? ButtonModel)?.size?.getHeight() + set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } - open override func updateView(_ size: CGFloat) { - super.updateView(size) - self.size = size - - switch buttonSize { - case .tiny: - titleLabel?.font = Styler.Font.BoldMicro.getFont(false) - case .small: - titleLabel?.font = Styler.Font.BoldBodySmall.getFont(false) - case .standard: - titleLabel?.font = Styler.Font.BoldBodyLarge.getFont(false) - } - - layer.cornerRadius = getInnerPadding() - contentEdgeInsets = getContentEdgeInsets() - - if let contraint = buttonModel?.width { - - if widthConstraint == nil { - widthConstraint = widthAnchor.constraint(equalToConstant: contraint) - } else if widthConstraint?.constant != contraint { - widthConstraint?.constant = contraint - } - widthConstraint?.isActive = true - minimumWidthConstraint?.isActive = false - } else { - - if minimumWidthConstraint == nil { - minimumWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: buttonSize.minimumWidth()) - } else { - minimumWidthConstraint?.constant = buttonSize.minimumWidth() - } - minimumWidthConstraint?.isActive = true - widthConstraint?.isActive = false - } + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + + open override func reset() { + super.reset() + //backgroundColor = .clear } - open override func setupView() { - super.setupView() - - titleLabel?.numberOfLines = 1 - titleLabel?.lineBreakMode = .byTruncatingTail - titleLabel?.textAlignment = .center - contentHorizontalAlignment = .center - stylePrimary() + open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return (model as? ButtonModel)?.size.height } + open func updateView(_ size: CGFloat) {} + + open func setupView() {} + //-------------------------------------------------- // MARK: - MVMCoreUIViewConstrainingProtocol //-------------------------------------------------- open func horizontalAlignment() -> UIStackView.Alignment { .center } - public func enableField(_ enable: Bool) { - isEnabled = enable + //-------------------------------------------------- + // MARK: - Action + //-------------------------------------------------- + + open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + onClickCancellable = onClickSubscriber.publisher.sink { [weak self] _ in + guard let self = self, + let actionModel = self.buttonModel?.action else { return } + Task(priority: .userInitiated) { + try await Self.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: self.model) + } + } + } + + open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws { + guard delegateObject?.buttonDelegate?.button?(button, shouldPerformActionWithMap: model.toJSON(), additionalData: additionalData) ?? true else { return } + try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: model, additionalData: MVMCoreUIActionHandler.add(sourceModel: sourceModel, to: additionalData), delegateObject: delegateObject) } } diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index b2463ed1..ea462930 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -16,5 +16,24 @@ extension Icon.Size: Codable {} extension TileContainer.BackgroundColor: Codable {} extension TileContainer.Padding: Codable {} extension TileContainer.AspectRatio: Codable {} -extension ButtonSize: Codable {} extension Use: Codable {} +extension VDS.Button.Size: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let string = try container.decode(String.self) + switch string { + case VDS.Button.Size.large.rawValue: + self = .large + case VDS.Button.Size.small.rawValue, "tiny": + self = .small + default: + self = .large + } + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(self) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift index 88f7fe97..54b313e6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMediumModel.swift @@ -42,7 +42,7 @@ public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelPro override public func setDefaults() { super.setDefaults() - button.size = .tiny + button.size = .small button.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift index 13be8c03..d06a3845 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmallModel.swift @@ -42,7 +42,7 @@ public class ListDeviceComplexButtonSmallModel: ListItemModel, MoleculeModelProt override public func setDefaults() { super.setDefaults() - button.size = .tiny + button.size = .small button.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift index 21a4b08c..30856e55 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift @@ -32,7 +32,7 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul override public func setDefaults() { super.setDefaults() - self.button.size = .tiny + self.button.size = .small self.button.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index b5d07c4a..a7b4055c 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -7,7 +7,7 @@ // import UIKit - +import VDS public class TwoButtonViewModel: ParentMoleculeModelProtocol { //-------------------------------------------------- @@ -56,13 +56,13 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { //set context value for 'primary' style to be set for the primaryButton in case the //property is not returned in the JSON and once decoded, this value is removed from the context - try decoder.setContext(value: Styler.Button.Style.primary, for: "style") { + try decoder.setContext(value: Use.primary, for: "style") { self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton) } //set context value for 'secondary' style to be set for the primaryButton in case the //property is not returned in the JSON and once decoded, this value is removed from the context - try decoder.setContext(value: Styler.Button.Style.secondary, for: "style") { + try decoder.setContext(value: Use.secondary, for: "style") { self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton) } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index d26bb06c..27ca95a8 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -89,7 +89,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { } } - button?.size = .tiny + button?.size = .small button?.style = .secondary switch style { case .error, .warning: diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift index 99ee1567..4e2d031a 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift @@ -54,7 +54,7 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc image.height = BGImageHeadlineBodyButton.heightConstant } - button?.size = .tiny + button?.size = .small button?.style = .secondary } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index 1b713720..347277fd 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -38,7 +38,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol { /// Defaults to set public func setDefaults() { - button.size = .tiny + button.size = .small button.style = .secondary }