From 07bd0a538f423a1a7a27cdd5f05716f2aae4d485 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 15 Aug 2022 16:47:34 -0500 Subject: [PATCH] added extra viewcontroller Signed-off-by: Matt Bruce --- VDSSample.xcodeproj/project.pbxproj | 8 ++ .../ViewControllers/ModelViewController.swift | 93 +++++++++++++ .../TemplateViewController.swift | 123 ++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 VDSSample/ViewControllers/ModelViewController.swift create mode 100644 VDSSample/ViewControllers/TemplateViewController.swift diff --git a/VDSSample.xcodeproj/project.pbxproj b/VDSSample.xcodeproj/project.pbxproj index 227b2f1..55cea22 100644 --- a/VDSSample.xcodeproj/project.pbxproj +++ b/VDSSample.xcodeproj/project.pbxproj @@ -41,6 +41,8 @@ EA3C3BB628996775000CA526 /* MenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3C3BB228996775000CA526 /* MenuViewController.swift */; }; EA3C3BB728996775000CA526 /* ToggleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3C3BB328996775000CA526 /* ToggleViewController.swift */; }; EAB1D2C528A6B11D00DAE764 /* TestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D2C428A6B11D00DAE764 /* TestViewController.swift */; }; + EAB1D2C928AAAA1D00DAE764 /* ModelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D2C828AAAA1D00DAE764 /* ModelViewController.swift */; }; + EAB1D2CB28AAB9E200DAE764 /* TemplateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D2CA28AAB9E200DAE764 /* TemplateViewController.swift */; }; EAF7F07C2899698800B287F5 /* Components.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EAF7F07A2899698800B287F5 /* Components.storyboard */; }; EAF7F07D2899698800B287F5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAF7F07B2899698800B287F5 /* Assets.xcassets */; }; EAF7F09C2899B92400B287F5 /* CheckboxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09B2899B92400B287F5 /* CheckboxViewController.swift */; }; @@ -97,6 +99,8 @@ EA3C3BBB289968A0000CA526 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = ""; }; EA3C3BC3289968B1000CA526 /* VDS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = VDS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EAB1D2C428A6B11D00DAE764 /* TestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestViewController.swift; sourceTree = ""; }; + EAB1D2C828AAAA1D00DAE764 /* ModelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelViewController.swift; sourceTree = ""; }; + EAB1D2CA28AAB9E200DAE764 /* TemplateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateViewController.swift; sourceTree = ""; }; EAF7F07A2899698800B287F5 /* Components.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Components.storyboard; sourceTree = ""; }; EAF7F07B2899698800B287F5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; EAF7F09B2899B92400B287F5 /* CheckboxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxViewController.swift; sourceTree = ""; }; @@ -210,6 +214,8 @@ EAF7F11928A14A0E00B287F5 /* RadioButtonViewController.swift */, EA3C3BB328996775000CA526 /* ToggleViewController.swift */, EAB1D2C428A6B11D00DAE764 /* TestViewController.swift */, + EAB1D2C828AAAA1D00DAE764 /* ModelViewController.swift */, + EAB1D2CA28AAB9E200DAE764 /* TemplateViewController.swift */, ); path = ViewControllers; sourceTree = ""; @@ -359,9 +365,11 @@ EA3C3BB628996775000CA526 /* MenuViewController.swift in Sources */, EA3C3B9D289966EF000CA526 /* AppDelegate.swift in Sources */, EAF7F11A28A14A0E00B287F5 /* RadioButtonViewController.swift in Sources */, + EAB1D2CB28AAB9E200DAE764 /* TemplateViewController.swift in Sources */, EA3C3B9F289966EF000CA526 /* SceneDelegate.swift in Sources */, EA3C3BB428996775000CA526 /* PickerBase.swift in Sources */, EAB1D2C528A6B11D00DAE764 /* TestViewController.swift in Sources */, + EAB1D2C928AAAA1D00DAE764 /* ModelViewController.swift in Sources */, EAF7F09C2899B92400B287F5 /* CheckboxViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/VDSSample/ViewControllers/ModelViewController.swift b/VDSSample/ViewControllers/ModelViewController.swift new file mode 100644 index 0000000..244c784 --- /dev/null +++ b/VDSSample/ViewControllers/ModelViewController.swift @@ -0,0 +1,93 @@ +// +// ModelViewController.swift +// VDSSample +// +// Created by Matt Bruce on 8/15/22. +// + +import Foundation +import UIKit +import Combine +import VDS + +public class ModelViewController: UIViewController { + deinit { + print("\(Self.self) deinit") + } + + //-------------------------------------------------- + // MARK: - Combine Properties + //-------------------------------------------------- + public var model = CurrentValueSubject(ModelType()) + public var subscribers = Set() + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + private var initialSetupPerformed = false + + @Proxy(\.model.value.surface) + open var surface: Surface + + @Proxy(\.model.value.disabled) + open var disabled: Bool + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + required public init() { + super.init(nibName: nil, bundle: nil) + initialSetup() + } + + public required init(with model: ModelType) { + super.init(nibName: nil, bundle: nil) + initialSetup() + set(with: model) + } + + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nil, bundle: nil) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + //-------------------------------------------------- + // MARK: - Setup + //-------------------------------------------------- + + public func initialSetup() { + if !initialSetupPerformed { + initialSetupPerformed = true + model + .filter { [weak self] viewModel in + return self?.shouldUpdateView(viewModel: viewModel) ?? false + + } + .debounce(for: .seconds(Constants.ModelStateDebounce), scheduler: RunLoop.main) + .sink { [weak self] viewModel in + self?.updateView() + + } + .store(in: &subscribers) + setup() + } + } + + open func setup() {} + + open func shouldUpdateView(viewModel: ModelType) -> Bool { true } + + open func updateView() {} + + open func set(with model: ModelType) { + if shouldUpdateView(viewModel: model){ + self.model.send(model) + } + } + +} diff --git a/VDSSample/ViewControllers/TemplateViewController.swift b/VDSSample/ViewControllers/TemplateViewController.swift new file mode 100644 index 0000000..b3ae02d --- /dev/null +++ b/VDSSample/ViewControllers/TemplateViewController.swift @@ -0,0 +1,123 @@ +// +// TemplateViewController.swift +// VDSSample +// +// Created by Matt Bruce on 8/15/22. +// + +import Foundation +import UIKit +import VDS +import VDSColorTokens +import Combine + +struct TestLayoutModel: Modelable { + var surface: VDS.Surface = .light + var disabled: Bool = false +// var molecules : [any Modelable] = [] + var checkbox: DefaultCheckboxModel + var radioButtonGroup: DefaultRadioButtonGroupModel + + init(){ + //add the checkbox + checkbox = DefaultCheckboxModel() + checkbox.labelText = "Terms and conditions" + checkbox.childText = "I agree to Verizon's terms and conditions click here" + checkbox.childTextAttributes = [ + LabelAttributeUnderline(location: 11, length: 10), + LabelAttributeStrikeThrough(location: 22, length: 5), + LabelAttributeColor(location: 31, length: 10, color: UIColor.blue.hexString!), + LabelAttributeActionModel(location: 31, length: 10){ print("clicked on the word 'conditions'") }, + LabelAttributeFont(location: 2, length: 5, style: .BoldTitleLarge, color: UIColor.red.hexString!) + ] + checkbox.errorText = "Error Text" + + //add the radio + radioButtonGroup = DefaultRadioButtonGroupModel() + var radio1 = DefaultRadioButtonModel() + radio1.value = "model 1 Value" + radio1.labelText = "Terms and conditions" + radio1.childText = "I agree to Verizon's terms and conditions click here" + radio1.childTextAttributes = [ + LabelAttributeUnderline(location: 11, length: 10), + LabelAttributeStrikeThrough(location: 22, length: 5), + LabelAttributeColor(location: 31, length: 10, color: UIColor.blue.hexString!), + LabelAttributeActionModel(location: 31, length: 10){ print("clicked on the word 'conditions'") }, + LabelAttributeFont(location: 2, length: 5, style: .BoldTitleLarge, color: UIColor.red.hexString!) + ] + + var radio2 = DefaultRadioButtonModel() + radio2.value = "model 2 Value" + radio2.childText = "Radio Sample 2" + radioButtonGroup.selectors = [radio1, radio2] + + } +} + +class TemplateViewController: ModelViewController, Initable { + enum ModelHandlerError: Error { + case cantFind + } + + var stackView = UIStackView() + var radioButtonGroup = RadioButtonGroup() + var checkbox = Checkbox() + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = .white + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.spacing = 10 + stackView.axis = .vertical + stackView.alignment = .top + + view.addSubview(stackView) + stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10).isActive = true + stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true + stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true + stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 10).isActive = true + +// //CurrentValueSubject +// let checkSubject = CurrentValueSubject(model.value.checkbox) +// checkbox.createBinding(with: checkSubject, storeIn: &subscribers) +// checkSubject.sink { [weak self] checkModel in +// self?.model.value.checkbox = checkModel +// }.store(in: &subscribers) +// stackView.addArrangedSubview(checkbox) +// +// let radioSubject = CurrentValueSubject(model.value.radioButtonGroup) +// radioButtonGroup.createBinding(with: radioSubject, storeIn: &subscribers) +// radioSubject.sink { [weak self] radioGroupModel in +// self?.model.value.radioButtonGroup = radioGroupModel +// }.store(in: &subscribers) +// stackView.addArrangedSubview(radioButtonGroup) + + //Publisher way + checkbox.handlerPublisher() + .sink { [weak self] checkModel in + self?.model.value.checkbox = checkModel + } + .store(in: &subscribers) + stackView.addArrangedSubview(checkbox) + + radioButtonGroup.handlerPublisher() + .sink { [weak self] radioGroupModel in + self?.model.value.radioButtonGroup = radioGroupModel + } + .store(in: &subscribers) + stackView.addArrangedSubview(radioButtonGroup) + + checkbox.set(with: model.value.checkbox) + radioButtonGroup.set(with: model.value.radioButtonGroup) + + } + + override func updateView() { + print("updateView Called") + checkbox.set(with: model.value.checkbox) + radioButtonGroup.set(with: model.value.radioButtonGroup) + + print("radioButtonGroup selected: \(radioButtonGroup.selectedModel?.id)") + print("model.value.radioButtonGroup selected: \(model.value.radioButtonGroup.selectedModel?.id)") + } +}