Merge branch 'feature/new_loading_spinner' into 'develop'

New loading spinner

See merge request BPHV_MIPS/mvm_core_ui!465
This commit is contained in:
Pfeil, Scott Robert 2020-07-07 14:56:31 -04:00
commit 02e0d9711e
4 changed files with 310 additions and 23 deletions

View File

@ -72,6 +72,8 @@
0A25209824645B76000FA9F6 /* TextViewEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */; };
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; };
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */; };
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A51F3E02475CB73002E08B6 /* LoadingSpinnerModel.swift */; };
0A51F3E32475CB73002E08B6 /* LoadingSpinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A51F3E12475CB73002E08B6 /* LoadingSpinner.swift */; };
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */; };
0A6682A22434DB4F00AD3CA1 /* ListLeftVariableRadioButtonBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682A12434DB4F00AD3CA1 /* ListLeftVariableRadioButtonBodyText.swift */; };
0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682A32434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift */; };
@ -529,6 +531,8 @@
0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewEntryFieldModel.swift; sourceTree = "<group>"; };
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = "<group>"; };
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryField.swift; sourceTree = "<group>"; };
0A51F3E02475CB73002E08B6 /* LoadingSpinnerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingSpinnerModel.swift; sourceTree = "<group>"; };
0A51F3E12475CB73002E08B6 /* LoadingSpinner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingSpinner.swift; sourceTree = "<group>"; };
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = "<group>"; };
0A6682A12434DB4F00AD3CA1 /* ListLeftVariableRadioButtonBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonBodyText.swift; sourceTree = "<group>"; };
0A6682A32434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonBodyTextModel.swift; sourceTree = "<group>"; };
@ -1797,6 +1801,8 @@
94382085243238D100B43AF3 /* WebViewModel.swift */,
943820832432382400B43AF3 /* WebView.swift */,
D20492A524329CE200A5EED6 /* LoadImageView.swift */,
0A51F3E02475CB73002E08B6 /* LoadingSpinnerModel.swift */,
0A51F3E12475CB73002E08B6 /* LoadingSpinner.swift */,
);
path = Views;
sourceTree = "<group>";
@ -2411,6 +2417,7 @@
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */,
@ -2440,6 +2447,7 @@
0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */,
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */,
D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */,
0A51F3E32475CB73002E08B6 /* LoadingSpinner.swift in Sources */,
BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */,
012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */,
94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */,

View File

@ -0,0 +1,213 @@
//
// LoadingSpinner.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 5/20/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
open class LoadingSpinner: View {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var strokeColor: UIColor = .mvmBlack
public var lineWidth: CGFloat = 4.0
public var speed: Float = 1.5
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
public var heightConstraint: NSLayoutConstraint?
public var widthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
override open var layer: CAShapeLayer {
get { return super.layer as! CAShapeLayer }
}
override open class var layerClass: AnyClass {
return CAShapeLayer.self
}
open override func setupView() {
super.setupView()
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
widthConstraint = widthAnchor.constraint(equalToConstant: 0)
}
override open func layoutSubviews() {
super.layoutSubviews()
layer.fillColor = nil
layer.strokeColor = strokeColor.cgColor
layer.lineWidth = lineWidth
layer.lineCap = .butt
layer.speed = speed
let halfWidth = lineWidth / 2
let radius = (bounds.width - lineWidth) / 2
layer.path = UIBezierPath(arcCenter: CGPoint(x: radius + halfWidth,
y: radius + halfWidth),
radius: radius,
startAngle: -CGFloat.pi / 2,
endAngle: 2 * CGFloat.pi,
clockwise: true).cgPath
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
layer.removeAllAnimations()
animate()
}
public override func reset() {
super.reset()
layer.removeAllAnimations()
heightConstraint?.isActive = false
widthConstraint?.isActive = false
}
//--------------------------------------------------
// MARK: - Animation
//--------------------------------------------------
override open func didMoveToWindow() {
animate()
}
struct Pose {
/// Delayed time (in seconds) to execute after the previous Pose.
let delay: CFTimeInterval
/// The time into the animation to begin drawing.
let startTime: CGFloat
/// The length of the drawn line.
let length: CGFloat
}
// TODO: This needs more attention to improve frame smoothness.
class var poses: [Pose] {
get {
return [
Pose(delay: 0.0, startTime: 0.000, length: 0.7),
Pose(delay: 0.7, startTime: 0.500, length: 0.5),
Pose(delay: 0.6, startTime: 1.000, length: 0.3),
Pose(delay: 0.5, startTime: 1.500, length: 0.2),
Pose(delay: 0.5, startTime: 1.875, length: 0.2),
Pose(delay: 0.3, startTime: 2.250, length: 0.3),
Pose(delay: 0.2, startTime: 2.600, length: 0.5),
Pose(delay: 0.2, startTime: 3.000, length: 0.7)
]
}
}
private func animate() {
var time: CFTimeInterval = 0
var times = [CFTimeInterval]()
var start: CGFloat = 0
var rotations = [CGFloat]()
var strokeEnds = [CGFloat]()
let poses = Self.poses
var totalSeconds: CFTimeInterval = poses.reduce(0) { $0 + $1.delay }
for pose in poses {
time += pose.delay
times.append(time / totalSeconds)
start = pose.startTime
rotations.append(start * 2 * CGFloat.pi)
strokeEnds.append(pose.length)
}
totalSeconds += 0.3
animateKeyPath(keyPath: "strokeEnd", duration: totalSeconds, times: times, values: strokeEnds)
animateKeyPath(keyPath: "transform.rotation", duration: totalSeconds, times: times, values: rotations)
}
private func animateKeyPath(keyPath: String, duration: CFTimeInterval, times: [CFTimeInterval], values: [CGFloat]) {
let animation = CAKeyframeAnimation(keyPath: keyPath)
animation.keyTimes = times as [NSNumber]?
animation.values = values
animation.calculationMode = .linear
animation.timingFunction = CAMediaTimingFunction(name: .linear)
animation.duration = duration
animation.rotationMode = .rotateAuto
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
animation.repeatCount = .infinity
layer.add(animation, forKey: animation.keyPath)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
func resumeSpinnerAfterDelay() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
self?.resumeAnimations()
}
}
func pauseAnimations() {
let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil)
layer.speed = 0
isHidden = true
layer.timeOffset = pausedTime
}
func resumeAnimations() {
let pausedTime = layer.timeOffset
isHidden = false
layer.speed = speed
layer.timeOffset = 0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
layer.beginTime = timeSincePause
}
func stopAllAnimations() {
layer.removeAllAnimations()
}
func pinWidthAndHeight(diameter: CGFloat) {
let dimension = diameter + lineWidth
heightConstraint?.constant = dimension
widthConstraint?.constant = dimension
heightConstraint?.isActive = true
widthConstraint?.isActive = true
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? LoadingSpinnerModel else { return }
strokeColor = model.strokeColor.uiColor
lineWidth = model.lineWidth
pinWidthAndHeight(diameter: model.diameter)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 40.0
}
}

View File

@ -0,0 +1,65 @@
//
// LoadingSpinnerModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 5/20/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class LoadingSpinnerModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var backgroundColor: Color?
public static var identifier: String = "loadingSpinner"
public var strokeColor = Color(uiColor: .mvmBlack)
public var lineWidth: CGFloat = 4
public var diameter: CGFloat = 40
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case strokeColor
case lineWidth
case diameter
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) {
self.diameter = diameter
}
if let strokeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .strokeColor) {
self.strokeColor = strokeColor
}
if let lineWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .lineWidth) {
self.lineWidth = lineWidth
}
}
public 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)
try container.encodeIfPresent(diameter, forKey: .diameter)
try container.encode(strokeColor, forKey: .strokeColor)
try container.encode(lineWidth, forKey: .lineWidth)
}
}

View File

@ -48,12 +48,12 @@ import Foundation
/// Call to register all of the CoreUI molecules.
public static func registerObjects() {
// Stacks
// MARK:- Stacks
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: StackModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self)
// Label
// MARK:- Label
MoleculeObjectMapping.shared()?.register(viewClass: Label.self, viewModelClass: LabelModel.self)
// need to move labelattributemodel to different method
try? ModelRegistry.register(LabelAttributeFontModel.self)
@ -63,24 +63,24 @@ import Foundation
try? ModelRegistry.register(LabelAttributeStrikeThroughModel.self)
try? ModelRegistry.register(LabelAttributeActionModel.self)
// TextView
// MARK:- TextView
MoleculeObjectMapping.shared()?.register(viewClass: TextViewEntryField.self, viewModelClass: TextViewEntryFieldModel.self)
// Buttons
// MARK:- Buttons
MoleculeObjectMapping.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ExternalLink.self, viewModelClass: ExternalLinkModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: CaretLink.self, viewModelClass: CaretLinkModel.self)
// Entry Field
// MARK:- Entry Field
MoleculeObjectMapping.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MdnEntryField.self, viewModelClass: MdnEntryFieldModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: DigitEntryField.self, viewModelClass: DigitEntryFieldModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ItemDropdownEntryField.self, viewModelClass: ItemDropdownEntryFieldModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: DateDropdownEntryField.self, viewModelClass: DateDropdownEntryFieldModel.self)
// Selectors
// MARK:- Selectors
MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
@ -90,7 +90,7 @@ import Foundation
// Other Atoms
// MARK:- Other Atoms
MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MultiProgress.self, viewModelClass: MultiProgressBarModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: CaretView.self, viewModelClass: CaretViewModel.self)
@ -103,14 +103,15 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: RadioButtonLabel.self, viewModelClass: RadioButtonLabelModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: WebView.self, viewModelClass: WebViewModel.self)
// Horizontal Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: LoadingSpinner.self, viewModelClass: LoadingSpinnerModel.self)
// MARK:- Horizontal Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: TwoLinkView.self, viewModelClass: TwoLinkViewModel.self)
// Vertical Combination Molecules
// MARK:- Vertical Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: HeadLineBodyCaretLinkImage.self, viewModelClass: HeadlineBodyCaretLinkImageModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: EyebrowHeadlineBodyLink.self, viewModelClass: EyebrowHeadlineBodyLinkModel.self)
@ -119,7 +120,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: BGImageHeadlineBodyButton.self, viewModelClass: BGImageHeadlineBodyButtonModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ThreeHeadlineBodyLink.self, viewModelClass: ThreeHeadlineBodyLinkModel.self)
// Left Right Molecules
// MARK:- Left Right Molecules
MoleculeObjectMapping.shared()?.register(viewClass: CornerLabels.self, viewModelClass: CornerLabelsModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: LeftRightLabelView.self, viewModelClass: LeftRightLabelModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: LabelToggle.self, viewModelClass: LabelToggleModel.self)
@ -127,21 +128,21 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBodyLinkToggle.self, viewModelClass: HeadlineBodyLinkToggleModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ActionDetailWithImage.self, viewModelClass: ActionDetailWithImageModel.self)
// List items
// MARK:- List items
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeTableViewCell.self, viewModelClass: MoleculeListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: DropDownFilterTableViewCell.self, viewModelClass: DropDownListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: AccordionMoleculeTableViewCell.self, viewModelClass: AccordionListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: TabsTableViewCell.self, viewModelClass: TabsListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListProgressBarData.self, viewModelClass: ListProgressBarDataModel.self)
// Other Items
// MARK:- Other Items
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackItem.self, viewModelClass: MoleculeStackItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: StackItem.self, viewModelClass: StackItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: MoleculeCollectionItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: CarouselItem.self, viewModelClass: CarouselItemModel.self)
// Other Container Molecules
// MARK:- Other Container Molecules
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeContainer.self, viewModelClass: MoleculeContainerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self)
@ -149,7 +150,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self)
// Other Molecules
// MARK:- Other Molecules
MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self)
// Navigation Molecules
@ -157,12 +158,12 @@ import Foundation
try? ModelRegistry.register(NavigationImageButtonModel.self)
try? ModelRegistry.register(NavigationLabelButtonModel.self)
// Other Organisms
// MARK:- Other Organisms
MoleculeObjectMapping.shared()?.register(viewClass: Carousel.self, viewModelClass: CarouselModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: BarsIndicatorView.self, viewModelClass: BarsCarouselIndicatorModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: NumericIndicatorView.self, viewModelClass: NumericCarouselIndicatorModel.self)
// Designed List Items
// MARK:- Designed List Items
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableIconWithRightCaret.self, viewModelClass: ListLeftVariableIconWithRightCaretModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableIconWithRightCaretBodyText.self, viewModelClass: ListLeftVariableIconWithRightCaretBodyTextModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self)
@ -192,7 +193,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListProgressBarThin.self, viewModelClass: ListProgressBarThinModel.self)
// Designed Section Dividers
// MARK:- Designed Section Dividers
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnTextWithWhitespaceDividerShort.self, viewModelClass: ListOneColumnTextWithWhitespaceDividerShortModel.self)
@ -204,7 +205,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnBillChangesDivider.self, viewModelClass: ListThreeColumnBillChangesDividerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsageDivider.self, viewModelClass: ListThreeColumnDataUsageDividerModel.self)
// Designed Headers
// MARK:- Designed Headers
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH1Button.self, viewModelClass: HeadersH1ButtonModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH1LandingPageHeader.self, viewModelClass: HeadersH1LandingPageHeaderModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self)
@ -214,14 +215,14 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Link.self, viewModelClass: HeadersH2LinkModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2CaretLink.self, viewModelClass: HeadersH2CaretLinkModel.self)
// Device Items
// MARK:- Device Items
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonSmall.self, viewModelClass: ListDeviceComplexButtonSmallModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkSmall.self, viewModelClass: ListDeviceComplexLinkSmallModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self)
// Helper models
// MARK:- Helper models
try? ModelRegistry.register(RuleRequiredModel.self)
try? ModelRegistry.register(RuleAnyRequiredModel.self)
try? ModelRegistry.register(RuleAnyValueChangedModel.self)
@ -230,12 +231,12 @@ import Foundation
try? ModelRegistry.register(RuleEqualsIgnoreCaseModel.self)
try? ModelRegistry.register(RuleRegexModel.self)
// Actions
// MARK:- Actions
try? ModelRegistry.register(ActionTopAlertModel.self)
try? ModelRegistry.register(ActionCollapseNotificationModel.self)
try? ModelRegistry.register(ActionOpenPanelModel.self)
// Behaviors
// MARK:- Behaviors
try? ModelRegistry.register(ScreenBrightnessModifierBehavior.self)
}