diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitBox.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitBox.swift index ba04f482..7dce16a4 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitBox.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/DigitBox.swift @@ -74,23 +74,6 @@ import UIKit private weak var widthConstraint: NSLayoutConstraint? private weak var heightConstraint: NSLayoutConstraint? - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - @objc public override init(frame: CGRect) { - super.init(frame: frame) - } - - @objc public convenience init() { - self.init(frame: .zero) - } - - @objc required public init?(coder: NSCoder) { - super.init(coder: coder) - fatalError("DigitBox does not support xibs.") - } - //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/ItemDropdownEntryField.swift index ddc459c3..47c59dae 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/ItemDropdownEntryField.swift @@ -81,7 +81,9 @@ open class ItemDropdownEntryField: BaseDropdownEntryField { guard !pickerData.isEmpty else { return } if setInitialValueInTextField, let pickerIndex = pickerView?.selectedRow(inComponent: 0) { + observeDropdownChange?(text ?? "", pickerData[pickerIndex]) text = pickerData[pickerIndex] + itemDropdownEntryFieldModel?.selectedIndex = pickerIndex } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Arrow.swift b/MVMCoreUI/Atomic/Atoms/Views/Arrow.swift index 13c4ff36..d80c1882 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Arrow.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Arrow.swift @@ -79,18 +79,6 @@ open class Arrow: View { widthConstraint?.isActive = true } - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift index 281c306d..88ee69be 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift @@ -73,30 +73,6 @@ layoutIfNeeded() } - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - public override init(frame: CGRect) { - super.init(frame: frame) - setupView() - } - - public convenience init() { - self.init(frame: .zero) - } - - public convenience init(position: CheckboxPosition) { - self.init(frame: .zero) - - alignCheckbox(position) - } - - required public init?(coder: NSCoder) { - super.init(coder: coder) - fatalError("xib file is not implemented for CheckboxLabel") - } - //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/DashLine.swift b/MVMCoreUI/Atomic/Atoms/Views/DashLine.swift index c8a59c6d..c5a6c09e 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/DashLine.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/DashLine.swift @@ -24,22 +24,6 @@ open class DashLine: View { @objc private var dashLayer: CAShapeLayer? - //------------------------------------------------------ - // MARK: - Initializer - //------------------------------------------------------ - - public override init(frame: CGRect) { - super.init(frame: .zero) - } - - public convenience init() { - self.init(frame: .zero) - } - - required public init?(coder: NSCoder) { - super.init(coder: coder) - } - //------------------------------------------------------ // MARK: - Lifecycle //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift index aca7113f..0fa3dc40 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LeftRightLabelView.swift @@ -46,22 +46,6 @@ rightTextLabelLeading?.isActive = false } - //------------------------------------------------------ - // MARK: - Initialization - //------------------------------------------------------ - - public convenience init() { - self.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - override open func setupView() { super.setupView() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift index d41b9022..3bd34674 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H1/HeadersH1Button.swift @@ -14,19 +14,9 @@ import Foundation //-------------------------------------------------- public let headlineBody = HeadlineBody(frame: .zero) public let buttons = TwoButtonView(frame: .zero) - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - public override init(frame: CGRect) { - stack = Stack.createStack(with: [headlineBody, buttons], spacing: Padding.Eighteen) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var stack: Stack = { + return Stack.createStack(with: [headlineBody, buttons], spacing: Padding.Eighteen) + }() //------------------------------------------------------- // MARK: - View Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift index 5cf8bba1..8604a56b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Buttons.swift @@ -16,20 +16,9 @@ import Foundation public let headlineBody = HeadlineBody() public let buttons = TwoButtonView() - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - - public override init(frame: CGRect) { - stack = Stack.createStack(with: [headlineBody, buttons], spacing: PaddingDefaultVerticalSpacing3) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var stack: Stack = { + return Stack.createStack(with: [headlineBody, buttons], spacing: PaddingDefaultVerticalSpacing3) + }() //------------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift index 1aaf092f..c641ac97 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLink.swift @@ -13,19 +13,9 @@ import Foundation //-------------------------------------------------- public let headlineBody = HeadlineBody() public let caretLink = CaretLink() - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - public override init(frame: CGRect) { - stack = Stack.createStack(with: [headlineBody, caretLink]) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var stack: Stack = { + return Stack.createStack(with: [headlineBody, caretLink]) + }() //------------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift index c5aaefc8..e90a51f2 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift @@ -14,19 +14,9 @@ import Foundation //-------------------------------------------------- public let headlineBody = HeadlineBody() public let link = Link() - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - public override init(frame: CGRect) { - stack = Stack.createStack(with: [headlineBody, link]) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var stack: Stack = { + return Stack.createStack(with: [headlineBody, link]) + }() //------------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift index 12097880..a6d69e24 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2PricingTwoRows.swift @@ -21,31 +21,26 @@ import Foundation public let subBody3 = Label(fontStyle: .RegularMicro) public let verticalLine1 = Line() public let verticalLine2 = Line() - public let verticalStack1: Stack - public let verticalStack2: Stack - public let verticalStack3: Stack - public let horizontalStack: Stack - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - public override init(frame: CGRect) { - verticalStack1 = Stack.createStack(with: [body, subBody], spacing: 0) - verticalStack2 = Stack.createStack(with: [body2, subBody2], spacing: 0) - verticalStack3 = Stack.createStack(with: [body3, subBody3], spacing: 0) - horizontalStack = Stack.createStack(with: [(view: verticalStack1, model: StackItemModel(percent: 29, verticalAlignment: .top)), (view: verticalLine1, model: StackItemModel(verticalAlignment: .top)), - (view: verticalStack2, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .top)), - (view: verticalLine2, model: StackItemModel(verticalAlignment: .top)), - (view: verticalStack3, model: StackItemModel(percent: 32, verticalAlignment: .top))], - axis: .horizontal) - stack = Stack.createStack(with: [headline, horizontalStack], spacing: 8) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var verticalStack1: Stack = { + return Stack.createStack(with: [body, subBody], spacing: 0) + }() + public lazy var verticalStack2: Stack = { + return Stack.createStack(with: [body2, subBody2], spacing: 0) + }() + public lazy var verticalStack3: Stack = { + return Stack.createStack(with: [body3, subBody3], spacing: 0) + }() + public lazy var horizontalStack: Stack = { + return Stack.createStack(with: [(view: verticalStack1, model: StackItemModel(percent: 29, verticalAlignment: .top)), + (view: verticalLine1, model: StackItemModel(verticalAlignment: .top)), + (view: verticalStack2, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .top)), + (view: verticalLine2, model: StackItemModel(verticalAlignment: .top)), + (view: verticalStack3, model: StackItemModel(percent: 32, verticalAlignment: .top))], + axis: .horizontal) + }() + public lazy var stack: Stack = { + return Stack.createStack(with: [headline, horizontalStack], spacing: 8) + }() //------------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift index 2ec507b9..77a44761 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButton.swift @@ -16,22 +16,11 @@ import Foundation public let headlineBody = HeadlineBody() public let button = PillButton() - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - - public override init(frame: CGRect) { - stack = Stack.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), - (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], - axis: .vertical) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var stack: Stack = { + return Stack.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), + (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], + axis: .vertical) + }() //------------------------------------------------------ // MARK: - Constants diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNames.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNames.swift index e947322f..fd776ebb 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNames.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockUpsPlanNames.swift @@ -15,21 +15,11 @@ import Foundation public let headline = Label(fontStyle: .Title2XLarge) public let subHeadline = Label(fontStyle: .RegularTitleLarge) public let body = Label(fontStyle: .RegularBodySmall) - public let stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - public override init(frame: CGRect) { - stack = Stack.createStack(with: [(view: headline, model: StackItemModel()), - (view: subHeadline, model: StackItemModel(spacing: 16)), - (view: body, model: StackItemModel(spacing: 8))]) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var stack: Stack = { + return Stack.createStack(with: [(view: headline, model: StackItemModel()), + (view: subHeadline, model: StackItemModel(spacing: 16)), + (view: body, model: StackItemModel(spacing: 8))]) + }() //------------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXL.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXL.swift index 8312e5da..c0d4c44f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXL.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/LockupsPlanSMLXL.swift @@ -16,26 +16,17 @@ import Foundation public let headline = Label(fontStyle: .BoldTitleLarge) public let subHeadline = Label(fontStyle: .RegularTitleLarge) public let body = Label(fontStyle: .RegularBodySmall) - public let verticalStack: Stack - public var stack: Stack - - //------------------------------------------------------- - // MARK: - Initializers - //------------------------------------------------------- - public override init(frame: CGRect) { - verticalStack = Stack.createStack(with: [(view: headline, model: StackItemModel()), - (view: subHeadline, model: StackItemModel()), - (view: body, model: StackItemModel(horizontalAlignment: .fill))], - axis: .vertical, spacing: 0) - stack = Stack.createStack(with: [(view: planLabel, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading)), - (view: verticalStack, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading))], - axis: .horizontal) - super.init(frame: frame) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public lazy var verticalStack: Stack = { + return Stack.createStack(with: [(view: headline, model: StackItemModel()), + (view: subHeadline, model: StackItemModel()), + (view: body, model: StackItemModel(horizontalAlignment: .fill))], + axis: .vertical, spacing: 0) + }() + public lazy var stack: Stack = { + return Stack.createStack(with: [(view: planLabel, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading)), + (view: verticalStack, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading))], + axis: .horizontal) + }() //------------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift index db57f977..18de25f1 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift @@ -49,22 +49,6 @@ open class DoughnutChart: View { } } - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - public override init(frame: CGRect) { - super.init(frame: .zero) - } - - public convenience init() { - self.init(frame: .zero) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift index d415971e..918871e7 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift @@ -15,19 +15,6 @@ import UIKit var delegateObject: MVMCoreUIDelegateObject? let label = Label() - // MARK: - Inits - public init() { - super.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - public override func updateView(_ size: CGFloat) { super.updateView(size) radioButton.updateView(size) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 31420e56..29fb22e8 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -23,22 +23,6 @@ import UIKit private var equalWidthConstraint: NSLayoutConstraint? - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - public init() { - super.init(frame: .zero) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift index fbc56b0b..09a09dcd 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoLinkView.swift @@ -17,22 +17,6 @@ import Foundation open var leftLink = Link() open var rightLink = Link() private var stack = UIStackView() - - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - public init() { - super.init(frame: .zero) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } //-------------------------------------------------- // MARK: - MVMCoreViewProtocol diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift index ab0924b2..74543d21 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift @@ -29,22 +29,6 @@ import UIKit var imageLeadingConstraint: NSLayoutConstraint? - //------------------------------------------------------ - // MARK: - Initialization - //------------------------------------------------------ - - public init() { - super.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - //------------------------------------------------------ // MARK: - View Lifecycle //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift index 4e2c6279..d6b795ce 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift @@ -11,11 +11,11 @@ import UIKit open class MoleculeContainer: Container { /// Can be overriden to change how the molecule is added to the hierarchy. - public func addMolecule(_ molecule: UIView) { + open func addMolecule(_ molecule: UIView) { addAndContain(molecule) } - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { if let casteModel = model as? MoleculeContainerModelProtocol { if view != nil { (view as? MoleculeViewProtocol)?.set(with: casteModel.molecule, delegateObject, additionalData) diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift index aa847f88..77b40716 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift @@ -9,7 +9,7 @@ import Foundation open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol { - public class var identifier: String { + open class var identifier: String { return "container" } public var backgroundColor: Color? @@ -41,7 +41,7 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco try super.init(from: decoder) } - 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(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift index 804bfeb6..17b1aef7 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift @@ -8,7 +8,7 @@ import Foundation -public class CollapsableNotificationModel: NotificationModel { +open class CollapsableNotificationModel: NotificationModel { public class override var identifier: String { return "collapsableNotification" } @@ -19,12 +19,12 @@ public class CollapsableNotificationModel: NotificationModel { public var initiallyCollapsed = false public var pages: [String]? - init(with topLabel: LabelModel, headline: LabelModel) { + public init(with topLabel: LabelModel, headline: LabelModel) { self.topLabel = topLabel super.init(with: headline) } - override func setDefault() { + open override func setDefault() { super.setDefault() if topLabel.textColor == nil { topLabel.textColor = Color(uiColor: .white) @@ -61,7 +61,7 @@ public class CollapsableNotificationModel: NotificationModel { try super.init(from: decoder) } - 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(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift index e2f94326..70ff00bb 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift @@ -8,7 +8,7 @@ import Foundation -public class NotificationModel: MoleculeModelProtocol { +open class NotificationModel: MoleculeModelProtocol { public class var identifier: String { return "notification" } @@ -18,11 +18,11 @@ public class NotificationModel: MoleculeModelProtocol { public var button: ButtonModel? public var closeButton: NotificationXButtonModel? - init(with headline: LabelModel) { + public init(with headline: LabelModel) { self.headline = headline } - func setDefault() { + open func setDefault() { if backgroundColor == nil { backgroundColor = Color(uiColor: .mvmGreen()) } @@ -59,7 +59,7 @@ public class NotificationModel: MoleculeModelProtocol { setDefault() } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift index 5170d8f2..90d31af0 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift @@ -29,22 +29,6 @@ import UIKit var buttonTopConstraint: NSLayoutConstraint? - //------------------------------------------------------ - // MARK: - Initialization - //------------------------------------------------------ - - public convenience init() { - self.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - //------------------------------------------------------ // MARK: - View Lifecycle //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift index 3c97e988..4fb125c4 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift @@ -36,6 +36,13 @@ open class StringAndMoleculeView: View { fatalError("init(coder:) has not been implemented") } + public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + let moleculeModel = model as? StringAndMoleculeModel + label.text = moleculeModel?.string + self.molecule = moleculeModel?.molecule as! MoleculeViewProtocol + super.init(model: model, delegateObject, additionalData) + } + override public func setupView() { super.setupView() guard subviews.count == 0 else { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLink.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLink.swift index 5926951f..ae7d8dab 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLink.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/ThreeHeadlineBodyLink.swift @@ -20,22 +20,6 @@ open class ThreeHeadlineBodyLink: View { public let body = Label(fontStyle: .RegularBodySmall) public let link = Link() - //------------------------------------------------------ - // MARK: - Initialization - //------------------------------------------------------ - - public convenience init() { - self.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - //------------------------------------------------------ // MARK: - Lifecycle //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Organisms/Stack.swift b/MVMCoreUI/Atomic/Organisms/Stack.swift index ad961586..7b31e45a 100644 --- a/MVMCoreUI/Atomic/Organisms/Stack.swift +++ b/MVMCoreUI/Atomic/Organisms/Stack.swift @@ -113,6 +113,11 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto fatalError("init(coder:) has not been implemented") } + public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.init(frame: .zero) + set(with: model, delegateObject, additionalData) + } + /// Returns a Stack created with a StackModel and StackItems containing the passed in views. public static func createStack(with views: [UIView], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) -> Stack { var items: [StackItem] = [] diff --git a/MVMCoreUI/BaseClasses/View.swift b/MVMCoreUI/BaseClasses/View.swift index 686985eb..cfb6ff1f 100644 --- a/MVMCoreUI/BaseClasses/View.swift +++ b/MVMCoreUI/BaseClasses/View.swift @@ -43,6 +43,12 @@ import UIKit } } + public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.init(frame: .zero) + initialSetup() + set(with: model, delegateObject, additionalData) + } + //-------------------------------------------------- // MARK: - MoleculeViewProtocol //-------------------------------------------------- diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUIPanelProtocol.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUIPanelProtocol.h index 4537e791..8d381b76 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUIPanelProtocol.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUIPanelProtocol.h @@ -17,7 +17,7 @@ - (BOOL)panelAvailable; // Notified when it is appearing and disappearing. Called by the container. -- (void)willOpenWithActionInformation:(nullable NSDictionary *)actionInformation; +- (void)willOpenWithActionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; - (void)willAppear:(BOOL)animated; - (void)didAppear:(BOOL)animated; - (void)willDisappear:(BOOL)animated; diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index d88641fa..72152c40 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -878,7 +878,7 @@ CGFloat const PanelAnimationDuration = 0.2; // Create bottom progress bar UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; progressView.translatesAutoresizingMaskIntoConstraints = NO; - progressView.tintColor = [UIColor mfTomatoRed]; + progressView.progressTintColor = [UIColor mfTomatoRed]; [self.view addSubview:progressView]; self.bottomProgressBar = progressView; [NSLayoutConstraint constraintWithItem:progressView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:mainView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0].active = YES; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift index 8bf4860f..58a06420 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift @@ -21,38 +21,121 @@ public extension MVMCoreUITopAlertView { NotificationCenter.default.addObserver(self, selector: #selector(viewControllerChanged(notification:)), name: NSNotification.Name(rawValue: MVMCoreNotificationViewControllerChanged), object: nil) } - /// Checks for new top alert json - @objc func responseJSONUpdated(notification: Notification) { - guard let responseJSON = (notification.userInfo?[String(describing: MVMCoreLoadObject.self)] as? MVMCoreLoadObject)?.responseJSON, - let json = responseJSON.optionalDictionaryForKey("TopNotification") else { return } - + private func getDelegateObject() -> MVMCoreUIDelegateObject { // TODO: Top alert view is current delegate. Should move to current view controller eventually? - let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self) - showTopAlert(with: json, delegateObject: delegateObject) + return MVMCoreUIDelegateObject.create(withDelegateForAll: self) + } + + /// Checks for new top alert json + @objc private func responseJSONUpdated(notification: Notification) { + guard let responseJSON = (notification.userInfo?[String(describing: MVMCoreLoadObject.self)] as? MVMCoreLoadObject)?.responseJSON, + let json = responseJSON.optionalDictionaryForKey("TopNotification"), + let model = decodeTopNotification(with: json, delegateObject: getDelegateObject()) else { return } + showTopAlert(with: model) } /// When a detail page changes, check top alerts. - @objc func viewControllerChanged(notification: Notification) { + @objc private func viewControllerChanged(notification: Notification) { guard let controller = MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() as? MVMCoreViewControllerProtocol else { return } - MVMCoreAlertHandler.shared()?.checkPagesDependency(for: controller.pageType) + MVMCoreAlertHandler.shared()?.handleAllPagesDependency(for: controller.pageType) + reevalutePriority() } - /// Shows the top alert with the json payload. - func showTopAlert(with json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) { + /// Re-evaluates the queue priority + private func reevalutePriority() { + guard let operations = MVMCoreAlertHandler.shared()?.topAlertQueue.operations else { return } + var highestReadyOperation: Operation? + var executingOperation: Operation? + for operation in operations { + guard !operation.isCancelled, + !operation.isFinished else { + continue + } + if operation.isReady, + highestReadyOperation == nil || operation.queuePriority.rawValue > highestReadyOperation!.queuePriority.rawValue { + highestReadyOperation = operation + } + if operation.isExecuting { + executingOperation = operation + } + } + + // If the highest priority operation is not executing, and the executing operation is persistent, cancel it. + if let newOperation = highestReadyOperation, + let currentOperation = executingOperation as? MVMCoreTopAlertOperation, + currentOperation != newOperation, + currentOperation.topAlertObject.persistent { + currentOperation.reAddAfterCancel = true + currentOperation.cancel() + } + } + + /// Decodes the json into a TopNotificationModel + private func decodeTopNotification(with json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) -> TopNotificationModel? { do { - let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject) - showTopAlert(with: model, delegateObject: delegateObject) + return try TopNotificationModel.decode(json: json, delegateObject: delegateObject) } catch { if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") { MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) } + return nil } } /// Shows the top alert with the model. - func showTopAlert(with model: TopNotificationModel, delegateObject: MVMCoreUIDelegateObject?) { + func showTopAlert(with model: TopNotificationModel) { let object = model.createTopAlertObject() - MVMCoreAlertHandler.shared()?.showTopAlert(with: object) + guard !checkAndUpdateExisting(with: object), + let operation = MVMCoreTopAlertOperation(topAlertObject: object) else { return } + MVMCoreAlertHandler.shared()?.addPagesDependency(to: operation) + MVMCoreAlertHandler.shared()?.handlePageDependency(for: operation, with: (MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() as? MVMCoreViewControllerProtocol)?.pageType) + MVMCoreAlertHandler.shared()?.add(operation) + } + + /// Checks for existing top alert object of same type and updates it. Only happens for molecular top alerts. Returns true if we updated. + private func checkAndUpdateExisting(with topAlertObject: MVMCoreTopAlertObject) -> Bool { + guard let queue = MVMCoreAlertHandler.shared()?.topAlertQueue.operations else { return false } + for case let operation as MVMCoreTopAlertOperation in queue { + guard topAlertObject.json != nil, + operation.topAlertObject.type == topAlertObject.type else { continue } + operation.update(with: topAlertObject) + MVMCoreAlertHandler.shared()?.updatePages(for: operation, with: topAlertObject) + MVMCoreAlertHandler.shared()?.handlePageDependency(for: operation, with: (MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() as? MVMCoreViewControllerProtocol)?.pageType) + reevalutePriority() + return true + } + return false + } + + /// Updates the current top alert molecule with the new object + @objc func updateMolecule(with topAlertObject: MVMCoreTopAlertObject) { + guard topAlertObject.type == self.topAlertObject?.type else { return } + let delegateObject = getDelegateObject() + guard let newJson = topAlertObject.json, + let newModel = decodeTopNotification(with: newJson, delegateObject: delegateObject), + let newModelName = MoleculeObjectMapping.shared()?.getMoleculeClass(newModel.molecule)?.nameForReuse(with: newModel.molecule, delegateObject), + let currentJson = self.topAlertObject?.json, + let currentModel = decodeTopNotification(with: currentJson, delegateObject: delegateObject), + let currentModelName = MoleculeObjectMapping.shared()?.getMoleculeClass(currentModel.molecule)?.nameForReuse(with: currentModel.molecule, delegateObject), + newModelName == currentModelName, + let molecule = currentAlert as? MoleculeViewProtocol else { + // Log that we couldn't update. + if let errorObject = MVMCoreErrorObject(title: nil, message: nil, messageToLog: nil, code: ErrorCode.parsingJSON.rawValue, domain: ErrorDomainNative, location: "TopNotification update \(String(describing: topAlertObject.type))") { + MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) + } + return + } + MVMCoreDispatchUtility.performBlock(onMainThread: { + // Update molecule + molecule.reset() + molecule.set(with: newModel.molecule, delegateObject, nil) + (molecule as? MVMCoreViewProtocol)?.updateView(self.bounds.width) + + // Update status bar. + guard let statusBarDelegate = molecule as? StatusBarUI else { return } + let statusBarUI = statusBarDelegate.getStatusBarUI() + self.setStatusBarColor(statusBarUI.color, statusBarStyle: statusBarUI.style) + }) } /// Returns the top alert molecule to use and status bar color legacy style. diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h index 82c0a7e9..1979a850 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h @@ -27,6 +27,9 @@ // Current top alert object @property (strong, nullable, nonatomic) MVMCoreTopAlertObject *topAlertObject; +/// Current top alert view. +@property (weak, nullable, nonatomic, readonly) UIView *currentAlert; + // Returns the top alert view + (nullable instancetype)sharedGlobal; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index d54190b0..14f4dee2 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -39,7 +39,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; @property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint; @property (weak, nonatomic) UIView *alertView; -@property (weak, nonatomic) UIView *currentAlert; +@property (weak, nullable, nonatomic, readwrite) UIView *currentAlert; @property (strong, nonatomic) NSLayoutConstraint *height; @property (weak, nonatomic) MVMCoreUITopAlertExpandableView *topAlertClearspotView; @@ -181,6 +181,10 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; }); } +- (void)updateTopAlertWith:(MVMCoreTopAlertObject *)topAlertObject { + [self updateMoleculeWith:topAlertObject]; +} + - (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style { self.statusBarView.backgroundColor = statusBarColor; self.statusBarStyle = style;