From fa52fa8c12948798ece5c995e42881842b25e501 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Jul 2024 15:58:01 -0500 Subject: [PATCH 1/6] added protocol/refactored to deal with RadiobuttonLabel Signed-off-by: Matt Bruce --- .../Selectors/RadioButtonSelectionHelper.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift index 2b6fa01d..4ca37dce 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift @@ -6,6 +6,10 @@ // Copyright © 2019 Verizon Wireless. All rights reserved. // +public protocol RadioButtonSelectionHelperProtocol: AnyObject { + var isSelected: Bool { get set } + var radioButtonModel: RadioButtonModel { get } +} @objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { //-------------------------------------------------- @@ -14,7 +18,7 @@ public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName - private var selectedRadioButton: RadioButton? + private var selectedRadioButton: RadioButtonSelectionHelperProtocol? private var selectedRadioButtonModel: RadioButtonModel? public var baseValue: AnyHashable? public var enabled: Bool = true @@ -24,7 +28,7 @@ // MARK: - Initializer //-------------------------------------------------- - public func set(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton) { + public func set(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButtonSelectionHelperProtocol) { self.fieldKey = radioButtonModel.fieldKey self.groupName = radioButtonModel.groupName @@ -49,7 +53,7 @@ // MARK: - Functions //-------------------------------------------------- - public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton, delegateObject: MVMCoreUIDelegateObject?) { + public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButtonSelectionHelperProtocol, delegateObject: MVMCoreUIDelegateObject?) { guard let groupName = radioButtonModel.fieldKey, let formValidator = delegateObject?.formHolderDelegate?.formValidator @@ -61,10 +65,10 @@ FormValidator.setupValidation(for: radioButtonSelectionHelper, delegate: delegateObject?.formHolderDelegate) } - public func selected(_ radioButton: RadioButton) { + public func selected(_ radioButton: RadioButtonSelectionHelperProtocol) { // Checks because the view could be reused - if selectedRadioButton?.radioModel === selectedRadioButtonModel { + if selectedRadioButton?.radioButtonModel === selectedRadioButtonModel { selectedRadioButton?.isSelected = false } else { selectedRadioButtonModel?.state = false @@ -72,7 +76,7 @@ selectedRadioButton = radioButton selectedRadioButton?.isSelected = true - selectedRadioButtonModel = selectedRadioButton?.radioModel + selectedRadioButtonModel = selectedRadioButton?.radioButtonModel } } From 10c55b12be709d291386ee24c9268308480442ea Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Jul 2024 15:58:15 -0500 Subject: [PATCH 2/6] converted to VDS Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/RadioButton.swift | 238 +++++++++--------- .../Atoms/Selectors/RadioButtonModel.swift | 69 ++--- 2 files changed, 131 insertions(+), 176 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index e73a8d5c..9c0d9e46 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -7,37 +7,35 @@ // import UIKit -import VDSCoreTokens +import VDS -@objcMembers open class RadioButton: Control, MFButtonProtocol { - //-------------------------------------------------- +@objcMembers open class RadioButton: VDS.RadioButton, RadioButtonSelectionHelperProtocol, VDSMoleculeViewProtocol, MFButtonProtocol, MVMCoreUIViewConstrainingProtocol { + //------------------------------------------------------ // MARK: - Properties - //-------------------------------------------------- - - public var diameter: CGFloat = 20 { - didSet { widthConstraint?.constant = diameter } + //------------------------------------------------------ + open var viewModel: RadioButtonModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + + open var radioButtonModel: RadioButtonModel { + viewModel } - @objc public override var isSelected: Bool { + // Form Validation + var fieldKey: String? + var fieldValue: JSONValue? + var groupName: String? + + open override var isSelected: Bool { didSet { - radioModel?.state = isSelected - updateAccessibilityLabel() + viewModel.state = isSelected + if oldValue != isSelected { + sendActions(for: .valueChanged) + } } } - public var enabledColor: UIColor { - return radioModel?.inverted ?? false ? VDSColor.elementsPrimaryOndark : VDSColor.elementsPrimaryOnlight - } - public var disabledColor: UIColor { - return radioModel?.inverted ?? false ? VDSColor.interactiveDisabledOndark : VDSColor.interactiveDisabledOnlight - } - public var delegateObject: MVMCoreUIDelegateObject? - var additionalData: [AnyHashable: Any]? - - public var radioModel: RadioButtonModel? { - model as? RadioButtonModel - } - - lazy public var radioGroupName: String? = { radioModel?.fieldKey }() + + lazy public var radioGroupName: String? = { viewModel.fieldKey }() lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { @@ -48,132 +46,120 @@ import VDSCoreTokens return radioButtonModel }() - public override var isEnabled: Bool { - didSet { - isUserInteractionEnabled = isEnabled - setNeedsDisplay() - } + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + override public init(frame: CGRect) { + super.init(frame: frame) } - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - public var widthConstraint: NSLayoutConstraint? - public var heightConstraint: NSLayoutConstraint? - - //-------------------------------------------------- - // MARK: - Lifecycle - //-------------------------------------------------- - - open override func draw(_ rect: CGRect) { - guard let context = UIGraphicsGetCurrentContext() else { return } - - let color = isEnabled == false ? disabledColor.cgColor : enabledColor.cgColor - layer.cornerRadius = bounds.width * 0.5 - layer.borderColor = color - layer.borderWidth = bounds.width * 0.0333 - - if isSelected { - // Space around inner circle is 1/5 the size - context.addEllipse(in: CGRect(x: bounds.width * 0.2, - y: bounds.height * 0.2, - width: bounds.width * 0.6, - height: bounds.height * 0.6)) - context.setFillColor(color) - context.fillPath() - } + /// There is currently no intention on using xib files. + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + fatalError("xib file is not implemented for Checkbox.") } + public convenience required init() { + self.init(frame:.zero) + } + //-------------------------------------------------- // MARK: - Validation //-------------------------------------------------- - /// The action performed when tapped. - func tapAction() { - if !isEnabled { - return + public func isValidField() -> Bool { isSelected } + + public func formFieldName() -> String? { + viewModel.fieldKey + } + + public func formFieldGroupName() -> String? { + viewModel.fieldKey + } + + public func formFieldValue() -> AnyHashable? { + guard let radioModel = viewModel, radioModel.enabled else { return nil } + return radioModel.fieldValue + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + open override func setup() { + super.setup() + bridge_accessibilityLabelBlock = { [weak self] in + guard let self else { return nil } + if let message = MVMCoreUIUtility.hardcodedString(withKey: "radio_button"), + let selectedState = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { + return message + selectedState + } else { + return nil + } } + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + } + + open override func toggle() { + guard !isSelected, isEnabled else { return } + + //removed error + if showError && isSelected == false { + showError.toggle() + } + let wasPreviouslySelected = isSelected - if let radioButtonModel = radioButtonSelectionHelper { - radioButtonModel.selected(self) + if let radioButtonSelectionHelper { + radioButtonSelectionHelper.selected(self) } else { isSelected = !isSelected } - if let radioModel = radioModel, let actionModel = radioModel.action, isSelected, !wasPreviouslySelected { + if let actionModel = viewModel.action, isSelected, !wasPreviouslySelected { Task(priority: .userInitiated) { - try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: radioModel) + try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel) } } - _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) - setNeedsDisplay() - } - - public func isValidField() -> Bool { isSelected } - - public func formFieldName() -> String? { - radioModel?.fieldKey - } - - public func formFieldGroupName() -> String? { - radioModel?.fieldKey - } - - public func formFieldValue() -> AnyHashable? { - guard let radioModel = radioModel, radioModel.enabled else { return nil } - return radioModel.fieldValue + setNeedsUpdate() } //-------------------------------------------------- - // MARK: - Methods + // MARK: - Actions //-------------------------------------------------- - /// Adjust accessibility label based on state of RadioButton. - func updateAccessibilityLabel() { - if let message = MVMCoreUIUtility.hardcodedString(withKey: "radio_button"), - let selectedState = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { - accessibilityLabel = message + selectedState + /// This will toggle the state of the Checkbox and execute the actionBlock if provided. + public func tapAction() { + toggle() + } + + //-------------------------------------------------- + // MARK: - Molecular + //-------------------------------------------------- + + open func needsToBeConstrained() -> Bool { true } + + public func horizontalAlignment() -> UIStackView.Alignment { .leading } + + public func updateView(_ size: CGFloat) {} + + public func viewModelDidUpdate() { + + //events + viewModel.updateUI = { + MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in + guard let self = self else { return } + let isValid = viewModel.isValid ?? true + showError = !isValid + isEnabled = viewModel.enabled + + }) } - } - - //-------------------------------------------------- - // MARK: - MVMViewProtocol - //-------------------------------------------------- - - open override func setupView() { - super.setupView() - - backgroundColor = .clear - clipsToBounds = true - widthConstraint = widthAnchor.constraint(equalToConstant: 20) - widthConstraint?.isActive = true - heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1) - heightConstraint?.isActive = true - - addTarget(self, action: #selector(tapAction), for: .touchUpInside) - isAccessibilityElement = true - accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") - accessibilityTraits = .button - updateAccessibilityLabel() - } - - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.set(with: model, delegateObject, additionalData) - self.delegateObject = delegateObject - self.additionalData = additionalData - - guard let model = model as? RadioButtonModel else { return } - - isSelected = model.state - isEnabled = model.enabled && !model.readOnly - RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject) - } - - public override func reset() { - super.reset() - backgroundColor = .clear + + isSelected = viewModel.state + isEnabled = viewModel.enabled && !viewModel.readOnly + RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 99b5cdb7..308ede2b 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -7,47 +7,31 @@ // import MVMCore +import VDS - -open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { +open class RadioButtonModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "radioButton" - public var id: String = UUID().uuidString - - public var backgroundColor: Color? - public var accessibilityIdentifier: String? + public static override var identifier: String { "radioButton" } public var state: Bool = false - public var enabled: Bool = true - public var readOnly: Bool = false /// The specific value to send to server. TODO: update this to be more generic. public var fieldValue: String? - public var baseValue: AnyHashable? - public var groupName: String = FormValidator.defaultGroupName - public var fieldKey: String? public var action: ActionModelProtocol? public var inverted: Bool = false - + public var surface: Surface { inverted ? .dark : .light } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case id - case moleculeName - case backgroundColor - case accessibilityIdentifier case state - case enabled case fieldValue - case fieldKey - case groupName case action - case readOnly case inverted } @@ -56,49 +40,41 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- public init(_ state: Bool) { + super.init() self.state = state - baseValue = state + self.baseValue = state } //-------------------------------------------------- // MARK: - Validation //-------------------------------------------------- - public func formFieldValue() -> AnyHashable? { + public override func formFieldValue() -> AnyHashable? { guard enabled else { return nil } return fieldValue } - //-------------------------------------------------- - // MARK: - Server Value - //-------------------------------------------------- - open func formFieldServerValue() -> AnyHashable? { - return formFieldValue() + open override func setValidity(_ valid: Bool, errorMessage: String?) { + if let ruleErrorMessage = errorMessage, fieldKey != nil { + self.errorMessage = ruleErrorMessage + } + isValid = valid + updateUI?() } - + //-------------------------------------------------- // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { + try super.init(from: decoder) + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - - id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString - if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.state = state } - - enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true - readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) baseValue = state - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName - } fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) action = try typeContainer.decodeModelIfPresent(codingKey: .action) if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { @@ -106,17 +82,10 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { } } - public func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) - try container.encode(id, forKey: .id) - try container.encode(moleculeName, forKey: .moleculeName) try container.encode(state, forKey: .state) - try container.encode(enabled, forKey: .enabled) - try container.encode(readOnly, forKey: .readOnly) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeModelIfPresent(action, forKey: .action) try container.encodeIfPresent(inverted, forKey: .inverted) From 724130a8275176e10a904034e3fd13db13c98bcb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Jul 2024 15:58:22 -0500 Subject: [PATCH 3/6] converted to vds Signed-off-by: Matt Bruce --- .../RadioButtonLabel.swift | 145 +++++++++++++----- .../RadioButtonLabelModel.swift | 14 +- 2 files changed, 118 insertions(+), 41 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift index eb7266a9..39a578ba 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift @@ -7,54 +7,121 @@ // import UIKit +import VDS +@objcMembers public class RadioButtonLabel: VDS.RadioButtonItem, RadioButtonSelectionHelperProtocol, VDSMoleculeViewProtocol, MFButtonProtocol { -@objcMembers public class RadioButtonLabel: View { - - public let radioButton = RadioButton() - var delegateObject: MVMCoreUIDelegateObject? - let label = Label() - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - radioButton.updateView(size) - label.updateView(size) - } + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + open var viewModel: RadioButtonLabelModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? - open override func setupView() { - super.setupView() + open var radioButtonModel: RadioButtonModel { + viewModel.radioButton + } - addSubview(radioButton) - radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true - radioButton.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor).isActive = true + // Form Validation + var fieldKey: String? + var fieldValue: JSONValue? + var groupName: String? - if let rightView = createRightView() { - addSubview(rightView) - rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: Padding.Component.gutterForApplicationWidth).isActive = true - rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - - var constraint = rightView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) - constraint.priority = .defaultHigh - constraint.isActive = true - - constraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne) - constraint.priority = .defaultHigh - constraint.isActive = true - layoutMarginsGuide.centerYAnchor.constraint(equalTo: rightView.centerYAnchor).isActive = true + open override var isSelected: Bool { + didSet { + radioButtonModel.state = isSelected + if oldValue != isSelected { + sendActions(for: .valueChanged) + } } } - func createRightView() -> Container? { - let rightView = Container(andContain: label) - return rightView + lazy public var radioGroupName: String? = { viewModel.radioButton.fieldKey }() + + lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { + + guard let radioGroupName = radioGroupName, + let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] + else { return nil } + + return radioButtonModel + }() + + //-------------------------------------------------- + // MARK: - Life Cycle + //-------------------------------------------------- + @objc open func updateView(_ size: CGFloat) {} + + open override func toggle() { + guard !isSelected, isEnabled else { return } + + //removed error + if showError && isSelected == false { + showError.toggle() + } + + let wasPreviouslySelected = isSelected + if let radioButtonSelectionHelper { + radioButtonSelectionHelper.selected(self) + } else { + isSelected = !isSelected + } + + if let actionModel = viewModel.radioButton.action, isSelected, !wasPreviouslySelected { + Task(priority: .userInitiated) { + try await Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel) + } + } + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + } - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let radioButtonLabelModel = model as? RadioButtonLabelModel else { return } - - radioButton.set(with: radioButtonLabelModel.radioButton, delegateObject, additionalData) - label.set(with: radioButtonLabelModel.label, delegateObject, additionalData) + //-------------------------------------------------- + // MARK: - Atomic + //-------------------------------------------------- + public func viewModelDidUpdate() { + surface = viewModel.surface + + updateRadioButton() + + //primary label + labelText = viewModel.label.text + if let attributes = viewModel.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + labelTextAttributes = attributes + } + + //secondary label + if let subTitleModel = viewModel.subTitle { + childText = subTitleModel.text + if let attributes = subTitleModel.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + childTextAttributes = attributes + } + } } + + public func updateRadioButton() { + + if let fieldKey = viewModel.radioButton.fieldKey { + self.fieldKey = fieldKey + } + + //properties + isEnabled = viewModel.radioButton.enabled && !viewModel.radioButton.readOnly + isSelected = viewModel.radioButton.state + + //forms + RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel.radioButton, self, delegateObject: delegateObject) + + //events + viewModel.radioButton.updateUI = { + MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in + guard let self = self else { return } + let isValid = viewModel.radioButton.isValid ?? true + showError = !isValid + errorText = viewModel.radioButton.errorMessage + isEnabled = viewModel.radioButton.enabled + }) + } + } + } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 571848dc..0f4a4be6 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -8,8 +8,9 @@ import Foundation import MVMCore +import VDS -@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol { +@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -21,14 +22,23 @@ import MVMCore public var moleculeName: String = RadioButtonLabelModel.identifier public var radioButton: RadioButtonModel public var label: LabelModel + public var subTitle: LabelModel? + public var inverted: Bool? = false + public var surface: Surface { inverted ?? false ? .dark : .light } + public var children: [MoleculeModelProtocol] { + guard let subTitle else { return [radioButton, label] } + return [radioButton, label, subTitle] + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(radioButton: RadioButtonModel, label: LabelModel) { + public init(radioButton: RadioButtonModel, label: LabelModel, subTitle: LabelModel?) { self.radioButton = radioButton self.label = label + self.subTitle = subTitle } } From 04f228ea48982b0a85d4700a845c069b5e978e6d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Jul 2024 15:58:35 -0500 Subject: [PATCH 4/6] refactored to remove old properties Signed-off-by: Matt Bruce --- .../ListLeftVariableRadioButtonAllTextAndLinks.swift | 4 +--- .../ListLeftVariableRadioButtonAndPaymentMethod.swift | 4 +--- .../LeftVariable/ListLeftVariableRadioButtonBodyText.swift | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAllTextAndLinks.swift index cc3e57d6..df62b27d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAllTextAndLinks.swift @@ -81,9 +81,7 @@ func updateAccessibilityLabel() { var message = "" - - radioButton.updateAccessibilityLabel() - + if let radioButtonLabel = radioButton.accessibilityLabel { message += radioButtonLabel + ", " } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index b749355d..cf38c043 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -98,9 +98,7 @@ import UIKit func updateAccessibilityLabel() { var message = "" - - radioButton.updateAccessibilityLabel() - + if let radioButtonLabel = radioButton.accessibilityLabel { message += radioButtonLabel + ", " } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift index dc3a582a..5fbd617b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift @@ -85,7 +85,6 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell { var message = "" - radioButton.updateAccessibilityLabel() if let radioButtonLabel = radioButton.accessibilityLabel { message += radioButtonLabel + ", " } From 226c23abae345a900dca1a810ef23af508794970 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Jul 2024 10:39:40 -0500 Subject: [PATCH 5/6] removed inverted Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 308ede2b..5340b079 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -21,8 +21,6 @@ open class RadioButtonModel: FormFieldModel { public var fieldValue: String? public var action: ActionModelProtocol? - public var inverted: Bool = false - public var surface: Surface { inverted ? .dark : .light } //-------------------------------------------------- // MARK: - Keys @@ -32,7 +30,6 @@ open class RadioButtonModel: FormFieldModel { case state case fieldValue case action - case inverted } //-------------------------------------------------- @@ -77,9 +74,6 @@ open class RadioButtonModel: FormFieldModel { baseValue = state fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) action = try typeContainer.decodeModelIfPresent(codingKey: .action) - if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { - self.inverted = inverted - } } public override func encode(to encoder: Encoder) throws { @@ -88,6 +82,5 @@ open class RadioButtonModel: FormFieldModel { try container.encode(state, forKey: .state) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeModelIfPresent(action, forKey: .action) - try container.encodeIfPresent(inverted, forKey: .inverted) } } From 35ab4c94d202e269f53fa09d05277df62e7bf6c1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 30 Jul 2024 08:17:51 -0500 Subject: [PATCH 6/6] removed accessibility and rearranged methods/comments Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/RadioButton.swift | 58 ++++++++----------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index 9c0d9e46..3b4cfbc8 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -22,9 +22,9 @@ import VDS } // Form Validation - var fieldKey: String? - var fieldValue: JSONValue? - var groupName: String? + open var fieldKey: String? + open var fieldValue: JSONValue? + open var groupName: String? open override var isSelected: Bool { didSet { @@ -86,22 +86,27 @@ import VDS //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- - - open override func setup() { - super.setup() - bridge_accessibilityLabelBlock = { [weak self] in - guard let self else { return nil } - if let message = MVMCoreUIUtility.hardcodedString(withKey: "radio_button"), - let selectedState = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { - return message + selectedState - } else { - return nil - } + public func viewModelDidUpdate() { + + //events + viewModel.updateUI = { + MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in + guard let self = self else { return } + let isValid = viewModel.isValid ?? true + showError = !isValid + isEnabled = viewModel.enabled + + }) } - - accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + + isSelected = viewModel.state + isEnabled = viewModel.enabled && !viewModel.readOnly + RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject) } - + + //-------------------------------------------------- + // MARK: - Overrides + //-------------------------------------------------- open override func toggle() { guard !isSelected, isEnabled else { return } @@ -136,7 +141,7 @@ import VDS } //-------------------------------------------------- - // MARK: - Molecular + // MARK: - MoleculeViewProtocol //-------------------------------------------------- open func needsToBeConstrained() -> Bool { true } @@ -145,21 +150,4 @@ import VDS public func updateView(_ size: CGFloat) {} - public func viewModelDidUpdate() { - - //events - viewModel.updateUI = { - MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in - guard let self = self else { return } - let isValid = viewModel.isValid ?? true - showError = !isValid - isEnabled = viewModel.enabled - - }) - } - - isSelected = viewModel.state - isEnabled = viewModel.enabled && !viewModel.readOnly - RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject) - } }