Merge branch 'develop' into feature/accessibilityHandler
This commit is contained in:
commit
8ca636aa23
@ -291,6 +291,7 @@
|
||||
AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */; };
|
||||
AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509629E477C0009DC2AD /* AlertHandler.swift */; };
|
||||
AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509729E477C0009DC2AD /* AlertController.swift */; };
|
||||
AF8118302AB39B0900FAD1BA /* RawRepresentableCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */; };
|
||||
AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931F29E5CA73001A9663 /* AlertOperation.swift */; };
|
||||
AFA4932229E5EF2E001A9663 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */; };
|
||||
AFA4933F29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */; };
|
||||
@ -589,6 +590,7 @@
|
||||
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
|
||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
|
||||
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
|
||||
EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */; };
|
||||
FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -879,6 +881,7 @@
|
||||
AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAccessibilityTraits+Codable.swift"; sourceTree = "<group>"; };
|
||||
AF7E509629E477C0009DC2AD /* AlertHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertHandler.swift; sourceTree = "<group>"; };
|
||||
AF7E509729E477C0009DC2AD /* AlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertController.swift; sourceTree = "<group>"; };
|
||||
AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawRepresentableCodable.swift; sourceTree = "<group>"; };
|
||||
AFA4931F29E5CA73001A9663 /* AlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertOperation.swift; sourceTree = "<group>"; };
|
||||
AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = "<group>"; };
|
||||
AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingDelegateProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1178,6 +1181,7 @@
|
||||
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
|
||||
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
|
||||
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
|
||||
EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VDS-Interpreters.swift"; sourceTree = "<group>"; };
|
||||
FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -2166,6 +2170,7 @@
|
||||
D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */,
|
||||
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */,
|
||||
0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */,
|
||||
AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */,
|
||||
);
|
||||
path = Utility;
|
||||
sourceTree = "<group>";
|
||||
@ -2429,6 +2434,7 @@
|
||||
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
||||
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */,
|
||||
EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */,
|
||||
EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
@ -2760,6 +2766,7 @@
|
||||
0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */,
|
||||
012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */,
|
||||
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */,
|
||||
AF8118302AB39B0900FAD1BA /* RawRepresentableCodable.swift in Sources */,
|
||||
94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */,
|
||||
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */,
|
||||
52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */,
|
||||
@ -2987,6 +2994,7 @@
|
||||
D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */,
|
||||
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
|
||||
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */,
|
||||
EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */,
|
||||
C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */,
|
||||
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */,
|
||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */,
|
||||
|
||||
@ -8,10 +8,11 @@
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDS
|
||||
import MVMCore
|
||||
|
||||
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
|
||||
|
||||
|
||||
open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
@ -26,13 +27,13 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
public var action: ActionModelProtocol
|
||||
public var enabled: Bool = true
|
||||
public var width: CGFloat?
|
||||
public var style: Styler.Button.Style? {
|
||||
public var style: Use? {
|
||||
didSet {
|
||||
guard let style = style else { return }
|
||||
setFacade(by: style)
|
||||
}
|
||||
}
|
||||
public var size: Styler.Button.Size? = .standard
|
||||
public var size: VDS.Button.Size = .large
|
||||
public var groupName: String = ""
|
||||
public var inverted: Bool = false
|
||||
|
||||
@ -160,14 +161,14 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
|
||||
}
|
||||
|
||||
public func setFacade(by style: Styler.Button.Style) {
|
||||
|
||||
public func setFacade(by style: VDS.Use) {
|
||||
switch style {
|
||||
case .primary:
|
||||
setPrimaryFacade()
|
||||
|
||||
case .secondary:
|
||||
setSecondaryFacade()
|
||||
@unknown default:
|
||||
setPrimaryFacade()
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,17 +212,17 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
action = try typeContainer.decodeModel(codingKey: .action)
|
||||
|
||||
///Style captured from the JSON
|
||||
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style){
|
||||
if let style = try typeContainer.decodeIfPresent(Use.self, forKey: .style) {
|
||||
self.style = style
|
||||
setFacade(by: style)
|
||||
} else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Styler.Button.Style { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
|
||||
} else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Use { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
|
||||
self.style = style
|
||||
setFacade(by: style)
|
||||
} else { ///Default style
|
||||
setFacade(by: .primary)
|
||||
}
|
||||
|
||||
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) {
|
||||
if let size = try typeContainer.decodeIfPresent(VDS.Button.Size.self, forKey: .size) {
|
||||
self.size = size
|
||||
}
|
||||
|
||||
|
||||
@ -11,30 +11,26 @@ import UIKit
|
||||
|
||||
open class ExternalLink: Link {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var exportImageView: UIImageView?
|
||||
|
||||
open var exportImageView: UIImageView?
|
||||
open var exportImageHeight: NSLayoutConstraint?
|
||||
open var exportImageWidth: NSLayoutConstraint?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? ExternalLinkModel else { return }
|
||||
|
||||
exportImageView?.tintColor = titleColor(for: model.enabled ? .normal : .disabled)
|
||||
open override func viewModelDidUpdate() {
|
||||
super.viewModelDidUpdate()
|
||||
exportImageView?.tintColor = textColor
|
||||
exportImageWidth?.constant = textStyle.lineHeight
|
||||
exportImageHeight?.constant = textStyle.lineHeight
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
open override func setup() {
|
||||
super.setup()
|
||||
contentHorizontalAlignment = .left
|
||||
|
||||
let image = MVMCoreUIUtility.imageNamed("externalLink")
|
||||
exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate))
|
||||
|
||||
@ -46,10 +42,10 @@ open class ExternalLink: Link {
|
||||
addSubview(exportIcon)
|
||||
trailingAnchor.constraint(greaterThanOrEqualTo: exportIcon.trailingAnchor).isActive = true
|
||||
|
||||
if let titleLabel = titleLabel {
|
||||
let dimension = titleLabel.font.pointSize
|
||||
exportIcon.heightAnchor.constraint(equalToConstant: dimension).isActive = true
|
||||
exportIcon.widthAnchor.constraint(equalToConstant: dimension).isActive = true
|
||||
exportImageHeight = exportIcon.heightAnchor.constraint(equalToConstant: textStyle.pointSize).activate()
|
||||
exportImageWidth = exportIcon.widthAnchor.constraint(equalToConstant: textStyle.pointSize).activate()
|
||||
|
||||
if let titleLabel {
|
||||
exportIcon.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4).isActive = true
|
||||
exportIcon.bottomAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor, constant: 3).isActive = true
|
||||
}
|
||||
|
||||
@ -8,83 +8,59 @@
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDS
|
||||
|
||||
open class Link: VDS.TextLink, VDSMoleculeViewProtocol {
|
||||
|
||||
@objcMembers open class Link: Button {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Draw
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var viewModel: LinkModel!
|
||||
open var delegateObject: MVMCoreUIDelegateObject?
|
||||
open var additionalData: [AnyHashable : Any]?
|
||||
|
||||
open override func draw(_ rect: CGRect) {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Functions
|
||||
//--------------------------------------------------
|
||||
open func viewModelDidUpdate() {
|
||||
isEnabled = viewModel.enabled
|
||||
size = viewModel.size
|
||||
text = viewModel.title
|
||||
surface = viewModel.surface
|
||||
|
||||
guard let textRect = titleLabel?.frame,
|
||||
let context = UIGraphicsGetCurrentContext()
|
||||
else { return }
|
||||
onClick = { [weak self] control in
|
||||
guard let self else { return }
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: self.viewModel.action,
|
||||
sourceModel: self.viewModel,
|
||||
additionalData: self.additionalData,
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
|
||||
// Set line to the same color as the text
|
||||
if let color = titleColor(for: state)?.cgColor {
|
||||
context.setStrokeColor(color)
|
||||
guard let viewModel = viewModel else { return }
|
||||
if let accessibilityText = viewModel.accessibilityText {
|
||||
self.accessibilityLabel = accessibilityText
|
||||
}
|
||||
|
||||
// x should be according to the text, not the button
|
||||
let x = textRect.origin.x
|
||||
|
||||
// Line is 0 point below the text
|
||||
let y = textRect.origin.y + textRect.size.height
|
||||
|
||||
context.move(to: CGPoint(x: x, y: y))
|
||||
context.addLine(to: CGPoint(x: x + textRect.size.width, y: y))
|
||||
context.strokePath()
|
||||
}
|
||||
|
||||
open override var intrinsicContentSize: CGSize {
|
||||
guard let size = titleLabel?.intrinsicContentSize else { return super.intrinsicContentSize }
|
||||
return CGSize(width: size.width, height: size.height + 1)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? LinkModel else { return }
|
||||
|
||||
setTitle(model.title, for: .normal)
|
||||
if let accessibilityText = model.accessibilityText {
|
||||
accessibilityLabel = accessibilityText
|
||||
if let accessibilityIdentifier = viewModel.accessibilityIdentifier {
|
||||
self.accessibilityIdentifier = accessibilityIdentifier
|
||||
}
|
||||
setTitleColor((model.inverted ? model.enabledColor_inverted : model.enabledColor).uiColor, for: .normal)
|
||||
setTitleColor((model.inverted ? model.disabledColor_inverted : model.disabledColor).uiColor, for: .disabled)
|
||||
setTitleColor((model.inverted ? model.activeColor_inverted : model.activeColor).uiColor, for: .highlighted)
|
||||
isEnabled = model.enabled
|
||||
titleLabel?.font = model.getFont(model.size)
|
||||
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 }
|
||||
}
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 }
|
||||
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
extension Link {
|
||||
open func updateView(_ size: CGFloat) { }
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
backgroundColor = .clear
|
||||
contentMode = .redraw
|
||||
setTitleColor(VDSColor.elementsPrimaryOnlight, for: .normal)
|
||||
setTitleColor(VDSColor.interactiveDisabledOnlight, for: .disabled)
|
||||
setTitleColor(VDSColor.interactiveActiveOnlight, for: .highlighted)
|
||||
titleLabel?.numberOfLines = 1
|
||||
titleLabel?.lineBreakMode = .byTruncatingTail
|
||||
titleLabel?.textAlignment = .left
|
||||
contentHorizontalAlignment = .left
|
||||
contentVerticalAlignment = .top
|
||||
}
|
||||
open func setupView() {}
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIViewConstrainingProtocol
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDS
|
||||
|
||||
open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
@ -23,15 +23,9 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
public var accessibilityText: String?
|
||||
public var action: ActionModelProtocol
|
||||
public var enabled = true
|
||||
public var enabledColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
public var enabledColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
public var disabledColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
|
||||
public var disabledColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
|
||||
public var activeColor = Color(uiColor: VDSColor.interactiveActiveOnlight)
|
||||
public var activeColor_inverted = Color(uiColor: VDSColor.interactiveActiveOndark)
|
||||
|
||||
public var inverted = false
|
||||
public var size:linkFontSize = linkFontSize.small
|
||||
public var size: TextLink.Size = .small
|
||||
|
||||
public var shouldMaskRecordedView: Bool? = false
|
||||
|
||||
@ -57,34 +51,10 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
case title
|
||||
case action
|
||||
case enabled
|
||||
case enabledColor
|
||||
case enabledColor_inverted
|
||||
case disabledColor
|
||||
case disabledColor_inverted
|
||||
case activeColor
|
||||
case activeColor_inverted
|
||||
case inverted
|
||||
case size
|
||||
case shouldMaskRecordedView
|
||||
}
|
||||
|
||||
public enum linkFontSize: String, Codable {
|
||||
case small
|
||||
case large
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Method
|
||||
//--------------------------------------------------
|
||||
|
||||
func getFont(_ type: linkFontSize) -> UIFont {
|
||||
switch type {
|
||||
case .small:
|
||||
return MFStyler.fontRegularBodySmall()
|
||||
case .large:
|
||||
return MFStyler.fontRegularBodyLarge()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
@ -108,30 +78,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
self.inverted = inverted
|
||||
}
|
||||
|
||||
if let enabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) {
|
||||
self.enabledColor = enabledColor
|
||||
}
|
||||
|
||||
if let enabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor_inverted) {
|
||||
self.enabledColor_inverted = enabledColor_inverted
|
||||
}
|
||||
|
||||
if let disabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) {
|
||||
self.disabledColor = disabledColor
|
||||
}
|
||||
|
||||
if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) {
|
||||
self.disabledColor_inverted = disabledColor_inverted
|
||||
}
|
||||
|
||||
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
|
||||
self.activeColor = activeColor
|
||||
}
|
||||
|
||||
if let activeColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor_inverted) {
|
||||
self.activeColor_inverted = activeColor_inverted
|
||||
}
|
||||
if let size = try typeContainer.decodeIfPresent(linkFontSize.self, forKey: .size) {
|
||||
if let size = try typeContainer.decodeIfPresent(TextLink.Size.self, forKey: .size) {
|
||||
self.size = size
|
||||
}
|
||||
|
||||
@ -148,13 +95,11 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(enabledColor, forKey: .enabledColor)
|
||||
try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted)
|
||||
try container.encode(disabledColor, forKey: .disabledColor)
|
||||
try container.encode(disabledColor_inverted, forKey: .disabledColor_inverted)
|
||||
try container.encode(activeColor, forKey: .activeColor)
|
||||
try container.encode(activeColor_inverted, forKey: .activeColor_inverted)
|
||||
try container.encodeIfPresent(size, forKey: .size)
|
||||
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||
}
|
||||
}
|
||||
|
||||
extension LinkModel {
|
||||
public var surface: Surface { inverted ? .dark : .light }
|
||||
}
|
||||
|
||||
@ -8,223 +8,68 @@
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDS
|
||||
import MVMCore
|
||||
import Combine
|
||||
|
||||
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
|
||||
open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol, VDSMoleculeViewProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Used to size the button.
|
||||
var size = MVMCoreUIUtility.getWidth()
|
||||
|
||||
var buttonModel: ButtonModel? {
|
||||
get { model as? ButtonModel }
|
||||
}
|
||||
|
||||
/// Need to re-style on set.
|
||||
open override var isEnabled: Bool {
|
||||
didSet { style(with: buttonModel) }
|
||||
}
|
||||
|
||||
open var buttonSize: Styler.Button.Size = .standard {
|
||||
didSet { buttonModel?.size = buttonSize }
|
||||
}
|
||||
open var viewModel: ButtonModel!
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
public var additionalData: [AnyHashable: Any]?
|
||||
|
||||
internal var onClickCancellable: Cancellable?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
// MARK: - VDSMoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
public var widthConstraint: NSLayoutConstraint?
|
||||
public var minimumWidthConstraint: NSLayoutConstraint?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
@objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) {
|
||||
let model = ButtonModel(with: "", action: ActionNoopModel())
|
||||
model.style = isPrimary ? .primary : .secondary
|
||||
model.size = istiny ? .tiny : .standard
|
||||
self.init(model: model, nil, nil)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var enabledTitleColor: UIColor? {
|
||||
get { titleColor(for: .normal) }
|
||||
set { setTitleColor(newValue, for: .normal) }
|
||||
}
|
||||
|
||||
public var disabledTitleColor: UIColor? {
|
||||
get { titleColor(for: .disabled) }
|
||||
set { setTitleColor(newValue, for: .disabled) }
|
||||
}
|
||||
|
||||
public var borderColor: UIColor? {
|
||||
get {
|
||||
guard let currentColor = layer.borderColor else { return nil }
|
||||
return UIColor(cgColor: currentColor)
|
||||
}
|
||||
set { layer.borderColor = newValue?.cgColor }
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
/// The primary styling for a button. Should be used for main buttons
|
||||
public func stylePrimary() {
|
||||
let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel())
|
||||
style(with: buttonModel)
|
||||
}
|
||||
|
||||
/// The secondary styling for a button. Should be used for secondary buttons
|
||||
public func styleSecondary() {
|
||||
let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel())
|
||||
style(with: buttonModel)
|
||||
}
|
||||
|
||||
/// Styles the button based on the model style
|
||||
private func style(with model: ButtonModel?) {
|
||||
|
||||
layer.borderWidth = model?.style == .secondary ? 1 : 0
|
||||
|
||||
if let titleColor = model?.enabledColors.text {
|
||||
enabledTitleColor = titleColor
|
||||
open func viewModelDidUpdate() {
|
||||
if let accessibilityIdentifier = viewModel.accessibilityIdentifier {
|
||||
self.accessibilityIdentifier = accessibilityIdentifier
|
||||
}
|
||||
|
||||
if let disabledTitleColor = model?.disabledColors.text {
|
||||
self.disabledTitleColor = disabledTitleColor
|
||||
text = viewModel.title
|
||||
isEnabled = viewModel.enabled
|
||||
size = viewModel.size
|
||||
use = viewModel.style ?? .primary
|
||||
surface = viewModel.inverted ? .dark : .light
|
||||
if let accessibilityText = viewModel.accessibilityText {
|
||||
accessibilityLabel = accessibilityText
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
// Useful to detect with isHittable when performing UI testing.
|
||||
isAccessibilityElement = isEnabled
|
||||
#endif
|
||||
|
||||
if isEnabled {
|
||||
if let fillColor = model?.enabledColors.fill {
|
||||
backgroundColor = fillColor
|
||||
}
|
||||
|
||||
if let borderColor = model?.enabledColors.border {
|
||||
self.borderColor = borderColor
|
||||
}
|
||||
} else {
|
||||
if let fillColor = model?.disabledColors.fill {
|
||||
backgroundColor = fillColor
|
||||
}
|
||||
|
||||
if let borderColor = model?.disabledColors.border {
|
||||
self.borderColor = borderColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func getInnerPadding() -> CGFloat {
|
||||
buttonSize.getHeight() / 2.0
|
||||
}
|
||||
set(with: viewModel.action, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
private func getContentEdgeInsets() -> UIEdgeInsets {
|
||||
var verticalPadding = 0.0
|
||||
var horizontalPadding = 0.0
|
||||
switch buttonSize {
|
||||
case .standard:
|
||||
verticalPadding = Padding.Three
|
||||
horizontalPadding = Padding.Five
|
||||
break
|
||||
case .small:
|
||||
verticalPadding = Padding.Two
|
||||
horizontalPadding = Padding.Four
|
||||
break
|
||||
case .tiny:
|
||||
verticalPadding = Padding.One
|
||||
horizontalPadding = Padding.Two
|
||||
break
|
||||
viewModel.updateUI = { [weak self] in
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
guard let self = self else { return }
|
||||
self.isEnabled = self.viewModel.enabled
|
||||
})
|
||||
}
|
||||
return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
|
||||
|
||||
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
// The button will get styled in the enable check in super.
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? ButtonModel else { return }
|
||||
|
||||
setTitle(model.title, for: .normal)
|
||||
if let accessibilityText = model.accessibilityText {
|
||||
accessibilityLabel = accessibilityText
|
||||
}
|
||||
|
||||
if let size = model.size {
|
||||
buttonSize = size
|
||||
}
|
||||
|
||||
model.updateUI = { [weak self] in
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
self?.enableField(model.enabled)
|
||||
})
|
||||
}
|
||||
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return (model as? ButtonModel)?.size.height
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return (model as? ButtonModel)?.size?.getHeight()
|
||||
open func updateView(_ size: CGFloat) {}
|
||||
|
||||
open override func setup() {
|
||||
super.setup()
|
||||
setupView()
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
self.size = size
|
||||
|
||||
switch buttonSize {
|
||||
case .tiny:
|
||||
titleLabel?.font = Styler.Font.BoldMicro.getFont(false)
|
||||
case .small:
|
||||
titleLabel?.font = Styler.Font.BoldBodySmall.getFont(false)
|
||||
case .standard:
|
||||
titleLabel?.font = Styler.Font.BoldBodyLarge.getFont(false)
|
||||
}
|
||||
|
||||
layer.cornerRadius = getInnerPadding()
|
||||
contentEdgeInsets = getContentEdgeInsets()
|
||||
|
||||
if let contraint = buttonModel?.width {
|
||||
|
||||
if widthConstraint == nil {
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: contraint)
|
||||
} else if widthConstraint?.constant != contraint {
|
||||
widthConstraint?.constant = contraint
|
||||
}
|
||||
widthConstraint?.isActive = true
|
||||
minimumWidthConstraint?.isActive = false
|
||||
} else {
|
||||
|
||||
if minimumWidthConstraint == nil {
|
||||
minimumWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: buttonSize.minimumWidth())
|
||||
} else {
|
||||
minimumWidthConstraint?.constant = buttonSize.minimumWidth()
|
||||
}
|
||||
minimumWidthConstraint?.isActive = true
|
||||
widthConstraint?.isActive = false
|
||||
}
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
titleLabel?.numberOfLines = 1
|
||||
titleLabel?.lineBreakMode = .byTruncatingTail
|
||||
titleLabel?.textAlignment = .center
|
||||
contentHorizontalAlignment = .center
|
||||
stylePrimary()
|
||||
}
|
||||
open func setupView() {}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreUIViewConstrainingProtocol
|
||||
@ -232,7 +77,21 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
open func horizontalAlignment() -> UIStackView.Alignment { .center }
|
||||
|
||||
public func enableField(_ enable: Bool) {
|
||||
isEnabled = enable
|
||||
//--------------------------------------------------
|
||||
// MARK: - Action
|
||||
//--------------------------------------------------
|
||||
|
||||
open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
onClick = { [weak self] control in
|
||||
guard let self = self, let viewModel = self.viewModel else { return }
|
||||
Task(priority: .userInitiated) {
|
||||
try await Self.performButtonAction(with: viewModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws {
|
||||
guard delegateObject?.buttonDelegate?.button?(button, shouldPerformActionWithMap: model.toJSON(), additionalData: additionalData) ?? true else { return }
|
||||
try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: model, additionalData: MVMCoreUIActionHandler.add(sourceModel: sourceModel, to: additionalData), delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,116 +7,112 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDS
|
||||
|
||||
|
||||
@objcMembers open class Line: View {
|
||||
@objcMembers open class Line: VDS.Line, VDSMoleculeViewProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
open var viewModel: LineModel!
|
||||
open var delegateObject: MVMCoreUIDelegateObject?
|
||||
open var additionalData: [AnyHashable : Any]?
|
||||
|
||||
var lineModel: LineModel? {
|
||||
get { return model as? LineModel }
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
|
||||
public var heightConstraint: NSLayoutConstraint?
|
||||
public var widthConstraint: NSLayoutConstraint?
|
||||
|
||||
open func updateLineConstraints(constant: CGFloat) {
|
||||
if let useVerticalLine = lineModel?.useVerticalLine, useVerticalLine {
|
||||
heightConstraint?.isActive = false
|
||||
widthConstraint?.isActive = true
|
||||
widthConstraint?.constant = constant
|
||||
} else {
|
||||
widthConstraint?.isActive = false
|
||||
heightConstraint?.isActive = true
|
||||
heightConstraint?.constant = constant
|
||||
open override var orientation: Line.Orientation {
|
||||
didSet {
|
||||
if orientation == .horizontal {
|
||||
setContentHuggingPriority(.defaultLow, for: .horizontal)
|
||||
setContentHuggingPriority(.required, for: .vertical)
|
||||
setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
} else {
|
||||
setContentHuggingPriority(.required, for: .horizontal)
|
||||
setContentHuggingPriority(.defaultLow, for: .vertical)
|
||||
setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
setContentCompressionResistancePriority(.defaultLow, for: .vertical)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
//--------------------------------------------------
|
||||
public convenience init(pinTo view: UIView, edge: UIRectEdge, useMargin: Bool) {
|
||||
self.init(frame: .zero)
|
||||
addLine(to: view, edge: edge, useMargin: useMargin)
|
||||
}
|
||||
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
model = LineModel(type: .secondary)
|
||||
setStyle(.secondary)
|
||||
public required init() {
|
||||
super.init()
|
||||
viewModel = LineModel(type: .secondary)
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
model = LineModel(type: .secondary)
|
||||
setStyle(.secondary)
|
||||
viewModel = LineModel(type: .secondary)
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
model = LineModel(type: .secondary)
|
||||
setStyle(.secondary)
|
||||
viewModel = LineModel(type: .secondary)
|
||||
}
|
||||
|
||||
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.init(model: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
open func setStyle(_ style: LineModel.Style) {
|
||||
lineModel?.type = style
|
||||
backgroundColor = lineModel?.backgroundColor?.uiColor
|
||||
updateLineConstraints(constant: lineModel?.thickness ?? 1)
|
||||
}
|
||||
|
||||
open func shouldBeVisible() -> Bool {
|
||||
guard let type = lineModel?.type else { return false }
|
||||
guard let type = viewModel?.type else { return false }
|
||||
return type != .none
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
open func setStyle(_ style: LineModel.Style) {
|
||||
viewModel.type = style
|
||||
update(viewModel: viewModel)
|
||||
}
|
||||
|
||||
open func addLine(to view: UIView, edge: UIRectEdge, useMargin: Bool) {
|
||||
view.addSubview(self)
|
||||
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: self, useMargins: useMargin, pinTop: edge != .bottom, pinBottom: edge != .top, pinLeft: edge != .right, pinRight: edge != .left).values))
|
||||
NSLayoutConstraint.activate(
|
||||
Array(
|
||||
NSLayoutConstraint.pinView(toSuperview: self,
|
||||
useMargins: useMargin,
|
||||
pinTop: edge != .bottom,
|
||||
pinBottom: edge != .top,
|
||||
pinLeft: edge != .right,
|
||||
pinRight: edge != .left).values
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
|
||||
heightConstraint?.isActive = true
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
|
||||
widthConstraint?.isActive = false
|
||||
open override func draw(_ rect: CGRect) {
|
||||
guard viewModel.type != .none else { return }
|
||||
super.draw(rect)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
//--------------------------------------------------
|
||||
// MARK: - VDSMoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
open func viewModelDidUpdate() {
|
||||
surface = viewModel.surface
|
||||
style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary
|
||||
orientation = viewModel.orientation
|
||||
}
|
||||
|
||||
if let lineModel = model as? LineModel {
|
||||
setStyle(lineModel.type)
|
||||
}
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
public func updateView(_ size: CGFloat) {
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
setStyle(.secondary)
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return (model as? LineModel)?.thickness ?? 1
|
||||
|
||||
public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreUIViewConstrainingProtocol
|
||||
//--------------------------------------------------
|
||||
extension Line: MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
open func needsToBeConstrained() -> Bool {
|
||||
|
||||
@ -8,8 +8,9 @@
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDS
|
||||
|
||||
@objcMembers public class LineModel: MoleculeModelProtocol {
|
||||
public class LineModel: MoleculeModelProtocol, Invertable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Enums
|
||||
//--------------------------------------------------
|
||||
@ -30,12 +31,12 @@ import VDSColorTokens
|
||||
|
||||
/**
|
||||
The style of the line:
|
||||
- secondary (1 height, silver)
|
||||
- primary (1 height, black)
|
||||
- standard (1 height, silver) - deprecated
|
||||
- thin (1 height, black) - deprecated
|
||||
- medium (2 height, black)
|
||||
- heavy (4 height, black)
|
||||
- secondary (VDS Secondary)
|
||||
- primary (VDS Primary)
|
||||
- standard (VDS Secondary) - deprecated
|
||||
- thin (VDS Primar) - deprecated
|
||||
- medium (VDS Primar)
|
||||
- heavy (VDS Primar)
|
||||
- none (hidden)
|
||||
*/
|
||||
public enum Style: String, Codable {
|
||||
@ -54,53 +55,14 @@ import VDSColorTokens
|
||||
|
||||
public static var identifier: String = "line"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
|
||||
public var type: Style = .secondary
|
||||
public var frequency: Frequency? = .allExceptTop
|
||||
|
||||
//TODO: use color insted of backgroundColor. Needs server changes
|
||||
// public var color: Color?
|
||||
private var _backgroundColor: Color?
|
||||
public var backgroundColor: Color? {
|
||||
get {
|
||||
if let backgroundColor = _backgroundColor { return backgroundColor }
|
||||
if inverted {
|
||||
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray20) }
|
||||
return Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
}
|
||||
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray85) }
|
||||
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
}
|
||||
set {
|
||||
_backgroundColor = newValue
|
||||
}
|
||||
}
|
||||
|
||||
private var _thickness: CGFloat?
|
||||
public var thickness: CGFloat {
|
||||
get {
|
||||
if let thickness = _thickness { return thickness }
|
||||
switch type {
|
||||
case .heavy:
|
||||
return 4
|
||||
case .medium:
|
||||
return 2
|
||||
case .none:
|
||||
return 0
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
set {
|
||||
_thickness = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var inverted: Bool = false
|
||||
|
||||
// Use this to show vertical line
|
||||
// Default is false
|
||||
public var useVerticalLine: Bool?
|
||||
public var orientation: VDS.Line.Orientation = .horizontal
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
@ -108,13 +70,11 @@ import VDSColorTokens
|
||||
|
||||
public init(type: Style) {
|
||||
self.type = type
|
||||
self.useVerticalLine = false
|
||||
}
|
||||
|
||||
public init(verticalLineOf type: Style, backgroundColor: Color? = nil) {
|
||||
public init(verticalLineOf type: Style) {
|
||||
self.type = type
|
||||
self.backgroundColor = backgroundColor
|
||||
self.useVerticalLine = true
|
||||
orientation = .vertical
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -125,13 +85,10 @@ import VDSColorTokens
|
||||
case id
|
||||
case moleculeName
|
||||
case type
|
||||
case backgroundColor
|
||||
case backgroundColor_inverted
|
||||
case color
|
||||
case frequency
|
||||
case inverted
|
||||
case useVerticalLine
|
||||
case thickness
|
||||
case orientation
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -155,9 +112,12 @@ import VDSColorTokens
|
||||
self.inverted = inverted
|
||||
}
|
||||
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine)
|
||||
_thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
|
||||
/// adding code to look for the old useVerticalLine or the new orientation
|
||||
if let useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) {
|
||||
orientation = useVerticalLine ? .vertical : .horizontal
|
||||
} else if let orientation = try typeContainer.decodeIfPresent(VDS.Line.Orientation.self, forKey: .orientation) {
|
||||
self.orientation = orientation
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -167,8 +127,6 @@ import VDSColorTokens
|
||||
try container.encode(type, forKey: .type)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encodeIfPresent(frequency, forKey: .frequency)
|
||||
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(useVerticalLine, forKey: .useVerticalLine)
|
||||
try container.encodeIfPresent(_thickness, forKey: .thickness)
|
||||
try container.encode(orientation == .vertical, forKey: .useVerticalLine)
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,14 +56,13 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{
|
||||
//setup action
|
||||
if let action = viewModel.action {
|
||||
//add the subscriber
|
||||
onClickSubscriber = publisher(for: .touchUpInside)
|
||||
.sink {[weak self] control in
|
||||
guard let self else { return }
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: action,
|
||||
sourceModel: self.viewModel,
|
||||
additionalData: self.additionalData,
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
onClick = { [weak self] control in
|
||||
guard let self, let viewModel = self.viewModel else { return }
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: action,
|
||||
sourceModel: viewModel,
|
||||
additionalData: self.additionalData,
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,3 +16,11 @@ extension Icon.Size: Codable {}
|
||||
extension TileContainer.BackgroundColor: Codable {}
|
||||
extension TileContainer.Padding: Codable {}
|
||||
extension TileContainer.AspectRatio: Codable {}
|
||||
extension TextLink.Size: Codable {}
|
||||
extension VDS.Line.Style: Codable {}
|
||||
extension VDS.Line.Orientation: Codable {}
|
||||
extension Use: Codable {}
|
||||
extension VDS.Button.Size: RawRepresentableCodable {
|
||||
public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] }
|
||||
public static var defaultValue: VDS.Button.Size? { nil }
|
||||
}
|
||||
@ -42,6 +42,13 @@ import Foundation
|
||||
return Stack<StackModel>.createStack(with: [headline, horizontalStack], spacing: 8)
|
||||
}()
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//-------------------------------------------------------
|
||||
public var verticalLine1HeightConstraint: NSLayoutConstraint?
|
||||
public var verticalLine2HeightConstraint: NSLayoutConstraint?
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//-------------------------------------------------------
|
||||
@ -51,11 +58,10 @@ import Foundation
|
||||
body.lineBreakMode = .byTruncatingTail
|
||||
body2.lineBreakMode = .byTruncatingTail
|
||||
body3.lineBreakMode = .byTruncatingTail
|
||||
|
||||
verticalLine1.widthConstraint?.isActive = true
|
||||
verticalLine1.backgroundColor = .mvmBlack
|
||||
verticalLine2.widthConstraint?.isActive = true
|
||||
verticalLine2.backgroundColor = .mvmBlack
|
||||
|
||||
// setup lines
|
||||
verticalLine1.orientation = .vertical
|
||||
verticalLine2.orientation = .vertical
|
||||
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
@ -80,13 +86,13 @@ import Foundation
|
||||
}
|
||||
|
||||
open func setLineHeight() {
|
||||
verticalLine1.heightConstraint?.isActive = false
|
||||
verticalLine1.heightConstraint = verticalLine1.heightAnchor.constraint(equalTo: body2.heightAnchor, multiplier: 1)
|
||||
verticalLine1.heightConstraint?.isActive = true
|
||||
verticalLine1HeightConstraint?.isActive = false
|
||||
verticalLine1HeightConstraint = verticalLine1.heightAnchor.constraint(equalTo: body2.heightAnchor, multiplier: 1)
|
||||
verticalLine1HeightConstraint?.isActive = true
|
||||
|
||||
verticalLine2.heightConstraint?.isActive = false
|
||||
verticalLine2.heightConstraint = verticalLine2.heightAnchor.constraint(equalTo: body3.heightAnchor, multiplier: 1)
|
||||
verticalLine2.heightConstraint?.isActive = true
|
||||
verticalLine2HeightConstraint?.isActive = false
|
||||
verticalLine2HeightConstraint = verticalLine2.heightAnchor.constraint(equalTo: body3.heightAnchor, multiplier: 1)
|
||||
verticalLine2HeightConstraint?.isActive = true
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@ -42,7 +42,7 @@ public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelPro
|
||||
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
button.size = .tiny
|
||||
button.size = .small
|
||||
button.style = .secondary
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ public class ListDeviceComplexButtonSmallModel: ListItemModel, MoleculeModelProt
|
||||
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
button.size = .tiny
|
||||
button.size = .small
|
||||
button.style = .secondary
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
|
||||
@objcMembers open class ListProgressBarThin: TableViewCell {
|
||||
open class ListProgressBarThin: TableViewCell {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
@ -15,7 +15,11 @@
|
||||
public let progressBar = ProgressBar()
|
||||
public let leftHeadline = Label(fontStyle: .BoldBodySmall)
|
||||
public let leftBody = Label(fontStyle: .BoldBodySmall)
|
||||
public let rightBar = Line()
|
||||
public let rightBar: DataLine = {
|
||||
var line = DataLine()
|
||||
line.heightConstraint.constant = 2
|
||||
return line
|
||||
}()
|
||||
public let rightLabel = Label(fontStyle: .BoldBodySmall)
|
||||
private let barStackItem: StackItem
|
||||
private let rightLabelStackItem: StackItem
|
||||
@ -102,7 +106,6 @@
|
||||
leftHeadline.styleB1(true)
|
||||
leftBody.styleB2(true)
|
||||
rightLabel.styleB2(true)
|
||||
rightBar.setStyle(.medium)
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
@ -16,14 +16,14 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
|
||||
public var progressBar: ProgressBarModel
|
||||
public var leftHeadline: LabelModel
|
||||
public var leftBody: LabelModel?
|
||||
public var rightBar: LineModel
|
||||
public var rightBar: DataLineModel
|
||||
public var rightLabel: LabelModel
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: LineModel, rightLabel: LabelModel) {
|
||||
public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: DataLineModel, rightLabel: LabelModel) {
|
||||
self.progressBar = progressBar
|
||||
self.leftHeadline = leftHeadline
|
||||
self.leftBody = leftBody
|
||||
@ -38,9 +38,7 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
|
||||
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
|
||||
rightBar.type = .medium
|
||||
|
||||
|
||||
if rightBar.backgroundColor == nil {
|
||||
rightBar.backgroundColor = Color(uiColor: .gray)
|
||||
}
|
||||
@ -74,7 +72,7 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
|
||||
progressBar = try typeContainer.decode(ProgressBarModel.self, forKey:.progressBar)
|
||||
leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline)
|
||||
leftBody = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .leftBody)
|
||||
rightBar = try typeContainer.decode(LineModel.self, forKey: .rightBar)
|
||||
rightBar = try typeContainer.decode(DataLineModel.self, forKey: .rightBar)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul
|
||||
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
self.button.size = .tiny
|
||||
self.button.size = .small
|
||||
self.button.style = .secondary
|
||||
}
|
||||
|
||||
|
||||
@ -6,15 +6,26 @@
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
open class DataLine: View {
|
||||
|
||||
lazy var heightConstraint = heightAnchor.constraint(equalToConstant: 4)
|
||||
lazy var widthConstraint = widthAnchor.constraint(equalToConstant: 20)
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
heightConstraint.isActive = true
|
||||
widthConstraint.isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
@objcMembers open class ListRightVariableTotalData: TableViewCell {
|
||||
open class ListRightVariableTotalData: TableViewCell {
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
|
||||
public let leftLabel = Label(fontStyle: .BoldBodySmall)
|
||||
public let rightLabel = Label(fontStyle: .RegularBodySmall)
|
||||
public let bar = Line()
|
||||
public let bar = DataLine()
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Properties
|
||||
@ -44,8 +55,6 @@
|
||||
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
bar.setStyle(.heavy)
|
||||
bar.widthAnchor.constraint(equalToConstant: 20).isActive = true
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
@ -74,7 +83,6 @@
|
||||
super.reset()
|
||||
leftLabel.setFontStyle(.BoldBodySmall)
|
||||
rightLabel.setFontStyle(.RegularBodySmall)
|
||||
bar.setStyle(.heavy)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -6,8 +6,18 @@
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
public struct DataLineModel: Codable, MoleculeModelProtocol {
|
||||
public var id: String = UUID().uuidString
|
||||
public static var identifier: String = "line"
|
||||
public var backgroundColor: Color?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case backgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -15,7 +25,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
|
||||
public static var identifier: String = "listRVLine"
|
||||
public var leftLabel: LabelModel
|
||||
public var rightLabel: LabelModel
|
||||
public var bar: LineModel
|
||||
public var bar: DataLineModel
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Method
|
||||
@ -24,8 +34,6 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
rightLabel.hero = 0
|
||||
bar.type = .heavy
|
||||
|
||||
if bar.backgroundColor == nil {
|
||||
bar.backgroundColor = Color(uiColor: .mvmBlue)
|
||||
}
|
||||
@ -35,7 +43,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(leftLabel: LabelModel, rightlabel:LabelModel, bar: LineModel){
|
||||
public init(leftLabel: LabelModel, rightlabel:LabelModel, bar: DataLineModel) {
|
||||
self.leftLabel = leftLabel
|
||||
self.rightLabel = rightlabel
|
||||
self.bar = bar
|
||||
@ -46,7 +54,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey{
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case leftLabel
|
||||
case rightLabel
|
||||
@ -61,7 +69,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
bar = try typeContainer.decode(LineModel.self, forKey: .bar)
|
||||
bar = try typeContainer.decode(DataLineModel.self, forKey: .bar)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
|
||||
@ -24,5 +24,14 @@
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = PaddingDefaultVerticalSpacing
|
||||
}
|
||||
guard !MVMCoreGetterUtility.isOnIPad(),
|
||||
horizontalAlignment == nil else { return }
|
||||
|
||||
if let _ = molecule as? ButtonModel {
|
||||
horizontalAlignment = .fill
|
||||
} else if let model = molecule as? TwoButtonViewModel,
|
||||
model.primaryButton == nil || model.secondaryButton == nil {
|
||||
horizontalAlignment = .fill
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ import VDSColorTokens
|
||||
setItems(tabs, animated: false)
|
||||
selectedItem = tabs[model.selectedTab]
|
||||
|
||||
guard let lineModel = line.lineModel else { return }
|
||||
guard let lineModel = line.viewModel else { return }
|
||||
lineModel.inverted = model.style == .dark
|
||||
line.set(with: lineModel, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ import VDSColorTokens
|
||||
self.additionalData = additionalData
|
||||
selectedIndex = tabsModel?.selectedIndex ?? 0
|
||||
selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor
|
||||
let lineModel = bottomLine.lineModel ?? LineModel(type: .secondary)
|
||||
let lineModel = bottomLine.viewModel ?? LineModel(type: .secondary)
|
||||
lineModel.inverted = tabsModel?.style == .dark
|
||||
bottomLine.set(with: lineModel, delegateObject, additionalData)
|
||||
reloadData()
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import VDS
|
||||
|
||||
@objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol {
|
||||
//--------------------------------------------------
|
||||
@ -29,9 +29,8 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
public func setDefaultAppearance() {
|
||||
|
||||
primaryButton.stylePrimary()
|
||||
secondaryButton.styleSecondary()
|
||||
primaryButton.use = .primary
|
||||
secondaryButton.use = .secondary
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import VDS
|
||||
|
||||
public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
@ -56,13 +56,13 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
||||
|
||||
//set context value for 'primary' style to be set for the primaryButton in case the
|
||||
//property is not returned in the JSON and once decoded, this value is removed from the context
|
||||
try decoder.setContext(value: Styler.Button.Style.primary, for: "style") {
|
||||
try decoder.setContext(value: Use.primary, for: "style") {
|
||||
self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton)
|
||||
}
|
||||
|
||||
//set context value for 'secondary' style to be set for the primaryButton in case the
|
||||
//property is not returned in the JSON and once decoded, this value is removed from the context
|
||||
try decoder.setContext(value: Styler.Button.Style.secondary, for: "style") {
|
||||
try decoder.setContext(value: Use.secondary, for: "style") {
|
||||
self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
button?.size = .tiny
|
||||
button?.size = .small
|
||||
button?.style = .secondary
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
|
||||
@ -15,7 +15,7 @@ import Foundation
|
||||
|
||||
public let headline = Label(fontStyle: .BoldBodySmall)
|
||||
public let body = Label(fontStyle: .RegularBodySmall)
|
||||
public let button = PillButton(asPrimaryButton: false, makeTiny: true)
|
||||
public let button = PillButton()
|
||||
public let closeButton = NotificationXButton()
|
||||
public var labelStack: Stack<StackModel>!
|
||||
public var horizontalStack: Stack<StackModel>!
|
||||
|
||||
@ -54,7 +54,7 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
|
||||
image.height = BGImageHeadlineBodyButton.heightConstant
|
||||
}
|
||||
|
||||
button?.size = .tiny
|
||||
button?.size = .small
|
||||
button?.style = .secondary
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
|
||||
headlineBody.headlineLabel.font = Styler.Font.BoldTitleMedium.getFont()
|
||||
headlineBody.messageLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
button.styleSecondary()
|
||||
button.use = .secondary
|
||||
button.isHidden = false
|
||||
buttonHeadlinePadding = PaddingTwo
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol {
|
||||
|
||||
/// Defaults to set
|
||||
public func setDefaults() {
|
||||
button.size = .tiny
|
||||
button.size = .small
|
||||
button.style = .secondary
|
||||
}
|
||||
|
||||
|
||||
18
MVMCoreUI/Atomic/Protocols/VDS-Interpreters.swift
Normal file
18
MVMCoreUI/Atomic/Protocols/VDS-Interpreters.swift
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// VDS-Interpreters.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 9/20/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
public protocol Invertable {
|
||||
var inverted: Bool { get set }
|
||||
}
|
||||
|
||||
extension Invertable {
|
||||
public var surface: Surface { return inverted ? .dark : .light }
|
||||
}
|
||||
@ -28,5 +28,9 @@ extension VDSMoleculeViewProtocol {
|
||||
viewModel = castedModel
|
||||
viewModelDidUpdate()
|
||||
}
|
||||
|
||||
public func update(viewModel: ViewModel){
|
||||
set(with: viewModel, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -82,13 +82,6 @@ public extension UINavigationController {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a ShadowImage based on the line property of NavigationItemModelProtocol
|
||||
func getNavigationBarShadowImage(for navigationItemModel: NavigationItemModelProtocol) -> UIImage? {
|
||||
guard let thickness = navigationItemModel.line?.thickness,
|
||||
let backgroundColor = navigationItemModel.line?.backgroundColor else { return nil }
|
||||
return backgroundColor.uiColor.image(CGSize(width: thickness, height: thickness))
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation bar ui
|
||||
@MainActor
|
||||
func setNavigationBarUI(with model: NavigationItemModelProtocol) {
|
||||
@ -105,14 +98,7 @@ public extension UINavigationController {
|
||||
appearance.backgroundColor = backgroundColor
|
||||
appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor)
|
||||
appearance.titlePositionAdjustment = model.titleOffset ?? .zero
|
||||
if let type = model.line?.type,
|
||||
type != .none,
|
||||
let color = model.line?.backgroundColor {
|
||||
appearance.shadowColor = color.uiColor
|
||||
} else {
|
||||
appearance.shadowColor = .clear
|
||||
}
|
||||
appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate)
|
||||
appearance.setShadow(for: model.line)
|
||||
navigationBar.standardAppearance = appearance
|
||||
navigationBar.scrollEdgeAppearance = appearance
|
||||
|
||||
@ -126,3 +112,16 @@ public extension UINavigationController {
|
||||
return viewController
|
||||
}
|
||||
}
|
||||
|
||||
public extension UINavigationBarAppearance {
|
||||
func setShadow(for model: LineModel?) {
|
||||
let model = model ?? LineModel(type: .secondary)
|
||||
let line = Line(model: model, nil, nil)
|
||||
if line.shouldBeVisible() {
|
||||
shadowColor = line.lineColor
|
||||
} else {
|
||||
shadowColor = .clear
|
||||
}
|
||||
shadowImage = line.lineColor.image(CGSize(width: line.lineWidth, height: line.lineWidth)).withRenderingMode(.alwaysTemplate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,13 +125,14 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
/// Hides/Shows the navigation bar for the page.
|
||||
open func hideNavigationBarLine(_ isHidden: Bool) {
|
||||
guard self == navigationController?.topViewController else { return }
|
||||
var color = UIColor.clear
|
||||
if !isHidden,
|
||||
let backgroundColor = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line?.backgroundColor?.uiColor {
|
||||
color = backgroundColor
|
||||
var model: LineModel?
|
||||
if isHidden {
|
||||
model = LineModel(type: .none)
|
||||
} else if let lineModel = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line {
|
||||
model = lineModel
|
||||
}
|
||||
navigationController?.navigationBar.standardAppearance.shadowColor = color
|
||||
navigationController?.navigationBar.scrollEdgeAppearance?.shadowColor = color
|
||||
navigationController?.navigationBar.standardAppearance.setShadow(for: model)
|
||||
navigationController?.navigationBar.scrollEdgeAppearance?.setShadow(for: model)
|
||||
}
|
||||
|
||||
open override func updateViews() {
|
||||
|
||||
@ -159,42 +159,6 @@ open class Styler {
|
||||
}
|
||||
}
|
||||
|
||||
public enum Button {
|
||||
|
||||
public enum Style: String, Codable {
|
||||
case primary
|
||||
case secondary
|
||||
}
|
||||
///MVA 3.0 - Button sizes are standard(default size), small, Tiny. Tiny button has been depricated as of Rebranding 3.0.
|
||||
public enum Size: String, Codable {
|
||||
case standard
|
||||
case small
|
||||
case tiny
|
||||
|
||||
func getHeight() -> CGFloat {
|
||||
switch self {
|
||||
case .standard:
|
||||
return 44
|
||||
case .small:
|
||||
return 32
|
||||
case .tiny:
|
||||
return 20
|
||||
}
|
||||
}
|
||||
|
||||
func minimumWidth() -> CGFloat {
|
||||
switch self {
|
||||
case .standard:
|
||||
return 76
|
||||
case .small:
|
||||
return 0
|
||||
case .tiny:
|
||||
return 49
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Functions
|
||||
//--------------------------------------------------
|
||||
|
||||
40
MVMCoreUI/Utility/RawRepresentableCodable.swift
Normal file
40
MVMCoreUI/Utility/RawRepresentableCodable.swift
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// RawRepresentableCodable.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 9/14/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol RawRepresentableCodable: RawRepresentable, Codable where RawValue: Hashable & Decodable {
|
||||
static var mapping: [RawValue: Self] { get }
|
||||
static var defaultValue: Self? { get }
|
||||
}
|
||||
|
||||
public enum RawRepresentableCodableError: Swift.Error {
|
||||
case invalid(value: String)
|
||||
}
|
||||
|
||||
extension RawRepresentableCodable {
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let rawValue = try container.decode(RawValue.self)
|
||||
if let found = Self(rawValue: rawValue) {
|
||||
self = found
|
||||
} else if let found = Self.mapping[rawValue] {
|
||||
self = found
|
||||
} else if let defaultValue = Self.defaultValue {
|
||||
self = defaultValue
|
||||
} else {
|
||||
throw RawRepresentableCodableError.invalid(value: "\(rawValue)")
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(self)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user