diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift index f864e72f..d71d40be 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonGroup.swift @@ -9,17 +9,23 @@ import Foundation import UIKit import VDS +import Combine -@objcMembers open class ButtonGroup: VDS.ButtonGroup, VDSMoleculeViewProtocol { +open class ButtonGroup: VDS.ButtonGroup, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- + public var model: MoleculeModelProtocol? open var viewModel: ButtonGroupModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? open var previousModel: ButtonGroupModel? + /// For notifying the delegate of layout updates. + private var contentSizeObservation: Cancellable? + private var previousSize: CGSize? + //-------------------------------------------------- // MARK: - MoleculeViewProtocol //-------------------------------------------------- @@ -74,6 +80,15 @@ import VDS // force redraw setNeedsUpdate() } + + // Notify the delegate of a size change. + previousSize = bounds.size + contentSizeObservation = contentSizePublisher.sink { [weak self] size in + guard let self = self, + !MVMCoreGetterUtility.fequal(a: Float(size.height), b: Float(self.previousSize?.height ?? Self.estimatedHeight(with: self.viewModel, self.delegateObject) ?? VDS.Button.Size.large.height)) else { return } + self.previousSize = size + self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + } } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 37eff177..d8c114f8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -182,29 +182,7 @@ public typealias ActionBlock = () -> () } @objc public func resetAttributeStyle() { - /* - * This is to address a reuse issue with iOS 13 and up. - * Even if you set text & attributedText to nil, the moment you set text with a value, - * attributedText will hold a dirty value from a previously reused cell even if reset() is - * appropriately called. - * Only other reference found of issue: https://www.thetopsites.net/article/58142205.shtml - */ - if let text = text, !text.isEmpty { - - //create the primary string - let mutableText = NSMutableAttributedString.mutableText(for: text, - textStyle: textStyle, - useScaledFont: useScaledFont, - textColor: textColorConfiguration.getColor(self), - alignment: textAlignment, - lineBreakMode: lineBreakMode) - - if let attributes = attributes { - mutableText.apply(attributes: attributes) - } - - self.attributedText = mutableText - } + setNeedsUpdate() } public func viewModelDidUpdate() { @@ -221,7 +199,6 @@ public typealias ActionBlock = () -> () } if let style = viewModel.fontStyle?.vdsTextStyle() { - font = style.font textStyle = style } else if let fontName = viewModel.fontName { // there is a TextStyle.defaultStyle @@ -229,10 +206,12 @@ public typealias ActionBlock = () -> () if let fontSize { standardFontSize = fontSize } - if let customStyle = style(for: fontName, pointSize: fontSize ?? standardFontSize), customStyle != textStyle { - font = customStyle.font - textStyle = customStyle + if let newFont = UIFont(name: fontName, size: fontSize ?? standardFontSize) { + font = newFont } + } else if let fontSize = viewModel.fontSize { + standardFontSize = fontSize + font = textStyle.font.withSize(fontSize) } if let color = viewModel.textColor { @@ -248,26 +227,6 @@ public typealias ActionBlock = () -> () } } - - /// See if the font that is currently set matches a VDS Font and if so grab the matching TextStyle or create custom TextStyle that - /// that the Label will use moving forward. - private func checkforFontChange() { - guard let customStyle = style(for: font.fontName, pointSize: font.pointSize), customStyle != textStyle - else { return } - textStyle = customStyle - } - - private func style(for fontName: String, pointSize: CGFloat) -> TextStyle? { - guard let vdsFont = Font.from(fontName: fontName), - let customStyle = TextStyle.style(from: vdsFont, pointSize: pointSize) - else { return nil } - return customStyle - } - - open override func updateView() { - checkforFontChange() - super.updateView() - } open override func updateAccessibility() { super.updateAccessibility() diff --git a/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift b/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift index f7e5917e..b8f4c74a 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-TextStyle.swift @@ -21,10 +21,10 @@ extension Styler.Font { case .TitleXLarge: actualFont = .RegularTitleXLarge case .H1: actualFont = .RegularTitle2XLarge case .H32: actualFont = .RegularTitleXLarge - case .H2: actualFont = .RegularTitleLarge + case .H2: actualFont = .RegularTitleXLarge case .B20: actualFont = .RegularBodyLarge case .H3: actualFont = .BoldTitleMedium - case .B1: actualFont = .BoldBodySmall + case .B1: actualFont = .RegularTitleSmall case .B2: actualFont = .RegularBodySmall case .B3: actualFont = .RegularMicro default: break @@ -54,12 +54,3 @@ extension VDS.Font { Self.allCases.filter({$0.fontName == fontName }).first } } - -extension VDS.TextStyle { - internal static func style(from font: VDS.Font, pointSize: CGFloat) -> TextStyle? { - guard let first = allCases.filter({$0.fontFace == font && $0.pointSize == pointSize}).first else { - return TextStyle(rawValue: "Custom-TextStyle", fontFace: font, pointSize: pointSize) - } - return first - } -} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift index e4ede5e8..e4708b51 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift @@ -8,14 +8,14 @@ import Foundation -@objcMembers open class HeadersH1Button: HeaderView { +open class HeadersH1Button: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() public let buttons = TwoButtonView() public lazy var stack: Stack = { - Stack.createStack(with: [headlineBody, buttons], spacing: Padding.Eighteen) + Stack.createStack(with: [titleLockup, buttons], spacing: Padding.Eighteen) }() //------------------------------------------------------- @@ -23,7 +23,6 @@ import Foundation //------------------------------------------------------- open override func setupView() { super.setupView() - headlineBody.styleLandingPageHeader() addMolecule(stack) stack.restack() } @@ -35,14 +34,9 @@ import Foundation super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadersH1ButtonModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) buttons.set(with: model.buttons, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 121 } - - open override func reset() { - super.reset() - headlineBody.styleLandingPageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift index 9ed584a9..0cf8410f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1ButtonModel.swift @@ -13,15 +13,16 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "headerH1Btn" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel public var buttons: TwoButtonViewModel - + private var helper = DeprecatedHeadlineBodyHelper() + public var children: [MoleculeModelProtocol] { - [headlineBody, buttons] + [titleLockup, buttons] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) || replaceChildMolecule(at: &buttons, with: molecule) } @@ -29,8 +30,8 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel, buttons: TwoButtonViewModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel, buttons: TwoButtonViewModel) { + self.titleLockup = titleLockup self.buttons = buttons super.init() } @@ -40,10 +41,13 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol //-------------------------------------------------- public override func setDefaults() { - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header - } super.setDefaults() + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitle2XLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium + } } //-------------------------------------------------- @@ -52,7 +56,7 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup case buttons } @@ -61,7 +65,7 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup) buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons) try super.init(from: decoder) } @@ -70,7 +74,8 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) try container.encode(buttons, forKey: .buttons) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyText.swift index e751815e..68e31680 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyText.swift @@ -8,20 +8,19 @@ import Foundation -@objcMembers open class HeadersH1NoButtonsBodyText: HeaderView { +open class HeadersH1NoButtonsBodyText: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() //------------------------------------------------------- // MARK: - View Lifecycle //------------------------------------------------------- open override func setupView() { super.setupView() - headlineBody.styleLandingPageHeader() - addMolecule(headlineBody) + addMolecule(titleLockup) } //---------------------------------------------------- @@ -31,13 +30,8 @@ import Foundation open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadersH1NoButtonsBodyTextModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 121 } - - open override func reset() { - super.reset() - headlineBody.styleLandingPageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift index 9f3e6133..7450c9aa 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1NoButtonsBodyTextModel.swift @@ -6,50 +6,48 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // - - public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "headerH1" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel + private var helper = DeprecatedHeadlineBodyHelper() public var children: [MoleculeModelProtocol] { - [headlineBody] + [titleLockup] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) + } + + public override func setDefaults() { + super.setDefaults() + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitle2XLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium + } } //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel) { + self.titleLockup = titleLockup super.init() } - //-------------------------------------------------- - // MARK: - Subclass - //-------------------------------------------------- - - public override func setDefaults() { - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header - } - super.setDefaults() - } - //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup } //-------------------------------------------------- @@ -57,7 +55,7 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup) try super.init(from: decoder) } @@ -65,6 +63,55 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) + } +} + +public struct DeprecatedHeadlineBodyHelper { + var headlineBody: HeadlineBodyModel? + + private enum DeprecatedCodingKeys: String, CodingKey { + case headlineBody + } + + public mutating func deprecatedCreate(from decoder: Decoder) throws -> TitleLockupModel? { + let typeContainer = try decoder.container(keyedBy: DeprecatedCodingKeys.self) + headlineBody = try typeContainer.decodeIfPresent(HeadlineBodyModel.self, forKey: .headlineBody) + guard let headlineBody = headlineBody else { return nil } + return try createTitleLockupModel(headlineBody: headlineBody) + } + + public func deprecatedEncode(to encoder: Encoder) throws -> Bool { + guard let headlineBody = headlineBody else { return false } + var container = encoder.container(keyedBy: DeprecatedCodingKeys.self) + try container.encode(headlineBody, forKey: DeprecatedCodingKeys.headlineBody) + return true + } + + public func createTitleLockupModel(defaultStyle: HeadlineBodyModel.Style = .header, headlineBody: HeadlineBodyModel) throws -> TitleLockupModel { + guard let headline = headlineBody.headline else { throw ModelRegistry.Error.decoderOther(message: "headline is required for this use case.") } + var body = headlineBody.body + switch headlineBody.style ?? defaultStyle { + case .landingHeader: + headline.fontStyle = Styler.Font.RegularTitle2XLarge + body?.fontStyle = Styler.Font.RegularTitleMedium + case .itemHeader: + headline.fontStyle = Styler.Font.BoldTitleLarge + body?.fontStyle = Styler.Font.RegularBodyLarge + default: + headline.fontStyle = Styler.Font.RegularTitleXLarge + body?.fontStyle = Styler.Font.RegularTitleMedium + } + let model = try TitleLockupModel(title: headline, subTitle: body) + model.id = headlineBody.id + return model + } + + public func createHeadlineBodyModel(titleLockup: TitleLockupModel) -> HeadlineBodyModel { + var headlineBody = HeadlineBodyModel(headline: titleLockup.title) + headlineBody.body = titleLockup.subTitle + headlineBody.id = titleLockup.id + return headlineBody } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift index 8604a56b..119cc551 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift @@ -9,15 +9,15 @@ import Foundation -@objcMembers open class HeadersH2Buttons: HeaderView { +open class HeadersH2Buttons: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() public let buttons = TwoButtonView() public lazy var stack: Stack = { - return Stack.createStack(with: [headlineBody, buttons], spacing: PaddingDefaultVerticalSpacing3) + return Stack.createStack(with: [titleLockup, buttons], spacing: PaddingDefaultVerticalSpacing3) }() //------------------------------------------------------- @@ -26,7 +26,6 @@ import Foundation open override func setupView() { super.setupView() - headlineBody.stylePageHeader() addMolecule(stack) stack.restack() } @@ -40,16 +39,11 @@ import Foundation guard let model = model as? HeadersH2ButtonsModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) buttons.set(with: model.buttons, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } - - open override func reset() { - super.reset() - headlineBody.stylePageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift index 8a5a3e64..3b4d0b7e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift @@ -15,15 +15,16 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo //-------------------------------------------------- public static var identifier: String = "headerH2Btns" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel public var buttons: TwoButtonViewModel + private var helper = DeprecatedHeadlineBodyHelper() public var children: [MoleculeModelProtocol] { - [headlineBody, buttons] + [titleLockup, buttons] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) || replaceChildMolecule(at: &buttons, with: molecule) } @@ -31,8 +32,8 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel, buttons: TwoButtonViewModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel, buttons: TwoButtonViewModel) { + self.titleLockup = titleLockup self.buttons = buttons super.init() } @@ -48,8 +49,11 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium } super.setDefaults() } @@ -60,7 +64,7 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup case buttons } @@ -70,7 +74,7 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup) buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons) try super.init(from: decoder) } @@ -79,7 +83,8 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) try container.encode(buttons, forKey: .buttons) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift index c641ac97..21bd02ab 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift @@ -7,14 +7,14 @@ // import Foundation -@objcMembers open class HeadersH2CaretLink: HeaderView { +open class HeadersH2CaretLink: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() public let caretLink = CaretLink() public lazy var stack: Stack = { - return Stack.createStack(with: [headlineBody, caretLink]) + return Stack.createStack(with: [titleLockup, caretLink]) }() //------------------------------------------------------- @@ -22,7 +22,6 @@ import Foundation //------------------------------------------------------- open override func setupView() { super.setupView() - headlineBody.stylePageHeader() addMolecule(stack) stack.restack() } @@ -33,16 +32,11 @@ import Foundation open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadersH2CaretLinkModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) caretLink.set(with: model.caretLink, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } - - open override func reset() { - super.reset() - headlineBody.stylePageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift index c50fb736..4f7129da 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift @@ -12,23 +12,24 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent // MARK: - Properties //-------------------------------------------------- public static var identifier: String = "headerH2CrtBtn" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel public var caretLink: CaretLinkModel + private var helper = DeprecatedHeadlineBodyHelper() public var children: [MoleculeModelProtocol] { - [headlineBody, caretLink] + [titleLockup, caretLink] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) || replaceChildMolecule(at: &caretLink, with: molecule) } //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel, caretLink: CaretLinkModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel, caretLink: CaretLinkModel) { + self.titleLockup = titleLockup self.caretLink = caretLink super.init() } @@ -43,8 +44,11 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium } super.setDefaults() } @@ -54,7 +58,7 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent //-------------------------------------------------- private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup case caretLink } @@ -63,7 +67,7 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup) caretLink = try typeContainer.decode(CaretLinkModel.self, forKey: .caretLink) try super.init(from: decoder) } @@ -72,7 +76,8 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) try container.encode(caretLink, forKey: .caretLink) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift index e90a51f2..24ad40b5 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift @@ -8,14 +8,14 @@ import Foundation -@objcMembers open class HeadersH2Link: HeaderView { +open class HeadersH2Link: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() public let link = Link() public lazy var stack: Stack = { - return Stack.createStack(with: [headlineBody, link]) + return Stack.createStack(with: [titleLockup, link]) }() //------------------------------------------------------- @@ -23,7 +23,6 @@ import Foundation //------------------------------------------------------- open override func setupView() { super.setupView() - headlineBody.stylePageHeader() addMolecule(stack) stack.restack() } @@ -34,16 +33,11 @@ import Foundation open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? HeadersH2LinkModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) link.set(with: model.link, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } - - open override func reset() { - super.reset() - headlineBody.stylePageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift index ced6b47a..1ec6590d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift @@ -14,15 +14,16 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec //-------------------------------------------------- public static var identifier: String = "headerH2Link" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel public var link: LinkModel + private var helper = DeprecatedHeadlineBodyHelper() public var children: [MoleculeModelProtocol] { - [headlineBody, link] + [titleLockup, link] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) || replaceChildMolecule(at: &link, with: molecule) } @@ -30,8 +31,8 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel, link: LinkModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel, link: LinkModel) { + self.titleLockup = titleLockup self.link = link super.init() } @@ -47,8 +48,11 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium } super.setDefaults() } @@ -59,7 +63,7 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup case link } @@ -69,7 +73,7 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup) link = try typeContainer.decode(LinkModel.self, forKey: .link) try super.init(from: decoder) } @@ -78,7 +82,8 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) try container.encode(link, forKey: .link) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyText.swift index ca394b05..7cd68ce7 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyText.swift @@ -9,12 +9,12 @@ import Foundation -@objcMembers open class HeadersH2NoButtonsBodyText: HeaderView { +open class HeadersH2NoButtonsBodyText: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() //------------------------------------------------------- // MARK: - View Lifecycle @@ -22,8 +22,7 @@ import Foundation open override func setupView() { super.setupView() - headlineBody.stylePageHeader() - addMolecule(headlineBody) + addMolecule(titleLockup) } //---------------------------------------------------- @@ -34,15 +33,10 @@ import Foundation guard let model = model as? HeadersH2NoButtonsBodyTextModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } - - open override func reset() { - super.reset() - headlineBody.stylePageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift index 774102da..671e5c0b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2NoButtonsBodyTextModel.swift @@ -15,22 +15,23 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol //-------------------------------------------------- public static var identifier: String = "headerH2" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel + private var helper = DeprecatedHeadlineBodyHelper() public var children: [MoleculeModelProtocol] { - [headlineBody] + [titleLockup] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) } //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel) { + self.titleLockup = titleLockup super.init() } @@ -41,8 +42,11 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium } super.setDefaults() } @@ -53,7 +57,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup } //-------------------------------------------------- @@ -62,7 +66,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup) try super.init(from: decoder) } @@ -70,6 +74,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift index 77a44761..10632aae 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift @@ -9,15 +9,15 @@ import Foundation -@objcMembers open class HeadersH2TinyButton: HeaderView { +open class HeadersH2TinyButton: HeaderView { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- - public let headlineBody = HeadlineBody() + public let titleLockup = TitleLockup() public let button = PillButton() public lazy var stack: Stack = { - return Stack.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), + return Stack.createStack(with: [(view: titleLockup, model: StackItemModel(horizontalAlignment: .fill)), (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], axis: .vertical) }() @@ -34,7 +34,6 @@ import Foundation open override func setupView() { super.setupView() - headlineBody.stylePageHeader() addMolecule(stack) stack.restack() } @@ -48,16 +47,11 @@ import Foundation guard let model = model as? HeadersH2TinyButtonModel else { return } - headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + titleLockup.set(with: model.titleLockup, delegateObject, additionalData) button.set(with: model.button, delegateObject, additionalData) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 121 } - - open override func reset() { - super.reset() - headlineBody.stylePageHeader() - } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift index 2a91c860..91a1c472 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift @@ -15,15 +15,16 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren //-------------------------------------------------- public static var identifier: String = "headerH2BtnTny" - public var headlineBody: HeadlineBodyModel + public var titleLockup: TitleLockupModel public var button: ButtonModel + private var helper = DeprecatedHeadlineBodyHelper() public var children: [MoleculeModelProtocol] { - [headlineBody, button] + [titleLockup, button] } public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { - return try replaceChildMolecule(at: &headlineBody, with: molecule) + return try replaceChildMolecule(at: &titleLockup, with: molecule) || replaceChildMolecule(at: &button, with: molecule) } @@ -31,8 +32,8 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren // MARK: - Initializer //-------------------------------------------------- - public init(headlineBody: HeadlineBodyModel, button: ButtonModel) { - self.headlineBody = headlineBody + public init(titleLockup: TitleLockupModel, button: ButtonModel) { + self.titleLockup = titleLockup self.button = button super.init() } @@ -48,8 +49,11 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren if bottomPadding == nil { bottomPadding = Padding.Component.VerticalMarginSpacing } - if headlineBody.headline?.accessibilityTraits == nil { - headlineBody.headline?.accessibilityTraits = .header + if titleLockup.title.fontStyle == nil { + titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge + } + if titleLockup.subTitle?.fontStyle == nil { + titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium } super.setDefaults() button.style = .secondary @@ -62,7 +66,7 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren private enum CodingKeys: String, CodingKey { case moleculeName - case headlineBody + case titleLockup case button } @@ -72,7 +76,7 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup) button = try typeContainer.decode(ButtonModel.self, forKey: .button) try super.init(from: decoder) } @@ -81,7 +85,8 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(headlineBody, forKey: .headlineBody) try container.encode(button, forKey: .button) + guard try !helper.deprecatedEncode(to: encoder) else { return } + try container.encode(titleLockup, forKey: .titleLockup) } } diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift index d1c7cf48..09a5451a 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift @@ -31,7 +31,7 @@ open class HeaderView: Container { (molecule as? MVMCoreViewProtocol)?.updateView(size) } - public override func setupView() { + open override func setupView() { super.setupView() line.setStyle(.none) addSubview(line) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/HeaderModel.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/HeaderModel.swift index df1045c2..fc63cbb7 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/HeaderModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/HeaderModel.swift @@ -7,9 +7,9 @@ // -@objcMembers public class HeaderModel: ContainerModel { - public var backgroundColor: Color? - public var line: LineModel? +open class HeaderModel: ContainerModel { + open var backgroundColor: Color? + open var line: LineModel? private enum CodingKeys: String, CodingKey { case line @@ -17,7 +17,7 @@ } /// Defaults to set - public override func setDefaults() { + open override func setDefaults() { if useHorizontalMargins == nil { useHorizontalMargins = true } @@ -43,7 +43,7 @@ backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) } - public override func encode(to encoder: Encoder) throws { + open override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(line, forKey: .line) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 2d176986..654e48ac 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -41,16 +41,6 @@ import VDS } } } - - //-------------------------------------------------- - // MARK: - Public Properties Overrides - //-------------------------------------------------- - open override var selectedIndex: Int { - didSet { - guard let viewModel else { return } - viewModel.selectedIndex = selectedIndex - } - } //------------------------------------------------- // MARK: - Layout Views diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 4785cfb9..536bc16b 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -17,11 +17,11 @@ import VDS open var viewModel: TwoButtonViewModel! open var delegateObject: MVMCoreUIDelegateObject? open var additionalData: [AnyHashable : Any]? - + open var primaryButton = PillButton() open var secondaryButton = PillButton() private var buttonGroup = VDS.ButtonGroup() - + private var heightConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -34,6 +34,7 @@ import VDS buttonGroup.alignment = .center buttonGroup.rowQuantityPhone = 2 buttonGroup.rowQuantityTablet = 2 + heightConstraint = height(constant: VDS.Button.Size.large.height, priority: .required) } //-------------------------------------------------- @@ -70,6 +71,8 @@ import VDS if buttons.count != buttonGroup.buttons.count { buttonGroup.buttons = buttons } + + heightConstraint?.constant = primaryButton.size == .small || secondaryButton.size == .small ? VDS.Button.Size.small.height : VDS.Button.Size.large.height } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index c2cad75a..0ed1db11 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -38,6 +38,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { case backgroundColor case primaryButton case secondaryButton + case fillContainer } //-------------------------------------------------- @@ -69,6 +70,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { try decoder.setContext(value: Use.secondary, for: "style") { self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton) } + fillContainer = try typeContainer.decodeIfPresent(Bool.self, forKey: .fillContainer) ?? false } public func encode(to encoder: Encoder) throws { @@ -78,5 +80,6 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(primaryButton, forKey: .primaryButton) try container.encodeIfPresent(secondaryButton, forKey: .secondaryButton) + try container.encodeIfPresent(fillContainer, forKey: .fillContainer) } } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index da5e959e..3bc61b40 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -14,7 +14,7 @@ public let stack = Stack(frame: .zero) public let eyebrow = Label(fontStyle: .RegularMicro) - public let headline = Label(fontStyle: .BoldBodySmall) + public let headline = Label(fontStyle: .RegularTitleSmall) public let body = Label(fontStyle: .RegularBodySmall, true) public let link = Link() @@ -58,7 +58,7 @@ super.reset() stack.reset() eyebrow.setFontStyle(.RegularMicro) - headline.setFontStyle(.BoldBodySmall) + headline.setFontStyle(.RegularTitleSmall) body.setFontStyle(.RegularBodySmall) } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift index 96e94640..a5bb8b49 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -60,9 +60,9 @@ open class HeadlineBody: View { } public func stylePageHeader() { - headlineLabel.setFontStyle(.RegularTitleLarge) - messageLabel.setFontStyle(.RegularBodyLarge) - spaceBetweenLabelsConstant = Padding.Two + headlineLabel.setFontStyle(.RegularTitleXLarge) + messageLabel.setFontStyle(.RegularTitleMedium) + spaceBetweenLabelsConstant = Padding.Four } public func styleListItem() { @@ -72,8 +72,8 @@ open class HeadlineBody: View { } public func styleListItemDivider() { - headlineLabel.setFontStyle(.BoldTitleSmall) - messageLabel.setFontStyle(.RegularBodySmall) + headlineLabel.setFontStyle(.BoldTitleLarge) + messageLabel.setFontStyle(.RegularBodyLarge) spaceBetweenLabelsConstant = Padding.Two } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 76e26f77..093528d1 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -6,8 +6,8 @@ // Copyright © 2019 Suresh, Kamlesh. All rights reserved. // - -@objcMembers open class HeadlineBodyModel: ParentMoleculeModelProtocol { +import MVMCore +open class HeadlineBodyModel: ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -90,3 +90,24 @@ try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } } + +public extension HeadlineBodyModel { + func createHeaderTitleLockupModel(defaultStyle: Style = .header) throws -> TitleLockupModel { + guard let headline = headline else { throw ModelRegistry.Error.decoderOther(message: "headline is required for this use case.") } + var body = self.body + switch style ?? defaultStyle { + case .landingHeader: + headline.fontStyle = Styler.Font.RegularTitle2XLarge + body?.fontStyle = Styler.Font.RegularTitleMedium + case .itemHeader: + headline.fontStyle = Styler.Font.BoldTitleLarge + body?.fontStyle = Styler.Font.RegularBodyLarge + default: + headline.fontStyle = Styler.Font.RegularTitleXLarge + body?.fontStyle = Styler.Font.RegularTitleMedium + } + let model = try TitleLockupModel(title: headline, subTitle: body) + model.id = id + return model + } +} diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 421c2e95..c4f7d825 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -55,6 +55,9 @@ open class Carousel: View { /// The view that we use for paging public var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? + /// The pagingView anchor to the bottom of the carousel. Disabled when the pagingView is hidden. + public var pagingBottomPin: NSLayoutConstraint? + /// If the carousel should loop after scrolling past the first and final cells. public var loop = false @@ -89,10 +92,10 @@ open class Carousel: View { // Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled. guard let model = model as? CarouselModel, !model.molecules.isEmpty, (model.paging == true || loop == true) else { return } - DispatchQueue.main.async { - self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false) - self.collectionView.layoutIfNeeded() - self.showPeaking(true) + DispatchQueue.main.async { [self] in + collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: false) + collectionView.layoutIfNeeded() + showPeaking(true) } } @@ -137,6 +140,16 @@ open class Carousel: View { (cell as? MVMCoreViewProtocol)?.updateView(size) } layoutCollection() + + // Check must be dispatched to main for the layout to complete in layoutCollection. + DispatchQueue.main.async { [self] in + let shouldHidePager = molecules?.count ?? 0 < 2 || collectionView.contentSize.width < bounds.width + if let pagingView = pagingView, shouldHidePager != pagingView.isHidden { + pagingView.isHidden = shouldHidePager + pagingBottomPin?.isActive = !shouldHidePager + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + } + } } //-------------------------------------------------- @@ -276,7 +289,8 @@ open class Carousel: View { addSubview(pagingView) pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true + pagingBottomPin = bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor) + pagingBottomPin?.isActive = true bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.priority = .defaultLow bottomPin?.isActive = true diff --git a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift index fcbd07d1..1bcc78c6 100644 --- a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift @@ -21,7 +21,9 @@ public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtoc } extension VDSMoleculeViewProtocol { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + self.model = model guard let castedModel = model as? ViewModel else { return } self.delegateObject = delegateObject self.additionalData = additionalData diff --git a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift index e1713b01..daf022a8 100644 --- a/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/ListPageTemplateModel.swift @@ -18,6 +18,8 @@ public var line: LineModel? public var scrollToRowIndex: Int? public var singleCellSelection: Bool = false + public var footerlessSpacerHeight: CGFloat? + public var footerlessSpacerColor: Color? public override var rootMolecules: [MoleculeModelProtocol] { if let molecules = molecules { @@ -60,6 +62,8 @@ case line case scrollToRowIndex case singleCellSelection + case footerlessSpacerHeight + case footerlessSpacerColor } //-------------------------------------------------- @@ -74,6 +78,8 @@ if let singleCellSelection = try typeContainer.decodeIfPresent(Bool.self, forKey: .singleCellSelection) { self.singleCellSelection = singleCellSelection } + footerlessSpacerColor = try typeContainer.decodeIfPresent(Color.self, forKey: .footerlessSpacerColor) + footerlessSpacerHeight = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .footerlessSpacerHeight) try super.init(from: decoder) try validateModelHasContent() } @@ -85,5 +91,7 @@ try container.encode(line, forKey: .line) try container.encode(singleCellSelection, forKey: .singleCellSelection) try container.encodeIfPresent(scrollToRowIndex, forKey: .scrollToRowIndex) + try container.encodeIfPresent(footerlessSpacerColor, forKey: .footerlessSpacerColor) + try container.encodeIfPresent(footerlessSpacerHeight, forKey: .footerlessSpacerHeight) } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index c00e5181..63d592ce 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -69,16 +69,21 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol return molecule } - override open func viewForBottom() -> UIView { - guard let footerModel = templateModel?.footer, - let molecule = generateMoleculeView(from: footerModel) - else { - let view = super.viewForBottom() - view.backgroundColor = templateModel?.backgroundColor?.uiColor ?? .clear - return view + open override func viewForBottom() -> UIView { + // If there is a footer molecule return the molecule. + if let footerModel = templateModel?.footer, + let molecule = generateMoleculeView(from: footerModel) { + return molecule } - - return molecule + // Otherwise setup a bottom spacer view. + let view: UIView + if let footerlessSpacerHeight = templateModel?.footerlessSpacerHeight { + view = MVMCoreUICommonViewsUtility.getView(with: footerlessSpacerHeight <= 0.5 ? 0.5 : footerlessSpacerHeight) + } else { + view = super.viewForBottom() + } + view.backgroundColor = templateModel?.footerlessSpacerColor?.uiColor ?? templateModel?.backgroundColor?.uiColor ?? .clear + return view } open override func handleNewData() { @@ -198,7 +203,29 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { guard let tableView = tableView else { return } + let id = molecule.model?.id + // Check for header + var inHeaderOrFooter = false + if let _ = templateModel?.header?.findFirstMolecule(by: { compareModel in id == compareModel.id }) { + showHeader(nil) + inHeaderOrFooter = true + } + + // Check for footer + if let _ = templateModel?.footer?.findFirstMolecule(by: { compareModel in id == compareModel.id }) { + showFooter(nil) + inHeaderOrFooter = true + } + + // If the view is in a header or footer, need to update the constraints. + if inHeaderOrFooter { + view.setNeedsUpdateConstraints() + view.updateConstraintsIfNeeded() + return + } + + // If the view is in a cell, refresh the table ui. let point = molecule.convert(molecule.bounds.origin, to: tableView) if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false { refreshTable()