// // Toggle.swift // MVMCoreUI // // Created by Kevin Christiano on 12/4/19. // Copyright © 2019 Verizon Wireless. All rights reserved. // import MVMCore import MVMCoreUI import UIKit import VDS public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtocol { associatedtype ViewModel: MoleculeModelProtocol var viewModel: ViewModel! { get set } var delegateObject: MVMCoreUIDelegateObject? { get set } var additionalData: [AnyHashable: Any]? { get set } func viewModelDidUpdate() } extension VDSMoleculeViewProtocol { public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let castedModel = model as? ViewModel else { return } self.delegateObject = delegateObject viewModel = castedModel viewModelDidUpdate() } } extension TestToggleModel { public func getVDSModel() -> DefaultToggleModel { return DefaultToggleModel().copyWith { $0.disabled = !enabled && readOnly $0.on = selected if let accessibilityText = accessibilityText { $0.accessibilityLabelEnabled = accessibilityText $0.accessibilityLabelDisabled = accessibilityText } } } } open class TestToggle: ToggleBase, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public var viewModel: TestToggleModel! public var delegateObject: MVMCoreUIDelegateObject? public var additionalData: [AnyHashable: Any]? //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- public override func initialSetup() { super.initialSetup() publisher(for: .touchUpInside) .sink {[weak self] toggle in guard let self = self else { return } self.toggle() }.store(in: &subscribers) publisher(for: .valueChanged) .sink {[weak self] toggle in guard let self = self else { return } self.valueChanged(isOn: toggle.isOn) }.store(in: &subscribers) model.accessibilityLabelEnabled = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel") model.accessibilityLabelDisabled = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel") model.accessibilityHintEnabled = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint") model.accessibilityHintDisabled = MVMCoreUIUtility.hardcodedString(withKey: "AccDisabled") model.accessibilityValueEnabled = MVMCoreUIUtility.hardcodedString(withKey: "AccOn") model.accessibilityValueDisabled = MVMCoreUIUtility.hardcodedString(withKey: "AccOff") } // MARK:- MVMCoreViewProtocol open func updateView(_ size: CGFloat) {} open func viewModelDidUpdate() { guard let viewModel else { return } FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) additionalData = additionalData.dictionaryAdding(key: KeySourceModel, value: viewModel) set(with: viewModel.getVDSModel()) } private func valueChanged(isOn: Bool){ guard let viewModel else { return } //sync the value on the viewModel viewModel.selected = isOn //tell the form you changed _ = FormValidator.validate(delegate: self.delegateObject?.formHolderDelegate) if viewModel.action != nil || viewModel.alternateAction != nil { var action: ActionModelProtocol? if isOn { action = viewModel.action } else { action = viewModel.alternateAction ?? viewModel.action } if let action { MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: viewModel, additionalData: additionalData, delegateObject: delegateObject) } } print("toggle value changed to: \(isOn)") print("viewModel server value: \(viewModel.formFieldServerValue()!)") } public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 44 } private typealias ActionDefinition = (model: ActionModelProtocol, sourceModel: MoleculeModelProtocol?) private func performActionUnstructured(definition: ActionDefinition) { MVMCoreUIActionHandler.performActionUnstructured(with: definition.model, sourceModel: definition.sourceModel, additionalData: additionalData, delegateObject: delegateObject) } } // MARK: - MVMCoreUIViewConstrainingProtocol extension TestToggle: MVMCoreUIViewConstrainingProtocol { public func needsToBeConstrained() -> Bool { true } public func horizontalAlignment() -> UIStackView.Alignment { .trailing } } open class TestToggle2: GenericMolecule, MVMCoreUIViewConstrainingProtocol { private var toggle = Toggle() open override func initialSetup() { super.initialSetup() //handle valueChanged toggle.publisher(for: .valueChanged) .sink { [weak self] control in self?.valueDidChange(isOn: control.isOn) }.store(in: &toggle.subscribers) } @Proxy(\.toggle.isOn) open var isOn: Bool @Proxy(\.toggle.isEnabled) open var isEnabled: Bool open override func setupView(){ super.setupView() addSubview(toggle) NSLayoutConstraint.constraintPinSubview(toSuperview: toggle) } open override func viewModelUpdate(model: TestToggleModel2) { toggle.isEnabled = model.enabled toggle.isOn = model.selected isUserInteractionEnabled = model.enabled && !model.readOnly additionalData = additionalData.dictionaryAdding(key: KeySourceModel, value: model) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) } open func valueDidChange(isOn: Bool) { print("Toggle valueDidChange: \(isOn)") if model.action != nil || model.alternateAction != nil { var action: ActionModelProtocol? if isOn { action = model.action } else { action = model.alternateAction ?? model.action } if let action { MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: model, additionalData: additionalData, delegateObject: delegateObject) } } } //MARK - MoleculeViewProtocol public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 44 } //MARK - MVMCoreUIViewConstrainingProtocol public func needsToBeConstrained() -> Bool { true } public func horizontalAlignment() -> UIStackView.Alignment { .trailing } }