latest state of updates

This commit is contained in:
Kevin G Christiano 2020-04-13 14:25:52 -04:00
parent bcb296fa5d
commit 98e4f3d621
11 changed files with 92 additions and 110 deletions

View File

@ -32,9 +32,7 @@ import UIKit
}() }()
public var dateFormat: String = "MMM d, y" { public var dateFormat: String = "MMM d, y" {
didSet { didSet { dateFormatter.dateFormat = dateFormat }
dateFormatter.dateFormat = dateFormat
}
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -33,7 +33,10 @@
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
if let dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) {
self.dateFormat = dateFormat
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {

View File

@ -246,15 +246,6 @@ import UIKit
} }
} }
@objc public override func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count
}
}
@objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) { @objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectPreviousField = false var selectPreviousField = false

View File

@ -36,8 +36,14 @@
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) ?? 4
secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) ?? false if let digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) {
self.digits = digits
}
if let secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) {
self.secureEntry = secureEntry
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {

View File

@ -20,7 +20,7 @@ import UIKit
public private(set) var titleLabel: Label = { public private(set) var titleLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontRegularMicro() label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical) label.setContentCompressionResistancePriority(.required, for: .vertical)
return label return label
@ -31,7 +31,7 @@ import UIKit
/// Provides contextual information on the TextField. /// Provides contextual information on the TextField.
public private(set) var feedbackLabel: Label = { public private(set) var feedbackLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontRegularMicro() label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical) label.setContentCompressionResistancePriority(.required, for: .vertical)
return label return label
@ -174,8 +174,6 @@ import UIKit
@objc final public override func setupView() { @objc final public override func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return }
isAccessibilityElement = false isAccessibilityElement = false
setContentCompressionResistancePriority(.required, for: .vertical) setContentCompressionResistancePriority(.required, for: .vertical)
accessibilityElements = [titleLabel, feedbackLabel] accessibilityElements = [titleLabel, feedbackLabel]
@ -258,13 +256,13 @@ import UIKit
title = model.title title = model.title
feedback = model.feedback feedback = model.feedback
errorMessage = model.errorMessage errorMessage = model.errorMessage
isEnabled = model.isEnabled isEnabled = model.enabled
if let isLocked = model.isLocked { if let isLocked = model.locked {
self.isLocked = isLocked self.isLocked = isLocked
} else if let isSelected = model.isSelected{ } else if let selected = model.selected {
self.isSelected = isSelected self.isSelected = selected
} }
} }

View File

@ -9,8 +9,8 @@
import Foundation import Foundation
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol { @objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -20,31 +20,24 @@ import Foundation
} }
public var backgroundColor: Color? public var backgroundColor: Color?
public var title: String? public var title: String = ""
public var feedback: String? public var feedback: String?
public var errorMessage: String = "" public var errorMessage: String = ""
public var isEnabled: Bool = true public var enabled: Bool = true
public var isLocked: Bool? public var locked: Bool?
public var isSelected: Bool? public var selected: Bool?
public var text: String? public var text: String?
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
public var isValid: Bool? { public var isValid: Bool? {
didSet { didSet { updateUI?() }
updateUI?()
}
} }
/// Temporary binding mechanism for the view to update on enable changes. /// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: (() -> Void)? public var updateUI: (() -> ())?
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
@ -52,23 +45,29 @@ import Foundation
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case title = "label" case title
case isEnabled case enabled
case feedback case feedback
case errorMessage = "errorMsg" case errorMessage
case isLocked case locked
case isSelected case selected
case isValid
case isRequired = "required"
case text case text
case fieldKey case fieldKey
case groupName case groupName
} }
//--------------------------------------------------
// MARK: - Validation Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { public func formFieldValue() -> AnyHashable? {
return text return text
} }
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -81,20 +80,26 @@ import Foundation
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? ""
isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true
isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked)
isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected)
isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
if let title = try typeContainer.decodeIfPresent(String.self, forKey: .title) {
self.title = title
}
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
if let errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) {
self.errorMessage = errorMessage
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
baseValue = text baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -103,13 +108,11 @@ import Foundation
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(title, forKey: .title)
try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(feedback, forKey: .feedback)
try container.encode(errorMessage, forKey: .errorMessage)
try container.encode(isEnabled, forKey: .isEnabled)
try container.encode(isLocked, forKey: .isLocked)
try container.encode(isSelected, forKey: .isSelected)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(isValid, forKey: .isValid)
try container.encodeIfPresent(text, forKey: .text) try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(locked, forKey: .locked)
try container.encodeIfPresent(selected, forKey: .selected)
try container.encode(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled)
} }
} }

View File

@ -35,8 +35,14 @@
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
options = try typeContainer.decode([String].self, forKey: .options)
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0 if let options = try typeContainer.decodeIfPresent([String].self, forKey: .options) {
self.options = options
}
if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
self.selectedIndex = selectedIndex
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {

View File

@ -107,18 +107,18 @@ import MVMCore
isValid = true isValid = true
return true return true
} }
let isValid = hasValidMDN() let isValid = hasValidMDN()
if isValid { if isValid {
showError = false showError = false
} else { } else {
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
showError = true showError = true
UIAccessibility.post(notification: .layoutChanged, argument: textField) UIAccessibility.post(notification: .layoutChanged, argument: textField)
} }
return isValid return isValid
} }
@ -196,7 +196,7 @@ import MVMCore
} }
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
} }

View File

@ -37,9 +37,7 @@ import UIKit
}() }()
public var accessoryView: View? { public var accessoryView: View? {
didSet { didSet { accessoryView == nil ? removeAccessoryView() : constrainAccessoryView() }
accessoryView == nil ? removeAccessoryView() : constrainAccessoryView()
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -108,12 +106,6 @@ import UIKit
set { textField.placeholder = newValue } set { textField.placeholder = newValue }
} }
//--------------------------------------------------
// MARK: - Property Observers
//--------------------------------------------------
public var validationBlock: ((_ value: String?) -> Bool)?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate Properties // MARK: - Delegate Properties
//-------------------------------------------------- //--------------------------------------------------
@ -155,9 +147,11 @@ import UIKit
textFieldTrailingConstraint = accessoryView?.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two) textFieldTrailingConstraint = accessoryView?.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
textFieldTrailingConstraint?.isActive = true textFieldTrailingConstraint?.isActive = true
accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView!.trailingAnchor, constant: Padding.Four) if let accessoryView = accessoryView {
accessoryViewTrailingConstraint?.isActive = true accessoryViewTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: accessoryView.trailingAnchor, constant: Padding.Four)
accessoryView?.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true accessoryViewTrailingConstraint?.isActive = true
accessoryView.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true
}
} }
public func removeAccessoryView() { public func removeAccessoryView() {
@ -242,15 +236,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Observing for Change (TextFieldDelegate) // MARK: - Observing for Change (TextFieldDelegate)
//-------------------------------------------------- //--------------------------------------------------
public func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0
}
}
@discardableResult @discardableResult
@objc override open func resignFirstResponder() -> Bool { @objc override open func resignFirstResponder() -> Bool {
if validateWhenDoneEditing { if validateWhenDoneEditing {
@ -317,11 +303,14 @@ import UIKit
model.updateUI = { [weak self] in model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: { MVMCoreDispatchUtility.performBlock(onMainThread: {
if self?.isSelected ?? false { guard let self = self else { return }
self?.updateValidation(model.isValid ?? true)
if self.isSelected {
self.updateValidation(model.isValid ?? true)
} }
}) })
} }
self.delegateObject = delegateObject self.delegateObject = delegateObject
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
textColor.enabled = model.enabledTextColor?.uiColor textColor.enabled = model.enabledTextColor?.uiColor
@ -343,15 +332,6 @@ import UIKit
break break
} }
if let regex = model.regex, !regex.isEmpty {
validationBlock = { enteredValue in
guard let value = enteredValue else { return false }
return MVMCoreUIUtility.validate(value, withRegularExpression: regex)
}
} else {
defaultValidationBlock()
}
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self) textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self)

View File

@ -8,6 +8,9 @@
@objcMembers public class TextEntryFieldModel: EntryFieldModel { @objcMembers public class TextEntryFieldModel: EntryFieldModel {
//--------------------------------------------------
// MARK: - Types
//--------------------------------------------------
public enum EntryType: String, Codable { public enum EntryType: String, Codable {
case password case password
@ -27,7 +30,6 @@
public var enabledTextColor: Color? public var enabledTextColor: Color?
public var disabledTextColor: Color? public var disabledTextColor: Color?
public var type: EntryType? public var type: EntryType?
public var regex: String?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
@ -40,7 +42,6 @@
case enabledTextColor case enabledTextColor
case disabledTextColor case disabledTextColor
case type case type
case regex
} }
//-------------------------------------------------- //--------------------------------------------------
@ -55,7 +56,6 @@
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
regex = try typeContainer.decodeIfPresent(String.self, forKey: .regex)
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -67,6 +67,5 @@
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(type, forKey: .type) try container.encodeIfPresent(type, forKey: .type)
try container.encodeIfPresent(regex, forKey: .regex)
} }
} }

View File

@ -25,9 +25,7 @@ import UIKit
/// Total control over the drawn top, bottom, left and right borders. /// Total control over the drawn top, bottom, left and right borders.
public var disableAllBorders = false { public var disableAllBorders = false {
didSet { didSet { bottomBar?.isHidden = disableAllBorders }
bottomBar?.isHidden = disableAllBorders
}
} }
private(set) var fieldState: FieldState = .original { private(set) var fieldState: FieldState = .original {