// // TestToggleVM.swift // JSONCreator // // Created by Matt Bruce on 10/12/22. // Copyright © 2022 Verizon Wireless. All rights reserved. // import Foundation import MVMCore import MVMCoreUI import VDS /// This is a mixed model of Atomic + VDS.ToggleModel that will be used with the Control /// There is no requirement for syncing since it is 1 model public class TestToggleModel3: MoleculeModelProtocol, FormFieldProtocol, VDS.ToggleModel { //ToggleModel public var id = UUID() public var showText: Bool = true public var on: Bool = false public var offText: String = "Off" public var onText: String = "On" public var textWeight: VDS.ToggleTextWeight = .bold public var textSize: VDS.ToggleTextSize = .small public var textPosition: VDS.ToggleTextPosition = .left public var inputId: String? public var value: AnyHashable? public var dataAnalyticsTrack: String? public var dataClickStream: String? public var dataTrack: String? public var accessibilityHintEnabled: String? public var accessibilityHintDisabled: String? public var accessibilityValueEnabled: String? public var accessibilityValueDisabled: String? public var accessibilityLabelEnabled: String? public var accessibilityLabelDisabled: String? public var surface: VDS.Surface = .light public var disabled: Bool = false public required init() {} //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "testToggle3" public var backgroundColor: Color? //not used public var selected: Bool = false public var enabled: Bool = true public var readOnly: Bool = false public var action: ActionModelProtocol? public var alternateAction: ActionModelProtocol? public var accessibilityText: String? public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { case moleculeName case state case enabled case readOnly case action case accessibilityIdentifier case alternateAction case accessibilityText case fieldKey case groupName } //-------------------------------------------------- // MARK: - Form Valdiation //-------------------------------------------------- public func formFieldValue() -> AnyHashable? { guard enabled else { return nil } return on } //-------------------------------------------------- // MARK: - Server Value //-------------------------------------------------- open func formFieldServerValue() -> AnyHashable? { return formFieldValue() } //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- public init(_ state: Bool) { selected = state baseValue = state } //-------------------------------------------------- // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { selected = state on = state } action = try typeContainer.decodeModelIfPresent(codingKey: .action) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) baseValue = selected fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) if let gName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { groupName = gName } enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true disabled = !enabled readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(selected, forKey: .state) try container.encode(enabled, forKey: .enabled) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encode(readOnly, forKey: .readOnly) } public static func == (lhs: TestToggleModel3, rhs: TestToggleModel3) -> Bool { return lhs.id == rhs.id && lhs.on == rhs.on && lhs.showText == rhs.showText && lhs.offText == rhs.offText && lhs.onText == rhs.onText && lhs.textWeight == rhs.textWeight && lhs.textSize == rhs.textSize && lhs.inputId == rhs.inputId && lhs.value == rhs.value && lhs.dataAnalyticsTrack == rhs.dataAnalyticsTrack && lhs.dataClickStream == rhs.dataClickStream && lhs.dataTrack == rhs.dataTrack && lhs.accessibilityHintEnabled == rhs.accessibilityHintEnabled && lhs.accessibilityHintDisabled == rhs.accessibilityHintDisabled && lhs.accessibilityValueEnabled == rhs.accessibilityValueEnabled && lhs.accessibilityValueDisabled == rhs.accessibilityValueDisabled && lhs.accessibilityLabelEnabled == rhs.accessibilityLabelEnabled && lhs.accessibilityLabelEnabled == rhs.accessibilityLabelEnabled && lhs.surface == rhs.surface && lhs.disabled == rhs.disabled } } /// The is a Sample of using the ViewModelHandler which is a an intermediate class between the View and the model /// Since we are using a viewModel there is more legwork upfront, however you can use classes or structs as the model open class TestToggle3: ToggleViewModelHandlerBase>, VDSVMMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- 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) } // MARK:- MVMCoreViewProtocol open func updateView(_ size: CGFloat) {} open func viewModelDidSet() { FormValidator.setupValidation(for: viewModel.model, delegate: delegateObject?.formHolderDelegate) additionalData = additionalData.dictionaryAdding(key: KeySourceModel, value: viewModel) } private func valueChanged(isOn: Bool){ //tell the form you changed _ = FormValidator.validate(delegate: self.delegateObject?.formHolderDelegate) if viewModel.model.action != nil || viewModel.model.alternateAction != nil { var action: ActionModelProtocol? if isOn { action = viewModel.model.action } else { action = viewModel.model.alternateAction ?? viewModel.model.action } if let action { MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: viewModel.model, additionalData: additionalData, delegateObject: delegateObject) } } print("toggle value changed to: \(isOn)") print("viewModel server value: \(viewModel.model.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) } }