Digital PCT265 story ONEAPP-7249 - Prevent UI updates when there are no model changes.
This commit is contained in:
parent
fd296b9623
commit
31096a15a5
@ -172,6 +172,7 @@
|
|||||||
5822720C2B1FC55F00F75BAE /* RotorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5822720A2B1FC55F00F75BAE /* RotorHandler.swift */; };
|
5822720C2B1FC55F00F75BAE /* RotorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5822720A2B1FC55F00F75BAE /* RotorHandler.swift */; };
|
||||||
5846ABF62B4762A600FA6C76 /* PollingBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */; };
|
5846ABF62B4762A600FA6C76 /* PollingBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */; };
|
||||||
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; };
|
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; };
|
||||||
|
58E7561D2BE04C320088BB5D /* MoleculeComparisonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E7561C2BE04C320088BB5D /* MoleculeComparisonProtocol.swift */; };
|
||||||
608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; };
|
608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; };
|
||||||
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */; };
|
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */; };
|
||||||
8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */; };
|
8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */; };
|
||||||
@ -780,6 +781,7 @@
|
|||||||
5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui.xcconfig; sourceTree = "<group>"; };
|
5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui.xcconfig; sourceTree = "<group>"; };
|
||||||
5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui_dev.xcconfig; sourceTree = "<group>"; };
|
5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui_dev.xcconfig; sourceTree = "<group>"; };
|
||||||
58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = "<group>"; };
|
58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = "<group>"; };
|
||||||
|
58E7561C2BE04C320088BB5D /* MoleculeComparisonProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeComparisonProtocol.swift; sourceTree = "<group>"; };
|
||||||
608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = "<group>"; };
|
608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = "<group>"; };
|
||||||
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = "<group>"; };
|
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = "<group>"; };
|
||||||
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = "<group>"; };
|
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = "<group>"; };
|
||||||
@ -1254,6 +1256,7 @@
|
|||||||
D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */,
|
D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */,
|
||||||
27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */,
|
27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */,
|
||||||
27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */,
|
27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */,
|
||||||
|
58E7561C2BE04C320088BB5D /* MoleculeComparisonProtocol.swift */,
|
||||||
);
|
);
|
||||||
path = ModelProtocols;
|
path = ModelProtocols;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -3010,6 +3013,7 @@
|
|||||||
EA1758482BC97ED800A5C0D9 /* BadgeIndicator.swift in Sources */,
|
EA1758482BC97ED800A5C0D9 /* BadgeIndicator.swift in Sources */,
|
||||||
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */,
|
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */,
|
||||||
0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */,
|
0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */,
|
||||||
|
58E7561D2BE04C320088BB5D /* MoleculeComparisonProtocol.swift in Sources */,
|
||||||
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
|
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
|
||||||
AF1C336928859778006B1001 /* ActionAlertHandler.swift in Sources */,
|
AF1C336928859778006B1001 /* ActionAlertHandler.swift in Sources */,
|
||||||
9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */,
|
9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */,
|
||||||
|
|||||||
@ -186,4 +186,20 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
|||||||
try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
|
try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
|
||||||
try container.encodeIfPresent(disabledAccessibilityTraits, forKey: .disabledAccessibilityTraits)
|
try container.encodeIfPresent(disabledAccessibilityTraits, forKey: .disabledAccessibilityTraits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return title == model.title
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& accessibilityIdentifier == model.accessibilityIdentifier
|
||||||
|
&& style == model.style
|
||||||
|
&& size == model.size
|
||||||
|
&& groupName == model.groupName
|
||||||
|
&& width == model.width
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
&& disabledAccessibilityTraits == model.disabledAccessibilityTraits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro
|
|||||||
[image].compactMap({$0})
|
[image].compactMap({$0})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &image, with: molecule)
|
return try replaceChildMolecule(at: &image, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -99,6 +99,19 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
|||||||
try container.encodeIfPresent(size, forKey: .size)
|
try container.encodeIfPresent(size, forKey: .size)
|
||||||
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& title == model.title
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& accessibilityIdentifier == model.accessibilityIdentifier
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& size == model.size
|
||||||
|
&& shouldMaskRecordedView == model.shouldMaskRecordedView
|
||||||
|
// && action.isEqual(to: model.action) // TODO: Move to isVisiuallyEquivalent.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LinkModel {
|
extension LinkModel {
|
||||||
|
|||||||
@ -130,4 +130,20 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
|||||||
try container.encode(indicatorColor, forKey: .indicatorColor)
|
try container.encode(indicatorColor, forKey: .indicatorColor)
|
||||||
try container.encodeIfPresent(position, forKey: .position)
|
try container.encodeIfPresent(position, forKey: .position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& numberOfPages == model.numberOfPages
|
||||||
|
&& currentIndex == model.currentIndex
|
||||||
|
&& alwaysSendAction == model.alwaysSendAction
|
||||||
|
&& animated == model.animated
|
||||||
|
&& hidesForSinglePage == model.hidesForSinglePage
|
||||||
|
&& accessibilityHasSlidesInsteadOfPage == model.accessibilityHasSlidesInsteadOfPage
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& disabledIndicatorColor == model.disabledIndicatorColor
|
||||||
|
&& indicatorColor == model.indicatorColor
|
||||||
|
&& position == model.position
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,4 +48,9 @@ open class LabelAttributeActionModel: LabelAttributeModel {
|
|||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encodeModel(action, forKey: .action)
|
try container.encodeModel(action, forKey: .action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return action.isEqual(to: model.action)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,4 +43,9 @@
|
|||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encodeIfPresent(textColor, forKey: .textColor)
|
try container.encodeIfPresent(textColor, forKey: .textColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return textColor == model.textColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,4 +55,11 @@
|
|||||||
try container.encodeIfPresent(name, forKey: .name)
|
try container.encodeIfPresent(name, forKey: .name)
|
||||||
try container.encodeIfPresent(size, forKey: .size)
|
try container.encodeIfPresent(size, forKey: .size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return style == model.style
|
||||||
|
&& name == model.name
|
||||||
|
&& size == model.size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,4 +69,12 @@ class LabelAttributeImageModel: LabelAttributeModel {
|
|||||||
try container.encodeIfPresent(URL, forKey: .URL)
|
try container.encodeIfPresent(URL, forKey: .URL)
|
||||||
try container.encodeIfPresent(tintColor, forKey: .tintColor)
|
try container.encodeIfPresent(tintColor, forKey: .tintColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return URL == model.URL
|
||||||
|
&& name == model.name
|
||||||
|
&& size == model.size
|
||||||
|
&& tintColor == model.tintColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,4 +75,10 @@
|
|||||||
try container.encode(location, forKey: .location)
|
try container.encode(location, forKey: .location)
|
||||||
try container.encode(length, forKey: .length)
|
try container.encode(length, forKey: .length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return location == model.location
|
||||||
|
&& length == model.length
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,6 +66,13 @@ import UIKit
|
|||||||
try container.encode(style, forKey: .style)
|
try container.encode(style, forKey: .style)
|
||||||
try container.encodeIfPresent(pattern, forKey: .pattern)
|
try container.encodeIfPresent(pattern, forKey: .pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return style == model.style
|
||||||
|
&& color == model.color
|
||||||
|
&& pattern == model.pattern
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum UnderlineStyle: String, Codable {
|
public enum UnderlineStyle: String, Codable {
|
||||||
|
|||||||
@ -132,6 +132,26 @@ import VDS
|
|||||||
try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||||
try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
|
try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& text == model.text
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& textColor == model.textColor
|
||||||
|
&& fontStyle == model.fontStyle
|
||||||
|
&& fontName == model.fontName
|
||||||
|
&& fontSize == model.fontSize
|
||||||
|
&& textAlignment == model.textAlignment
|
||||||
|
&& attributes.areEqual(to: model.attributes)
|
||||||
|
&& html == model.html
|
||||||
|
&& hero == model.hero
|
||||||
|
&& makeWholeViewClickable == model.makeWholeViewClickable
|
||||||
|
&& numberOfLines == model.numberOfLines
|
||||||
|
&& shouldMaskRecordedView == model.shouldMaskRecordedView
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
&& inverted == inverted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LabelModel {
|
extension LabelModel {
|
||||||
|
|||||||
@ -129,4 +129,12 @@ public class LineModel: MoleculeModelProtocol, Invertable {
|
|||||||
try container.encodeIfPresent(frequency, forKey: .frequency)
|
try container.encodeIfPresent(frequency, forKey: .frequency)
|
||||||
try container.encode(orientation == .vertical, forKey: .useVerticalLine)
|
try container.encode(orientation == .vertical, forKey: .useVerticalLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return type == model.type
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& frequency == model.frequency
|
||||||
|
&& orientation == model.orientation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ open class TileContainerModel: TileContainerBaseModel<TileContainer.Padding, Til
|
|||||||
return [molecule]
|
return [molecule]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &self.molecule, with: molecule)
|
return try replaceChildMolecule(at: &self.molecule, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,9 +21,13 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
|
|||||||
[titleLockup, buttons]
|
[titleLockup, buttons]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &buttons, with: molecule)
|
if try replaceChildMolecule(at: &titleLockup, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &buttons, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -24,13 +24,17 @@ public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol
|
|||||||
[headline, headline2, subHeadline, body, link, buttons]
|
[headline, headline2, subHeadline, body, link, buttons]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &headline, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &headline2, with: molecule)
|
if try replaceChildMolecule(at: &headline, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &subHeadline, with: molecule)
|
|| replaceChildMolecule(at: &headline2, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &body, with: molecule)
|
|| replaceChildMolecule(at: &subHeadline, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &link, with: molecule)
|
|| replaceChildMolecule(at: &body, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &buttons, with: molecule)
|
|| replaceChildMolecule(at: &link, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &buttons, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
|||||||
[titleLockup]
|
[titleLockup]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,9 +23,13 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
|
|||||||
[titleLockup, buttons]
|
[titleLockup, buttons]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &buttons, with: molecule)
|
if try replaceChildMolecule(at: &titleLockup, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &buttons, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -20,9 +20,13 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
|
|||||||
[titleLockup, caretLink]
|
[titleLockup, caretLink]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &caretLink, with: molecule)
|
if try replaceChildMolecule(at: &titleLockup, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &caretLink, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
public class HeadersH2LinkModel: HeaderModel, ParentMoleculeModelProtocol {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -22,9 +22,13 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
|
|||||||
[titleLockup, link]
|
[titleLockup, link]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &link, with: molecule)
|
if try replaceChildMolecule(at: &titleLockup, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &link, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -22,7 +22,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
|||||||
[titleLockup]
|
[titleLockup]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,15 +25,19 @@ public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol, P
|
|||||||
[headline, body, subBody, body2, subBody2, body3, subBody3].compactMap({$0})
|
[headline, body, subBody, body2, subBody2, body3, subBody3].compactMap({$0})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &headline, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &body, with: molecule)
|
if try replaceChildMolecule(at: &headline, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &subBody, with: molecule)
|
|| replaceChildMolecule(at: &body, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &body2, with: molecule)
|
|| replaceChildMolecule(at: &subBody, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &body2, with: molecule)
|
|| replaceChildMolecule(at: &body2, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &subBody2, with: molecule)
|
|| replaceChildMolecule(at: &body2, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &body3, with: molecule)
|
|| replaceChildMolecule(at: &subBody2, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &subBody3, with: molecule)
|
|| replaceChildMolecule(at: &body3, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &subBody3, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -23,9 +23,13 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
|
|||||||
[titleLockup, button]
|
[titleLockup, button]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &titleLockup, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &button, with: molecule)
|
if try replaceChildMolecule(at: &titleLockup, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &button, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -20,9 +20,13 @@ open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelPr
|
|||||||
[checkbox, headlineBody]
|
[checkbox, headlineBody]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &checkbox, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &headlineBody, with: molecule)
|
if try replaceChildMolecule(at: &checkbox, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &headlineBody, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -20,9 +20,13 @@ public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModel
|
|||||||
return [image, eyebrowHeadlineBodyLink]
|
return [image, eyebrowHeadlineBodyLink]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &image, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule)
|
if try replaceChildMolecule(at: &image, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -21,10 +21,14 @@ public class ListLeftVariableIconWithRightCaretAllTextLinksModel: ListItemModel,
|
|||||||
return [image, eyebrowHeadlineBodyLink, rightLabel]
|
return [image, eyebrowHeadlineBodyLink, rightLabel]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &image, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule)
|
if try replaceChildMolecule(at: &image, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &rightLabel, with: molecule)
|
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &rightLabel, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|||||||
@ -21,10 +21,14 @@ public class ListLeftVariableIconWithRightCaretBodyTextModel: ListItemModel, Par
|
|||||||
[image, headlineBody, rightLabel]
|
[image, headlineBody, rightLabel]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &image, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &headlineBody, with: molecule)
|
if try replaceChildMolecule(at: &image, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &rightLabel, with: molecule)
|
|| replaceChildMolecule(at: &headlineBody, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &rightLabel, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|||||||
@ -21,10 +21,14 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, ParentMolec
|
|||||||
return [image, leftLabel, rightLabel]
|
return [image, leftLabel, rightLabel]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &image, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &leftLabel, with: molecule)
|
if try replaceChildMolecule(at: &image, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &rightLabel, with: molecule)
|
|| replaceChildMolecule(at: &leftLabel, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &rightLabel, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|||||||
@ -20,9 +20,13 @@ open class ListLeftVariableRadioButtonBodyTextModel: ListItemModel, ParentMolecu
|
|||||||
[radioButton, headlineBody]
|
[radioButton, headlineBody]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &radioButton, with: replacementMolecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &headlineBody, with: replacementMolecule)
|
if try replaceChildMolecule(at: &radioButton, with: replacementMolecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &headlineBody, with: replacementMolecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|||||||
@ -39,7 +39,7 @@ public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeMod
|
|||||||
return [headlineBody]
|
return [headlineBody]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &headlineBody, with: molecule)
|
return try replaceChildMolecule(at: &headlineBody, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,4 +68,9 @@ public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeMod
|
|||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encode(headlineBody, forKey: .headlineBody)
|
try container.encode(headlineBody, forKey: .headlineBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return headlineBody.isEqual(to: headlineBody)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,9 +40,13 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul
|
|||||||
return [button, eyebrowHeadlineBodyLink]
|
return [button, eyebrowHeadlineBodyLink]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &button, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule)
|
if try replaceChildMolecule(at: &button, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -20,9 +20,13 @@ public class ListRightVariableRightCaretAllTextAndLinksModel: ListItemModel, Par
|
|||||||
[rightLabel, eyebrowHeadlineBodyLink]
|
[rightLabel, eyebrowHeadlineBodyLink]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &rightLabel, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule)
|
if try replaceChildMolecule(at: &rightLabel, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &eyebrowHeadlineBodyLink, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
import VDSTokens
|
import VDSTokens
|
||||||
import VDS
|
import VDS
|
||||||
|
|
||||||
public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
public class TitleLockupModel: ParentMoleculeModelProtocol {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
@ -34,10 +34,24 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco
|
|||||||
[eyebrow, title, subTitle].compactMap { (molecule: MoleculeModelProtocol?) in molecule }
|
[eyebrow, title, subTitle].compactMap { (molecule: MoleculeModelProtocol?) in molecule }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &eyebrow, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &title, with: molecule)
|
if try replaceChildMolecule(at: &eyebrow, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &subTitle, with: molecule)
|
|| replaceChildMolecule(at: &title, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &subTitle, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return textAlignment == model.textAlignment
|
||||||
|
&& subTitleColor == model.subTitleColor
|
||||||
|
&& alignment == model.alignment
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& backgroundColor == model.backgroundColor
|
||||||
|
&& children.areEqual(to: model.children)
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -22,9 +22,13 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
|
|||||||
[headline, body].compactMap({$0})
|
[headline, body].compactMap({$0})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &headline, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &body, with: molecule)
|
if try replaceChildMolecule(at: &headline, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &body, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -22,9 +22,13 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
|
|||||||
[headline, body].compactMap({$0})
|
[headline, body].compactMap({$0})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &headline, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &body, with: molecule)
|
if try replaceChildMolecule(at: &headline, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &body, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -22,9 +22,13 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
|
|||||||
[headline, body].compactMap({$0})
|
[headline, body].compactMap({$0})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &headline, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &body, with: molecule)
|
if try replaceChildMolecule(at: &headline, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &body, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -23,9 +23,13 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
|||||||
|
|
||||||
public var children: [MoleculeModelProtocol] { [primaryButton, secondaryButton].compactMap { $0 } }
|
public var children: [MoleculeModelProtocol] { [primaryButton, secondaryButton].compactMap { $0 } }
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &primaryButton, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &secondaryButton, with: molecule)
|
if try replaceChildMolecule(at: &primaryButton, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &secondaryButton, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -85,8 +85,19 @@
|
|||||||
try container.encodeIfPresent(peakingUI, forKey: .peakingUI)
|
try container.encodeIfPresent(peakingUI, forKey: .peakingUI)
|
||||||
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
|
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
|
||||||
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
|
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
|
||||||
|
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||||
try container.encode(enabled, forKey: .enabled)
|
try container.encode(enabled, forKey: .enabled)
|
||||||
try container.encode(readOnly, forKey: .readOnly)
|
try container.encode(readOnly, forKey: .readOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return peakingUI == model.peakingUI
|
||||||
|
&& peakingArrowColor == model.peakingArrowColor
|
||||||
|
&& analyticsData == model.analyticsData
|
||||||
|
&& fieldValue == model.fieldValue
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& readOnly == model.readOnly
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
import MVMCore
|
import MVMCore
|
||||||
|
|
||||||
@objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol {
|
@objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -73,4 +73,10 @@
|
|||||||
try container.encodeIfPresent(border, forKey: .border)
|
try container.encodeIfPresent(border, forKey: .border)
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return action.isEqual(to: model.action)
|
||||||
|
&& border == border
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,4 +52,18 @@ import MVMCore
|
|||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeModel(molecule, forKey: .molecule)
|
try container.encodeModel(molecule, forKey: .molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
|
&& hideArrow == model.hideArrow
|
||||||
|
&& line.isEqual(to: model.line)
|
||||||
|
&& style == model.style
|
||||||
|
&& gone == model.gone
|
||||||
|
&& molecule.isEqual(to: model.molecule)
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
&& accessibilityValue == model.accessibilityValue
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,4 +58,12 @@
|
|||||||
try container.encodeIfPresent(percent, forKey: .percent)
|
try container.encodeIfPresent(percent, forKey: .percent)
|
||||||
try container.encode(gone, forKey: .gone)
|
try container.encode(gone, forKey: .gone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& spacing == model.spacing
|
||||||
|
&& percent == model.percent
|
||||||
|
&& gone == model.gone
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,4 +36,12 @@
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
fatalError("init(from:) has not been implemented")
|
fatalError("init(from:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& spacing == model.spacing
|
||||||
|
&& percent == model.percent
|
||||||
|
&& gone == model.gone
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,12 +23,16 @@ public class CornerLabelsModel: ParentMoleculeModelProtocol {
|
|||||||
[molecule, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel].compactMap { $0 }
|
[molecule, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel].compactMap { $0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &self.molecule, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &topLeftLabel, with: molecule)
|
if try replaceChildMolecule(at: &self.molecule, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &topRightLabel, with: molecule)
|
|| replaceChildMolecule(at: &topLeftLabel, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &bottomLeftLabel, with: molecule)
|
|| replaceChildMolecule(at: &topRightLabel, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &bottomRightLabel, with: molecule)
|
|| replaceChildMolecule(at: &bottomLeftLabel, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &bottomRightLabel, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(with molecule: MoleculeModelProtocol?) {
|
public init(with molecule: MoleculeModelProtocol?) {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco
|
|||||||
return [molecule]
|
return [molecule]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &self.molecule, with: molecule)
|
return try replaceChildMolecule(at: &self.molecule, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,4 +61,10 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco
|
|||||||
try container.encodeModel(molecule, forKey: .molecule)
|
try container.encodeModel(molecule, forKey: .molecule)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return molecule.isEqual(to: model.molecule)
|
||||||
|
&& backgroundColor == model.backgroundColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public extension MoleculeContainerModelProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public extension MoleculeContainerModelProtocol where Self: AnyObject {
|
public extension MoleculeContainerModelProtocol where Self: AnyObject {
|
||||||
mutating func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
mutating func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &molecule, with: replacementMolecule)
|
return try replaceChildMolecule(at: &molecule, with: replacementMolecule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
public class EyebrowHeadlineBodyLinkModel: ParentMoleculeModelProtocol {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -25,11 +25,15 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule
|
|||||||
[eyebrow, headline, body, link].compactMap { (molecule: MoleculeModelProtocol?) in molecule }
|
[eyebrow, headline, body, link].compactMap { (molecule: MoleculeModelProtocol?) in molecule }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &eyebrow, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at: &headline, with: molecule)
|
if try replaceChildMolecule(at: &eyebrow, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &body, with: molecule)
|
|| replaceChildMolecule(at: &headline, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &link, with: molecule)
|
|| replaceChildMolecule(at: &body, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &link, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -102,4 +106,10 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule
|
|||||||
try container.encodeIfPresent(body, forKey: .body)
|
try container.encodeIfPresent(body, forKey: .body)
|
||||||
try container.encodeIfPresent(link, forKey: .link)
|
try container.encodeIfPresent(link, forKey: .link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& children.areEqual(to: model.children)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,9 +24,13 @@ open class HeadlineBodyModel: ParentMoleculeModelProtocol {
|
|||||||
[headline, body].compactMap { $0 }
|
[headline, body].compactMap { $0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at:&headline, with: replacementMolecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|| replaceChildMolecule(at:&body, with: replacementMolecule)
|
if try replaceChildMolecule(at:&headline, with: replacementMolecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at:&body, with: replacementMolecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -89,6 +93,14 @@ open class HeadlineBodyModel: ParentMoleculeModelProtocol {
|
|||||||
try container.encodeIfPresent(style, forKey: .style)
|
try container.encodeIfPresent(style, forKey: .style)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return headline.isEqual(to: model.headline)
|
||||||
|
&& body.isEqual(to: model.body)
|
||||||
|
&& style == style
|
||||||
|
&& backgroundColor == backgroundColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension HeadlineBodyModel {
|
public extension HeadlineBodyModel {
|
||||||
|
|||||||
@ -171,6 +171,29 @@ import UIKit
|
|||||||
try container.encode(enabled, forKey: .enabled)
|
try container.encode(enabled, forKey: .enabled)
|
||||||
try container.encode(readOnly, forKey: .readOnly)
|
try container.encode(readOnly, forKey: .readOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == backgroundColor
|
||||||
|
&& molecules.areEqual(to: model.molecules)
|
||||||
|
&& spacing == model.spacing
|
||||||
|
&& border == model.border
|
||||||
|
&& loop == model.loop
|
||||||
|
&& height == model.height
|
||||||
|
&& itemWidthPercent == model.itemWidthPercent
|
||||||
|
&& itemAlignment == model.itemAlignment
|
||||||
|
&& pagingMolecule.isEqual(to: model.pagingMolecule)
|
||||||
|
&& paging == model.paging
|
||||||
|
&& useHorizontalMargins == model.useHorizontalMargins
|
||||||
|
&& leftPadding == model.leftPadding
|
||||||
|
&& rightPadding == model.rightPadding
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& baseValue == model.baseValue
|
||||||
|
&& fieldKey == model.fieldKey
|
||||||
|
&& groupName == model.groupName
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& readOnly == model.readOnly
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CarouselModel {
|
extension CarouselModel {
|
||||||
@ -179,7 +202,7 @@ extension CarouselModel {
|
|||||||
return molecules
|
return molecules
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(in: &molecules, with: molecule)
|
return try replaceChildMolecule(in: &molecules, with: molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -79,4 +79,11 @@
|
|||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return backgroundColor == model.backgroundColor
|
||||||
|
&& molecules.areEqual(to: model.molecules)
|
||||||
|
&& axis == model.axis
|
||||||
|
&& spacing == model.spacing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ extension StackModelProtocol {
|
|||||||
|
|
||||||
extension StackModelProtocol where Self: AnyObject {
|
extension StackModelProtocol where Self: AnyObject {
|
||||||
|
|
||||||
public mutating func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public mutating func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(in: &molecules, with: molecule)
|
return try replaceChildMolecule(in: &molecules, with: molecule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,3 +7,19 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
public protocol MoleculeModelComparisonProtocol: ModelProtocol {
|
||||||
|
|
||||||
|
/** True if there are no visual differences between models.
|
||||||
|
|
||||||
|
By default if the models are equal then they are visually equivalent. However, if there are parts of models that can be upddated without a UI update, this could be subset of properties.
|
||||||
|
**/
|
||||||
|
func isVisuallyEquivalent(to model: MoleculeModelComparisonProtocol) -> Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MoleculeModelComparisonProtocol {
|
||||||
|
|
||||||
|
public func isVisuallyEquivalent(to model: MoleculeModelComparisonProtocol) -> Bool {
|
||||||
|
return isEqual(to: model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ public enum MolecularError: Swift.Error {
|
|||||||
case countImbalance(String)
|
case countImbalance(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol, MoleculeMaskingProtocol {
|
public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol, MoleculeMaskingProtocol, MoleculeModelComparisonProtocol, CustomDebugStringConvertible {
|
||||||
var moleculeName: String { get }
|
var moleculeName: String { get }
|
||||||
var backgroundColor: Color? { get set }
|
var backgroundColor: Color? { get set }
|
||||||
var id: String { get }
|
var id: String { get }
|
||||||
@ -18,6 +18,15 @@ public extension MoleculeModelProtocol {
|
|||||||
static var categoryName: String { "\(MoleculeModelProtocol.self)" }
|
static var categoryName: String { "\(MoleculeModelProtocol.self)" }
|
||||||
|
|
||||||
static var categoryCodingKey: String { "moleculeName" }
|
static var categoryCodingKey: String { "moleculeName" }
|
||||||
|
|
||||||
|
func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return id == model.id
|
||||||
|
}
|
||||||
|
|
||||||
|
var debugDescription: String {
|
||||||
|
return "\(moleculeName): \(id)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helpers made due to swift not able to reconcile which category.
|
// Helpers made due to swift not able to reconcile which category.
|
||||||
|
|||||||
@ -8,52 +8,70 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public protocol ParentModelProtocol: MoleculeTreeTraversalProtocol {
|
public protocol ParentModelProtocol: ModelProtocol, MoleculeTreeTraversalProtocol {
|
||||||
|
|
||||||
/// Returns the direct children of this component. (Does not recurse.)
|
/// Returns the direct children of this component. (Does not recurse.)
|
||||||
var children: [MoleculeModelProtocol] { get }
|
var children: [MoleculeModelProtocol] { get }
|
||||||
|
|
||||||
/// Method for replacing surface level children. (Does not recurse.)
|
/// Method for replacing surface level children. (Does not recurse.)
|
||||||
mutating func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool
|
mutating func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol?
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension ParentModelProtocol where Self: AnyObject {
|
public extension ParentModelProtocol where Self: AnyObject {
|
||||||
|
|
||||||
/// Top level test to replace child molecules. Each parent molecule should attempt to replace.
|
/// Top level test to replace child molecules. Each parent molecule should attempt to replace.
|
||||||
func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { return false }
|
func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? { return nil }
|
||||||
|
|
||||||
|
func replaceChildMolecule<T>(at childMolecule: inout T, with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|
return try replaceChildMolecule(at: &childMolecule, with: replacementMolecule, replaced: &replacedMolecule) ? replacedMolecule : nil
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function for replacing a single molecules with type and optionality checks.
|
/// Helper function for replacing a single molecules with type and optionality checks.
|
||||||
func replaceChildMolecule<T>(at childMolecule: inout T, with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
func replaceChildMolecule<T>(at childMolecule: inout T, with replacementMolecule: MoleculeModelProtocol, replaced: inout MoleculeModelProtocol?) throws -> Bool {
|
||||||
guard let childIdMolecule = childMolecule as? MoleculeModelProtocol else { return false }
|
guard let childIdMolecule = childMolecule as? MoleculeModelProtocol else { return false }
|
||||||
if childIdMolecule.id == replacementMolecule.id {
|
if childIdMolecule.id == replacementMolecule.id {
|
||||||
guard let replacementMolecule = replacementMolecule as? T else {
|
guard let typedReplacementMolecule = replacementMolecule as? T else {
|
||||||
throw MolecularError.error("Molecular replacement '\(replacementMolecule.id)' does not type match \(type(of: T.self)) of \(type(of: self))")
|
throw MolecularError.error("Molecular replacement '\(replacementMolecule.id)' does not type match \(type(of: T.self)) of \(type(of: self))")
|
||||||
}
|
}
|
||||||
childMolecule = replacementMolecule
|
replaced = childIdMolecule
|
||||||
|
childMolecule = typedReplacementMolecule
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func replaceChildMolecule<T>(in molecules: inout [T], with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|
return try replaceChildMolecule(at: &molecules, with: replacementMolecule, replaced: &replacedMolecule) ? replacedMolecule : nil
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper for replacing a molecule in place within an array. Note the "in".
|
/// Helper for replacing a molecule in place within an array. Note the "in".
|
||||||
func replaceChildMolecule<T>(in molecules: inout [T], with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
func replaceChildMolecule<T>(in molecules: inout [T], with replacementMolecule: MoleculeModelProtocol, replaced: inout MoleculeModelProtocol?) throws -> Bool {
|
||||||
guard let moleculeIdModels = molecules as? [MoleculeModelProtocol], let matchingIndex = moleculeIdModels.firstIndex(where: {
|
guard let moleculeIdModels = molecules as? [MoleculeModelProtocol],
|
||||||
$0.id == replacementMolecule.id
|
let matchingIndex = moleculeIdModels.firstIndex(where: {
|
||||||
}) else { return false }
|
$0.id == replacementMolecule.id
|
||||||
guard let replacementMolecule = replacementMolecule as? T else {
|
})
|
||||||
|
else { return false }
|
||||||
|
guard let typedReplacementMolecule = replacementMolecule as? T else {
|
||||||
throw MolecularError.error("Molecular replacement '\(replacementMolecule.id)' does not type match \(type(of: T.self)) of \(type(of: self))")
|
throw MolecularError.error("Molecular replacement '\(replacementMolecule.id)' does not type match \(type(of: T.self)) of \(type(of: self))")
|
||||||
}
|
}
|
||||||
molecules[matchingIndex] = replacementMolecule
|
replaced = molecules[matchingIndex] as? MoleculeModelProtocol
|
||||||
|
molecules[matchingIndex] = typedReplacementMolecule
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol ParentMoleculeModelProtocol: ParentModelProtocol, MoleculeModelProtocol {
|
public protocol ParentMoleculeModelProtocol: ParentModelProtocol, MoleculeModelProtocol {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension ParentMoleculeModelProtocol {
|
public extension ParentMoleculeModelProtocol {
|
||||||
|
|
||||||
|
func isEqual(to model: any ModelProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return model.children.areEqual(to: model.children)
|
||||||
|
}
|
||||||
|
|
||||||
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result {
|
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result {
|
||||||
var result = initialResult
|
var result = initialResult
|
||||||
if (options == .parentFirst) {
|
if (options == .parentFirst) {
|
||||||
@ -64,7 +82,7 @@ public extension ParentMoleculeModelProtocol {
|
|||||||
// Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol.
|
// Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol.
|
||||||
return additionalParent.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult)
|
return additionalParent.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult)
|
||||||
}
|
}
|
||||||
return molecule.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult)
|
return nextPartialResult(result, molecule, depth + 1)
|
||||||
}
|
}
|
||||||
if (options == .childFirst) {
|
if (options == .childFirst) {
|
||||||
result = nextPartialResult(result, self, depth)
|
result = nextPartialResult(result, self, depth)
|
||||||
@ -88,7 +106,7 @@ public extension ParentMoleculeModelProtocol {
|
|||||||
// Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol.
|
// Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol.
|
||||||
additionalParent.depthFirstTraverse(options: options, depth: depth + 1, onVisit: stopIntercept)
|
additionalParent.depthFirstTraverse(options: options, depth: depth + 1, onVisit: stopIntercept)
|
||||||
} else {
|
} else {
|
||||||
child.depthFirstTraverse(options: options, depth: depth + 1, onVisit: stopIntercept)
|
onVisit(depth, child, &shouldStop)
|
||||||
}
|
}
|
||||||
guard !shouldStop else { return }
|
guard !shouldStop else { return }
|
||||||
}
|
}
|
||||||
@ -98,3 +116,29 @@ public extension ParentMoleculeModelProtocol {
|
|||||||
// if options == .leafOnly don't call on self.
|
// if options == .leafOnly don't call on self.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ParentModelProtocol {
|
||||||
|
|
||||||
|
func deepCompare(_ anotherParent: ParentModelProtocol, with test: (ModelProtocol, ModelProtocol)->Bool) -> (Bool, myChild: ModelProtocol?, theirChild: ModelProtocol?) {
|
||||||
|
|
||||||
|
guard test(self, anotherParent) else { return (false, myChild: self, theirChild: self)}
|
||||||
|
|
||||||
|
let myChildren = children
|
||||||
|
let theirChildren = anotherParent.children
|
||||||
|
guard myChildren.count == theirChildren.count else { return (false, myChild: self, theirChild: self) }
|
||||||
|
for index in myChildren.indices {
|
||||||
|
if let myChild = myChildren[index] as? ParentModelProtocol {
|
||||||
|
if let theirChild = theirChildren[index] as? ParentModelProtocol {
|
||||||
|
let result = myChild.deepCompare(theirChild, with: test)
|
||||||
|
guard result.0 else { return result }
|
||||||
|
} else {
|
||||||
|
return (false, myChild: myChild, theirChild: theirChildren[index])
|
||||||
|
}
|
||||||
|
} else if !test(myChildren[index], theirChildren[index]) {
|
||||||
|
return (false, myChild: myChildren[index], theirChild: theirChildren[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -42,27 +42,27 @@ public extension TemplateModelProtocol {
|
|||||||
extension TemplateModelProtocol {
|
extension TemplateModelProtocol {
|
||||||
|
|
||||||
/// Recursively finds and replaces the first child matching the replacement molecule id property.
|
/// Recursively finds and replaces the first child matching the replacement molecule id property.
|
||||||
mutating func replaceMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
mutating func replaceMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
// Attempt root level replacement on the template model first.
|
// Attempt root level replacement on the template model first.
|
||||||
if try replaceChildMolecule(with: replacementMolecule) {
|
if let replacedMolecule = try replaceChildMolecule(with: replacementMolecule) {
|
||||||
return true
|
return replacedMolecule
|
||||||
}
|
}
|
||||||
|
|
||||||
var didReplaceMolecule = false
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
var possibleError: Error?
|
var possibleError: Error?
|
||||||
// Dive into each root thereafter.
|
// Dive into each root thereafter.
|
||||||
depthFirstTraverse(options: .parentFirst, depth: 0) { depth, molecule, stop in
|
depthFirstTraverse(options: .parentFirst, depth: 0) { depth, molecule, stop in
|
||||||
guard var parentMolecule = molecule as? ParentMoleculeModelProtocol else { return }
|
guard var parentMolecule = molecule as? ParentMoleculeModelProtocol else { return }
|
||||||
do {
|
do {
|
||||||
didReplaceMolecule = try parentMolecule.replaceChildMolecule(with: replacementMolecule)
|
replacedMolecule = try parentMolecule.replaceChildMolecule(with: replacementMolecule)
|
||||||
} catch {
|
} catch {
|
||||||
possibleError = error
|
possibleError = error
|
||||||
}
|
}
|
||||||
stop = didReplaceMolecule || possibleError != nil
|
stop = replacedMolecule != nil || possibleError != nil
|
||||||
}
|
}
|
||||||
if let error = possibleError {
|
if let error = possibleError {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
return didReplaceMolecule
|
return replacedMolecule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,8 +35,12 @@ import Foundation
|
|||||||
public var hideLeftPanel: Bool?
|
public var hideLeftPanel: Bool?
|
||||||
public var hideRightPanel: Bool?
|
public var hideRightPanel: Bool?
|
||||||
|
|
||||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try replaceChildMolecule(at: &navigationBar, with: molecule)
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|
if try replaceChildMolecule(at: &navigationBar, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -23,9 +23,14 @@
|
|||||||
return super.rootMolecules
|
return super.rootMolecules
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try super.replaceChildMolecule(with: molecule)
|
if let replacedMolecule = try super.replaceChildMolecule(with: molecule) {
|
||||||
|| (molecules != nil && replaceChildMolecule(in: &(molecules!), with: molecule))
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
if molecules != nil, let replacedMolecule = try replaceChildMolecule(in: &(molecules!), with: molecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -28,10 +28,16 @@
|
|||||||
return super.rootMolecules
|
return super.rootMolecules
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try super.replaceChildMolecule(with: molecule)
|
if let replacedMolecule = try super.replaceChildMolecule(with: molecule) {
|
||||||
|| (molecules != nil && replaceChildMolecule(in: &(molecules!), with: molecule))
|
return replacedMolecule
|
||||||
|| replaceChildMolecule(at: &line, with: molecule)
|
}
|
||||||
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|
if try (molecules != nil && replaceChildMolecule(in: &(molecules!), with: molecule, replaced: &replacedMolecule))
|
||||||
|
|| replaceChildMolecule(at: &line, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This template requires content.
|
/// This template requires content.
|
||||||
|
|||||||
@ -19,10 +19,14 @@
|
|||||||
super.rootMolecules + [moleculeStack]
|
super.rootMolecules + [moleculeStack]
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
return try super.replaceChildMolecule(with: molecule)
|
return try super.replaceChildMolecule(with: molecule)
|
||||||
|| replaceChildMolecule(at: &navigationBar, with: molecule)
|
if try replaceChildMolecule(at: &navigationBar, with: molecule, replaced: &replacedMolecule)
|
||||||
|| replaceChildMolecule(at: &moleculeStack, with: molecule)
|
|| replaceChildMolecule(at: &moleculeStack, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -21,10 +21,16 @@
|
|||||||
[navigationBar, header, footer].compactMap { $0 }
|
[navigationBar, header, footer].compactMap { $0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try super.replaceChildMolecule(with: molecule)
|
if let replacedMolecule = try super.replaceChildMolecule(with: molecule) {
|
||||||
|| replaceChildMolecule(at: &header, with: molecule)
|
return replacedMolecule
|
||||||
|| replaceChildMolecule(at: &footer, with: molecule)
|
}
|
||||||
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|
if try replaceChildMolecule(at: &header, with: molecule, replaced: &replacedMolecule)
|
||||||
|
|| replaceChildMolecule(at: &footer, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -22,9 +22,15 @@
|
|||||||
return super.rootMolecules
|
return super.rootMolecules
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
public override func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
return try super.replaceChildMolecule(with: molecule)
|
if let replacedMolecule = try super.replaceChildMolecule(with: molecule) {
|
||||||
|| replaceChildMolecule(at: &middle, with: molecule)
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
|
if try replaceChildMolecule(at: &middle, with: molecule, replaced: &replacedMolecule) {
|
||||||
|
return replacedMolecule
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -513,27 +513,34 @@ import MVMCore
|
|||||||
|
|
||||||
public func replaceMoleculeData(_ moleculeModels: [MoleculeModelProtocol], completionHandler: (([MoleculeModelProtocol])->Void)? = nil) {
|
public func replaceMoleculeData(_ moleculeModels: [MoleculeModelProtocol], completionHandler: (([MoleculeModelProtocol])->Void)? = nil) {
|
||||||
pageUpdateQueue.addOperation {
|
pageUpdateQueue.addOperation {
|
||||||
let replacedModels:[MoleculeModelProtocol] = moleculeModels.compactMap { model in
|
let replacedModels:[(MoleculeModelProtocol, MoleculeModelProtocol)] = moleculeModels.compactMap { model in
|
||||||
guard self.attemptToReplace(with: model) else {
|
guard let replacedMolecule = self.attemptToReplace(with: model) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return model
|
return (model, replacedMolecule)
|
||||||
}
|
}
|
||||||
if replacedModels.count > 0 {
|
let uiUpdatedModels: [MoleculeModelProtocol] = replacedModels.compactMap { new, existing in
|
||||||
|
guard !new.isVisuallyEquivalent(to: existing) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return new
|
||||||
|
}
|
||||||
|
if uiUpdatedModels.count > 0 {
|
||||||
|
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Updating UI for molecules: \(uiUpdatedModels)")
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
self.updateUI(for: replacedModels)
|
self.updateUI(for: uiUpdatedModels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
completionHandler?(replacedModels)
|
completionHandler?(replacedModels.map { $0.0 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open func attemptToReplace(with replacementModel: MoleculeModelProtocol) -> Bool {
|
open func attemptToReplace(with replacementModel: MoleculeModelProtocol) -> MoleculeModelProtocol? {
|
||||||
guard var templateModel = getTemplateModel() else { return false }
|
guard var templateModel = getTemplateModel() else { return nil }
|
||||||
var didReplace = false
|
var replacedMolecule: MoleculeModelProtocol?
|
||||||
do {
|
do {
|
||||||
didReplace = try templateModel.replaceMolecule(with: replacementModel)
|
replacedMolecule = try templateModel.replaceMolecule(with: replacementModel)
|
||||||
if !didReplace {
|
if replacedMolecule == nil {
|
||||||
MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Failed to find '\(replacementModel.id)' in the current screen.", code: ErrorCode.viewControllerProcessingJSON.rawValue, domain: ErrorDomainSystem, location: String(describing: type(of: self)))!)
|
MVMCoreLoggingHandler.shared()?.addError(toLog: MVMCoreErrorObject(title: nil, messageToLog: "Failed to find '\(replacementModel.id)' in the current screen.", code: ErrorCode.viewControllerProcessingJSON.rawValue, domain: ErrorDomainSystem, location: String(describing: type(of: self)))!)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@ -543,7 +550,7 @@ import MVMCore
|
|||||||
}
|
}
|
||||||
MVMCoreLoggingHandler.shared()?.addError(toLog: coreError)
|
MVMCoreLoggingHandler.shared()?.addError(toLog: coreError)
|
||||||
}
|
}
|
||||||
return didReplace
|
return replacedMolecule
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import UIKit
|
|||||||
Int and String and can be used the same.
|
Int and String and can be used the same.
|
||||||
*/
|
*/
|
||||||
public final class Color: Codable {
|
public final class Color: Codable {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -151,3 +152,9 @@ public final class Color: Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Color: Equatable {
|
||||||
|
public static func == (lhs: Color, rhs: Color) -> Bool {
|
||||||
|
return lhs.hex == rhs.hex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user