Merge branch 'feature/develop_mvp_3' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/3.0-TitleLockup

This commit is contained in:
Scott Pfeil 2022-06-20 11:50:41 -04:00
commit 7554a718b5
31 changed files with 372 additions and 271 deletions

View File

@ -126,6 +126,7 @@
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; };
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; };
0AF60F0926B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */; };
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */; };
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */; };
1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258726899B0B00DEBB08 /* ImageButton.swift */; };
279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; };
@ -350,7 +351,7 @@
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */; };
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */; };
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; };
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */; };
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
D23118B325124E18001C8440 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* Notification.swift */; };
D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; };
@ -716,6 +717,7 @@
0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = "<group>"; };
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = "<group>"; };
0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIUtility+Extension.swift"; sourceTree = "<group>"; };
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; };
1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; };
279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = "<group>"; };
@ -940,7 +942,7 @@
D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraintExtension.swift; sourceTree = "<group>"; };
D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyLink.swift; sourceTree = "<group>"; };
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTemplateModel.swift; sourceTree = "<group>"; };
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
D23118B225124E18001C8440 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = "<group>"; };
@ -1193,6 +1195,7 @@
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */,
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */,
9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */,
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1992,7 +1995,7 @@
D29DF0DF21E418B2003B2FB9 /* Templates */ = {
isa = PBXGroup;
children = (
D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */,
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */,
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
@ -2025,6 +2028,7 @@
D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = {
isa = PBXGroup;
children = (
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */,
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */,
D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */,
9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */,
@ -3085,7 +3089,7 @@
D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */,
D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */,
012A88F123985E0100FE3DA1 /* Color.swift in Sources */,
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */,
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */,
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */,
D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */,

View File

@ -7,6 +7,7 @@
//
import UIKit
import VDSColorTokens
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
@ -17,12 +18,12 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
//--------------------------------------------------
//Making static property as class property so that subclasses can override getter function of the property
open class var identifier: String { "button" }
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var accessibilityText: String?
public var title: String
public var action: ActionModelProtocol
public var enabled: Bool = true
public var width: CGFloat?
public var style: Styler.Button.Style? {
didSet {
guard let style = style else { return }
@ -57,6 +58,20 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public var disabledTextColor_inverted: Color?
public var disabledBorderColor_inverted: Color?
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
return enabled ? enabledFillColor_inverted : disabledFillColor_inverted
}
return enabled ? enabledFillColor : disabledFillColor
}
set {
_backgroundColor = newValue
}
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
@ -70,18 +85,21 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public init(with title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
setFacade(by: .primary)
}
public init(secondaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .secondary
setFacade(by: .secondary)
}
public init(primaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .primary
setFacade(by: .primary)
}
//--------------------------------------------------
@ -114,40 +132,30 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
/// Defines the default appearance for the primary style.
func setPrimaryFacade() {
enabledFillColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledFillColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
if enabledFillColor == nil && enabledTextColor == nil {
enabledFillColor = Color(uiColor: .mvmBlack)
enabledTextColor = Color(uiColor: .mvmWhite)
}
if disabledFillColor == nil && disabledTextColor == nil {
disabledFillColor = Color(uiColor: .mvmCoolGray6)
disabledTextColor = Color(uiColor: .mvmWhite)
}
enabledFillColor_inverted = Color(uiColor: .mvmWhite)
enabledTextColor_inverted = Color(uiColor: .mvmBlack)
disabledFillColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledTextColor_inverted = Color(uiColor: .mvmBlack)
enabledFillColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledFillColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
/// Defines the default appearance for the Secondary style.
func setSecondaryFacade() {
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledFillColor = Color(uiColor: UIColor.clear)
enabledBorderColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledTextColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledBorderColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
if enabledTextColor == nil && enabledBorderColor == nil {
enabledTextColor = Color(uiColor: .mvmBlack)
enabledBorderColor = Color(uiColor: .mvmBlack)
}
if disabledTextColor == nil && disabledBorderColor == nil {
disabledTextColor = Color(uiColor: .mvmCoolGray6)
disabledBorderColor = Color(uiColor: .mvmCoolGray6)
}
enabledTextColor_inverted = Color(uiColor: .mvmWhite)
enabledBorderColor_inverted = Color(uiColor: .mvmWhite)
disabledTextColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledBorderColor_inverted = Color(uiColor: .mvmCoolGray6)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledFillColor_inverted = Color(uiColor: UIColor.clear)
enabledBorderColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
}
public func setFacade(by style: Styler.Button.Style) {
@ -183,6 +191,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
case disabledFillColor
case disabledTextColor
case disabledBorderColor
case width
}
//--------------------------------------------------
@ -192,15 +201,21 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action)
if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Styler.Button.Style{
self.style = style
setFacade(by: style)
}
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style) {
self.style = style
setFacade(by: style)
} else {
setFacade(by: .primary)
}
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) {
@ -242,6 +257,9 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) {
self.disabledBorderColor = disabledBorderColor
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
}
open func encode(to encoder: Encoder) throws {
@ -251,7 +269,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encode(enabled, forKey: .enabled)
try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
@ -263,5 +281,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(width, forKey: .width)
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
@objcMembers open class Link: Button {
//--------------------------------------------------
@ -28,8 +28,8 @@ import UIKit
// x should be according to the text, not the button
let x = textRect.origin.x
// Line is 1 point below the text
let y = textRect.origin.y + textRect.size.height + 1
// 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))
@ -38,7 +38,7 @@ import UIKit
open override var intrinsicContentSize: CGSize {
guard let size = titleLabel?.intrinsicContentSize else { return super.intrinsicContentSize }
return CGSize(width: size.width, height: size.height + 2)
return CGSize(width: size.width, height: size.height + 1)
}
//--------------------------------------------------
@ -56,7 +56,9 @@ import UIKit
}
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)
}
@ -68,21 +70,15 @@ extension Link {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
var width = size
if MVMCoreGetterUtility.fequal(a: Float.leastNormalMagnitude, b: Float(size)) {
width = MVMCoreUIUtility.getWidth()
}
titleLabel?.font = MFStyler.fontB2(forWidth: width)
}
open override func setupView() {
super.setupView()
backgroundColor = .clear
contentMode = .redraw
setTitleColor(.mvmBlack, for: .normal)
setTitleColor(.mvmCoolGray6, for: .disabled)
setTitleColor(VDSColor.elementsPrimaryOnlight, for: .normal)
setTitleColor(VDSColor.interactiveDisabledOnlight, for: .disabled)
setTitleColor(VDSColor.interactiveActiveOnlight, for: .highlighted)
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .left

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -22,11 +22,15 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
public var accessibilityText: String?
public var action: ActionModelProtocol
public var enabled = true
public var enabledColor = Color(uiColor: .mvmBlack)
public var enabledColor_inverted = Color(uiColor: .mvmWhite)
public var disabledColor = Color(uiColor: .mvmCoolGray6)
public var disabledColor_inverted = Color(uiColor: .mvmCoolGray10)
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
//--------------------------------------------------
// MARK: - Initializer
@ -53,9 +57,30 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
case enabledColor_inverted
case disabledColor
case disabledColor_inverted
case activeColor
case activeColor_inverted
case inverted
case size
}
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
//--------------------------------------------------
@ -92,6 +117,17 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
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) {
self.size = size
}
}
public func encode(to encoder: Encoder) throws {
@ -107,5 +143,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
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)
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
//--------------------------------------------------
@ -23,21 +23,29 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
/// Need to re-style on set.
open override var isEnabled: Bool {
didSet { style() }
didSet { style(with: buttonModel) }
}
open var buttonSize: Styler.Button.Size = .standard {
didSet { buttonModel?.size = buttonSize }
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
public var widthConstraint: NSLayoutConstraint?
public var minimumWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) {
self.init()
buttonSize = istiny ? .tiny : .standard
isPrimary ? stylePrimary() : styleSecondary()
let model = ButtonModel(with: "", action: ActionNoopModel())
model.style = isPrimary ? .primary : .secondary
model.size = istiny ? .tiny : .standard
self.init(model: model, nil, nil)
}
//--------------------------------------------------
@ -68,39 +76,26 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmWhite
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmWhite
layer.borderWidth = 0
backgroundColor = isEnabled ? buttonModel?.enabledColors.fill ?? .mvmBlack : buttonModel?.disabledColors.fill ?? .mvmCoolGray6
let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmBlack
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmCoolGray6
backgroundColor = .clear
layer.borderWidth = 1
borderColor = isEnabled ? buttonModel?.enabledColors.border ?? .mvmBlack : buttonModel?.disabledColors.border ?? .mvmCoolGray6
let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// Styles the button based on the model style
private func style() {
private func style(with model: ButtonModel?) {
switch buttonModel?.style {
case .secondary:
styleSecondary()
default:
stylePrimary()
}
layer.borderWidth = model?.style == .secondary ? 1 : 0
if let titleColor = buttonModel?.enabledColors.text {
if let titleColor = model?.enabledColors.text {
enabledTitleColor = titleColor
}
if let disabledTitleColor = buttonModel?.disabledColors.text {
if let disabledTitleColor = model?.disabledColors.text {
self.disabledTitleColor = disabledTitleColor
}
@ -110,72 +105,46 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
#endif
if isEnabled {
if let fillColor = buttonModel?.enabledColors.fill {
if let fillColor = model?.enabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.enabledColors.border {
layer.borderWidth = 1
if let borderColor = model?.enabledColors.border {
self.borderColor = borderColor
}
} else {
if let fillColor = buttonModel?.disabledColors.fill {
if let fillColor = model?.disabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.disabledColors.border {
layer.borderWidth = 1
if let borderColor = model?.disabledColors.border {
self.borderColor = borderColor
}
}
}
private func getInnerPadding() -> CGFloat {
getHeight() / 2.0
buttonSize.getHeight() / 2.0
}
private func getHeight() -> CGFloat {
PillButton.getHeight(for: buttonSize, size: size)
}
public static func getHeight(for buttonSize: Styler.Button.Size?, size: CGFloat) -> CGFloat {
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:
let tinyHeight = Styler.Button.Size.tiny.getHeight()
return MFSizeObject(standardSize: tinyHeight,
standardiPadPortraitSize: 34,
iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? tinyHeight
default:
let standardHeight = Styler.Button.Size.standard.getHeight()
return MFSizeObject(standardSize: standardHeight,
standardiPadPortraitSize: 46,
iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? standardHeight
}
}
private func getMinimumWidth() -> CGFloat {
switch buttonSize {
case .tiny:
return MFSizeObject(standardSize: 49,
standardiPadPortraitSize: 90,
iPadProLandscapeSize: 135)?.getValueBased(onSize: size) ?? 49
default: return 151
}
}
open override var intrinsicContentSize: CGSize {
if buttonSize == .tiny {
let size = super.intrinsicContentSize
let width = size.width + (2 * getInnerPadding())
return CGSize(width: max(width, getMinimumWidth()), height: getHeight())
} else {
let width = Padding.Component.gutterForApplicationWidth + (2.0 * Padding.Component.columnFor(size: MVMCoreUISplitViewController.getApplicationViewWidth()))
return CGSize(width: min(292, width), height: getHeight())
verticalPadding = Padding.One
horizontalPadding = Padding.Two
break
}
return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}
//--------------------------------------------------
@ -187,6 +156,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
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
@ -206,24 +176,44 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
PillButton.getHeight(for: (model as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth())
return (model as? ButtonModel)?.size?.getHeight()
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
self.size = size
invalidateIntrinsicContentSize()
switch buttonSize {
case .tiny:
titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / Styler.Button.Size.tiny.getHeight()))
default:
titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / Styler.Button.Size.standard.getHeight()))
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() {

View File

@ -49,16 +49,19 @@ import UIKit
public init() {
super.init(frame: .zero)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public override init(frame: CGRect) {
super.init(frame: frame)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {

View File

@ -58,11 +58,11 @@ import VDSColorTokens
/// Sets the item colors.
private func set(tabItemAppearance: UITabBarItemAppearance, model: TabBarModel) {
tabItemAppearance.normal.iconColor = model.unSelectedColor.uiColor
tabItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.unSelectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXRegular(10)]
tabItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.unSelectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXBold(10)]
tabItemAppearance.normal.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabItemAppearance.selected.iconColor = model.selectedColor.uiColor
tabItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.selectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXRegular(10)]
tabItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.selectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXBold(10)]
tabItemAppearance.selected.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
}

View File

@ -50,13 +50,17 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton)
if primaryButton?.style == nil {
primaryButton?.style = .primary
//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") {
self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton)
}
secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
if secondaryButton?.style == nil {
secondaryButton?.style = .secondary
//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") {
self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
}
}

View File

@ -61,7 +61,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
open var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var titleView: MoleculeModelProtocol?
open var titleOffset: UIOffset?
open var titleOffset: UIOffset? = UIOffset(horizontal: -CGFloat.greatestFiniteMagnitude, vertical: 0)
//--------------------------------------------------
// MARK: - Initializer
@ -114,7 +114,9 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
additionalRightButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalRightButtons)
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style)
titleOffset = try typeContainer.decodeIfPresent(UIOffset.self, forKey: .titleOffset) ?? UIOffset(horizontal: -CGFloat.greatestFiniteMagnitude, vertical: 0)
if let titleOffset = try typeContainer.decodeIfPresent(UIOffset.self, forKey: .titleOffset) {
self.titleOffset = titleOffset
}
line?.inverted = style == .dark
}

View File

@ -23,4 +23,33 @@ public protocol MoleculeDelegateProtocol: AnyObject {
extension MoleculeDelegateProtocol {
public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
public func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
let moduleJSON: [AnyHashable: Any]? = getModuleWithName(moleculeName)
guard let moduleJSON = moduleJSON as? [String: Any],
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
else { return nil }
do {
return try modelType.decode(jsonDict: moduleJSON as [String : Any]) as? MoleculeModelProtocol
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
return nil
}
}
extension MoleculeDelegateProtocol where Self: TemplateProtocol {
public func getRootMolecules() -> [MoleculeModelProtocol] {
templateModel?.rootMolecules ?? []
}
}
extension MoleculeDelegateProtocol where Self: MVMCoreViewControllerProtocol {
public func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? {
guard let name = name else { return nil }
return loadObject??.modulesJSON?.optionalDictionaryForKey(name)
}
}

View File

@ -8,43 +8,42 @@
import Foundation
public protocol TemplateProtocol: AnyObject {
public protocol TemplateProtocol: AnyObject, PageProtocol {
associatedtype TemplateModel: TemplateModelProtocol
var templateModel: TemplateModel? { get set }
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel
}
public extension TemplateProtocol where Self: ViewController {
public extension TemplateProtocol {
// Utilize existing underlying property
var templateModel: TemplateModel? {
get {
pageModel as? TemplateModel
}
set {
var mutableSelf = self
mutableSelf.pageModel = newValue
}
}
/// Helper function to do common parsing logic.
func parseTemplate(json: [AnyHashable: Any]?) throws {
guard let pageJSON = json else { return }
let delegateObject = (self as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
let data = try JSONSerialization.data(withJSONObject: pageJSON)
let decoder = JSONDecoder()
try decoder.add(delegateObject: delegateObjectIVar)
let decoder = JSONDecoder.create(with: delegateObject)
templateModel = try decodeTemplate(using: decoder, from: data)
model = templateModel as? MVMControllerModelProtocol
guard let model = model else { return }
traverseAndAddRequiredBehaviors()
var behaviorHandler = self
behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar)
// Add additional required behaviors if applicable.
guard var behaviorHandlerModel = templateModel as? TemplateModelProtocol & PageBehaviorHandlerModelProtocol,
var behaviorHandler = self as? PageBehaviorHandlerProtocol else { return }
behaviorHandlerModel.traverseAndAddRequiredBehaviors()
behaviorHandler.createBehaviors(for: behaviorHandlerModel, delegateObject: delegateObject)
}
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {
try decoder.decode(TemplateModel.self, from: data)
}
/// Traverses all models and adds any required behavior models.
func traverseAndAddRequiredBehaviors() {
guard var model = model else { return }
let behaviorModels: [PageBehaviorModelProtocol] = model.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in
if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer {
return accumulator + behaviorRequirer.getRequiredBehaviors()
}
return accumulator
}
for behavior in behaviorModels {
model.add(behavior: behavior)
}
}
}

View File

@ -1,5 +1,5 @@
//
// TemplateModel.swift
// BaseTemplateModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/13/20.
@ -9,7 +9,7 @@
import Foundation
@objcMembers open class TemplateModel: MVMControllerModelProtocol, TabPageModelProtocol {
@objcMembers open class BaseTemplateModel: MVMControllerModelProtocol, TabPageModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -13,7 +13,6 @@
//--------------------------------------------------
public typealias TemplateModel = CollectionTemplateModel
public var templateModel: CollectionTemplateModel?
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (CollectionItemModelProtocol & MoleculeModelProtocol))]?

View File

@ -19,9 +19,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
public var moleculesInfo: [MoleculeInfo]?
var observer: NSKeyValueObservation?
public var templateModel: ListPageTemplateModel?
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------

View File

@ -15,7 +15,6 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
//--------------------------------------------------
var observer: NSKeyValueObservation?
public var templateModel: StackPageTemplateModel?
//--------------------------------------------------
// MARK: - Lifecycle

View File

@ -7,7 +7,7 @@
//
@objcMembers open class ThreeLayerModelBase: TemplateModel, ThreeLayerTemplateModelProtocol {
@objcMembers open class ThreeLayerModelBase: BaseTemplateModel, ThreeLayerTemplateModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -9,11 +9,6 @@
import UIKit
@objcMembers open class ThreeLayerTemplate<TemplateModel: ThreeLayerPageTemplateModel>: ThreeLayerViewController, TemplateProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var templateModel: TemplateModel?
//--------------------------------------------------
// MARK: - Lifecycle

View File

@ -43,9 +43,6 @@ import UIKit
public var selectedField: UIView?
// Stores the previous tab bar index.
public var tabBarIndex: Int?
/// Checks if the screen width has changed
open func screenSizeChanged() -> Bool {
!MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1)
@ -244,12 +241,6 @@ import UIKit
view.backgroundColor = backgroundColor.uiColor
}
// Update splitview properties
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
updateTabBar()
}
// Notify the manager of new data
manager?.newDataReceived?(in: self)
}
@ -267,34 +258,6 @@ import UIKit
return model?.navigationBar
}
//--------------------------------------------------
// MARK: - TabBar
//--------------------------------------------------
open func updateTabBar() {
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self else { return }
MVMCoreUISplitViewController.main()?.tabBar?.delegateObject = delegateObjectIVar
if let index = (model as? TabPageModelProtocol)?.tabBarIndex {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = loadObject?.requestParameters?.actionMap?["tabBarIndex"] as? Int {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = self.tabBarIndex {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = MVMCoreUISplitViewController.main()?.tabBar?.currentTabIndex() {
// Store current tab index for cases like back button.
self.tabBarIndex = index
}
if let hidden = (model as? TabPageModelProtocol)?.tabBarHidden {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
} else if let hidden = loadObject?.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
} else {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(true)
}
}
//--------------------------------------------------
// MARK: - View Lifecycle
//--------------------------------------------------
@ -349,12 +312,6 @@ import UIKit
}
open func pageShown() {
// Update split view properties if this is the current detail controller.
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
updateTabBar()
}
// Track.
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
@ -484,26 +441,6 @@ import UIKit
model?.rootMolecules ?? []
}
open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? {
guard let name = name else { return nil }
return loadObject?.modulesJSON?.optionalDictionaryForKey(name)
}
open func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName),
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
else { return nil }
do {
return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
return nil
}
// Needed otherwise when subclassed, the extension gets called.
open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
@ -618,12 +555,4 @@ import UIKit
selectedField = nil
}
}
//--------------------------------------------------
// MARK: - Behavior Execution
//--------------------------------------------------
public func executeBehaviors<T>(_ behaviorBlock: (_ behavior: T) -> Void) {
behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) }
}
}

View File

@ -75,7 +75,7 @@ public class AddRemoveMoleculesBehavior: PageCustomActionHandlerBehavior, PageMo
self.delegate = delegateObject
}
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) {
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {
guard let list = delegate?.moleculeListDelegate else { return }
for case let model as (MoleculeModelProtocol & ListItemModelProtocol & AddMolecules) in rootMolecules {
if let moleculesToAdd = model.getRecursiveMoleculesToAdd(),

View File

@ -23,3 +23,19 @@ public extension PageBehaviorHandlerModelProtocol {
self.behaviors = newBehaviors
}
}
public extension PageBehaviorHandlerModelProtocol where Self: MoleculeTreeTraversalProtocol {
/// Traverses all models and adds any required behavior models.
mutating func traverseAndAddRequiredBehaviors() {
let behaviorModels: [PageBehaviorModelProtocol] = reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in
if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer {
return accumulator + behaviorRequirer.getRequiredBehaviors()
}
return accumulator
}
for behavior in behaviorModels {
add(behavior: behavior)
}
}
}

View File

@ -34,4 +34,9 @@ public extension PageBehaviorHandlerProtocol {
}
self.behaviors = behaviors.count > 0 ? behaviors : nil
}
/// Executes all behaviors of type.
func executeBehaviors<T>(_ behaviorBlock: (_ behavior: T) -> Void) {
behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) }
}
}

View File

@ -19,7 +19,7 @@ public protocol PageBehaviorProtocol: ModelHandlerProtocol {
public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject)
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?)
}
public protocol PageVisibilityBehavior: PageBehaviorProtocol {
@ -50,8 +50,11 @@ public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol {
}
public extension MVMCoreUIDelegateObject {
var behaviorModelDelegate: PageBehaviorHandlerModelProtocol? {
(moleculeDelegate as? PageProtocol)?.pageModel as? PageBehaviorHandlerModelProtocol
}
weak var behaviorTemplateDelegate: (PageBehaviorHandlerProtocol & NSObjectProtocol)? {
(moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorHandlerProtocol & NSObjectProtocol)
moleculeDelegate as? (PageBehaviorHandlerProtocol & NSObjectProtocol)
}
}

View File

@ -66,7 +66,7 @@ public extension UINavigationController {
/// Convenience function for setting the navigation bar ui
func setNavigationBarUI(with model: NavigationItemModelProtocol) {
let navigationBar = navigationBar
let font = MFStyler.fontBoldBodySmall(false)
let font = MFStyler.fontBoldBodyLarge(false)
let backgroundColor = model.backgroundColor?.uiColor
let tint = model.tintColor.uiColor
navigationBar.tintColor = tint

View File

@ -12,6 +12,64 @@ import UIKit
// Navigation bar update functions
public extension MVMCoreUISplitViewController {
/// Updates the state for various controls (navigation, tab, progress) for the controller.
func updateState(with viewController: UIViewController) {
guard let navigationController = navigationController,
navigationController.isDisplayed(viewController: viewController) else { return }
updateNavigationBarFor(viewController: viewController)
updateProgressBar(for: viewController)
updateTabBar(for: viewController)
}
// MARK: - Progress Bar
/// Updates the progress bar based on the page json for the view controller.
func updateProgressBar(for viewController: UIViewController) {
guard let viewController = viewController as? MVMCoreViewControllerProtocol else { return }
var progress: Float = 0.0
if let progressString = viewController.loadObject??.pageJSON?.optionalStringForKey(KeyProgressPercent),
let floatValue = Float(progressString) {
progress = floatValue/100
}
setBottomProgressBarProgress(progress)
}
// MARK: - Tab Bar
/// Updates the tab bar based on the page json for the view controller.
func updateTabBar(for viewController: UIViewController) {
let mvmViewController = viewController as? MVMCoreViewControllerProtocol
tabBar?.delegateObject = mvmViewController?.delegateObject?() as? MVMCoreUIDelegateObject
let navigationIndex = (MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 1) - 1
// Set the highlighted index. In terms of priority, Page > Action > Previous.
if let index = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarIndex {
tabBar?.highlightTab(at: index)
} else if let index = mvmViewController?.loadObject??.requestParameters?.actionMap?["tabBarIndex"] as? Int {
tabBar?.highlightTab(at: index)
} else if navigationIndex < tabBarIndices.count {
let index = (tabBarIndices[navigationIndex] as! NSNumber).intValue
tabBar?.highlightTab(at: index)
}
// Store current tab index, so we can switch back when going back in hierarchy.
if tabBarIndices.count > 0 {
tabBarIndices.removeObjects(in: NSRange(location: navigationIndex, length: tabBarIndices.count - navigationIndex))
}
if let currentIndex = tabBar?.currentTabIndex() {
tabBarIndices.add(NSNumber(integerLiteral: currentIndex))
}
// Show/Hide. In terms of priority, Page > Action > Always Show.
if let hidden = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarHidden {
updateTabBarShowing(!hidden)
} else if let hidden = mvmViewController?.loadObject??.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
updateTabBarShowing(!hidden)
} else {
updateTabBarShowing(true)
}
}
// MARK: - Navigation Bar
/// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol.
func setNavigationBar(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
guard navigationController == self.navigationController,
@ -122,6 +180,7 @@ public extension MVMCoreUISplitViewController {
setStatusBarForCurrentViewController()
}
// MARK: - Status Bar
/// Returns the bar style for the background color. Light if on a dark background, otherwise default.
func getStatusBarStyle(for backgroundColor: UIColor?) -> UIStatusBarStyle {
var greyScale: CGFloat = 0
@ -155,10 +214,10 @@ extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol {
public func willDisplay(_ viewController: UIViewController) {
setupPanels()
updateNavigationBarFor(viewController: viewController)
updateState(with: viewController)
}
public func newDataReceived(in viewController: UIViewController) {
updateNavigationBarFor(viewController: viewController)
updateState(with: viewController)
}
}

View File

@ -55,6 +55,9 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
/// Reference to the tabbar.
@property (nullable, weak, nonatomic) UIView <TabBarProtocol>*tabBar;
/// Tab bar index history.
@property (nonnull, strong, nonatomic) NSMutableArray <NSNumber *>*tabBarIndices;
// Convenience getter
+ (nullable instancetype)mainSplitViewController;

View File

@ -93,13 +93,20 @@ CGFloat const PanelAnimationDuration = 0.2;
}
- (nullable instancetype)initWithLeftPanel:(nullable UIViewController <MVMCoreUIPanelProtocol> *)leftPanel rightPanel:(nullable UIViewController <MVMCoreUIPanelProtocol> *)rightPanel {
if (self = [super init]) {
if (self = [self init]) {
self.globalLeftPanel = leftPanel;
self.globalRightPanel = rightPanel;
}
return self;
}
- (nullable instancetype)init {
if (self = [super init]) {
self.tabBarIndices = [NSMutableArray array];
}
return self;
}
#pragma mark - Main Subclassables
- (MFNumberOfDrawers)numberOfDrawersShouldShow:(NSNumber *)forWidth {

View File

@ -19,7 +19,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
/// Used to layout the ui.
public lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [tabs, line, subNavigationController.view])
let stackView = UIStackView(arrangedSubviews: [tabs, subNavigationController.view])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.isAccessibilityElement = false
stackView.axis = .vertical
@ -33,10 +33,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
return tabs
}()
public lazy var line: Line = {
return Line(model: LineModel(type: .secondary), delegateObjectIVar, nil)
}()
public lazy var subNavigationController: UINavigationController = {
let subNavigationController = SubNavManagerNavigationController(rootViewController: viewController)
subNavigationController.view.translatesAutoresizingMaskIntoConstraints = false

View File

@ -125,8 +125,6 @@
- (void)openURLInSafariWebView:(nonnull NSURL *)url {
SFSafariViewController *safariViewController = [[SFSafariViewController alloc] initWithURL:url];
safariViewController.preferredBarTintColor = [UIColor whiteColor];
safariViewController.preferredControlTintColor = [UIColor blackColor];
[[MVMCoreNavigationHandler sharedNavigationHandler] presentViewController:safariViewController animated:YES];
}

View File

@ -178,20 +178,33 @@ open class Styler {
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 42
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
}
}
}
}

View File

@ -204,7 +204,6 @@
// Sets up to use a button action. Always uses the top view controller
PillButton *button = [[PillButton alloc] initAsPrimaryButton:false makeTiny:true];
[button styleSecondary];
[button setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[button setContentHuggingPriority:800 forAxis:UILayoutConstraintAxisHorizontal];

View File

@ -69,10 +69,7 @@ open class TopNotificationModel: Codable {
/// Decodes the top alert json to a model.
public static func decode(json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) throws -> Self {
let data = try JSONSerialization.data(withJSONObject: json)
let decoder = JSONDecoder()
if let delegateObject = delegateObject {
try decoder.add(delegateObject: delegateObject)
}
let decoder = JSONDecoder.create(with: delegateObject)
return try decoder.decode(self, from: data)
}