Digital PCT265 story ONEAPP-7249 - isVisuallyEquivalent build out to work with stabilizing carousel refreshes.

This commit is contained in:
Hedden, Kyle Matthew 2024-05-08 20:34:08 -04:00
parent 067f63e6de
commit 04581558e3
31 changed files with 248 additions and 62 deletions

View File

@ -187,7 +187,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encodeIfPresent(disabledAccessibilityTraits, forKey: .disabledAccessibilityTraits)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return title == model.title
&& enabled == model.enabled
@ -195,11 +195,25 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
&& action.isEqual(to: model.action)
&& accessibilityText == model.accessibilityText
&& accessibilityIdentifier == model.accessibilityIdentifier
&& accessibilityTraits == model.accessibilityTraits
&& disabledAccessibilityTraits == model.disabledAccessibilityTraits
&& style == model.style
&& size == model.size
&& groupName == model.groupName
&& width == model.width
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return title == model.title
&& enabled == model.enabled
&& inverted == model.inverted
&& accessibilityText == model.accessibilityText
&& accessibilityIdentifier == model.accessibilityIdentifier
&& accessibilityTraits == model.accessibilityTraits
&& disabledAccessibilityTraits == model.disabledAccessibilityTraits
&& style == model.style
&& size == model.size
&& width == model.width
}
}

View File

@ -100,7 +100,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& title == model.title
@ -110,7 +110,18 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
&& enabled == model.enabled
&& size == model.size
&& shouldMaskRecordedView == model.shouldMaskRecordedView
// && action.isEqual(to: model.action) // TODO: Move to isVisiuallyEquivalent.
&& action.isEqual(to: model.action)
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> 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
}
}

View File

@ -21,6 +21,8 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
public var id: String = UUID().uuidString
public var backgroundColor: Color?
public var moleculeName: String?
// Assigned and computed by parent.
public var numberOfPages: Int = 0
/// Sets the current Index to focus on.
@ -49,7 +51,6 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
case moleculeName
case backgroundColor
case currentIndex
case numberOfPages
case alwaysSendAction
case animated
case hidesForSinglePage
@ -118,7 +119,6 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
try container.encode(id, forKey: .id)
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(numberOfPages, forKey: .numberOfPages)
try container.encode(currentIndex, forKey: .currentIndex)
try container.encode(alwaysSendAction, forKey: .alwaysSendAction)
try container.encode(animated, forKey: .animated)
@ -131,10 +131,9 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
try container.encodeIfPresent(position, forKey: .position)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> 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

View File

@ -49,8 +49,12 @@ open class LabelAttributeActionModel: LabelAttributeModel {
try container.encodeModel(action, forKey: .action)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return action.isEqual(to: model.action)
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
return super.isEqual(to: model)
}
}

View File

@ -44,7 +44,7 @@
try container.encodeIfPresent(textColor, forKey: .textColor)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return textColor == model.textColor
}

View File

@ -56,7 +56,7 @@
try container.encodeIfPresent(size, forKey: .size)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return style == model.style
&& name == model.name

View File

@ -70,7 +70,7 @@ class LabelAttributeImageModel: LabelAttributeModel {
try container.encodeIfPresent(tintColor, forKey: .tintColor)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return URL == model.URL
&& name == model.name

View File

@ -7,7 +7,7 @@
//
@objcMembers open class LabelAttributeModel: ModelProtocol {
@objcMembers open class LabelAttributeModel: ModelProtocol, ModelComparisonProtocol, MoleculeModelComparisonProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -76,7 +76,7 @@
try container.encode(length, forKey: .length)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return location == model.location
&& length == model.length

View File

@ -67,7 +67,7 @@ import UIKit
try container.encodeIfPresent(pattern, forKey: .pattern)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return style == model.style
&& color == model.color

View File

@ -133,7 +133,7 @@ import VDS
try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& text == model.text
@ -143,12 +143,31 @@ import VDS
&& fontName == model.fontName
&& fontSize == model.fontSize
&& textAlignment == model.textAlignment
&& attributes.areEqual(to: model.attributes)
&& attributes.isEqual(to: model.attributes)
&& html == model.html
&& hero == model.hero
&& makeWholeViewClickable == model.makeWholeViewClickable
&& numberOfLines == model.numberOfLines
&& accessibilityTraits == model.accessibilityTraits
&& inverted == inverted
&& shouldMaskRecordedView == model.shouldMaskRecordedView
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& text == model.text
&& textColor == model.textColor
&& fontStyle == model.fontStyle
&& fontName == model.fontName
&& fontSize == model.fontSize
&& textAlignment == model.textAlignment
&& attributes.isEqual(to: model.attributes)
&& html == model.html
&& hero == model.hero
&& makeWholeViewClickable == model.makeWholeViewClickable
&& numberOfLines == model.numberOfLines
&& accessibilityText == model.accessibilityText
&& accessibilityTraits == model.accessibilityTraits
&& inverted == inverted
}

View File

@ -130,7 +130,7 @@ public class LineModel: MoleculeModelProtocol, Invertable {
try container.encode(orientation == .vertical, forKey: .useVerticalLine)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return type == model.type
&& inverted == model.inverted

View File

@ -68,9 +68,4 @@ public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeMod
try container.encode(moleculeName, forKey: .moleculeName)
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)
}
}

View File

@ -46,14 +46,24 @@ public class TitleLockupModel: ParentMoleculeModelProtocol {
return nil
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> 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)
&& children.isEqual(to: model.children)
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> 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.isVisuallyEquivalent(to: model.children)
}
//--------------------------------------------------

View File

@ -91,7 +91,7 @@
try container.encode(readOnly, forKey: .readOnly)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return peakingUI == model.peakingUI
&& peakingArrowColor == model.peakingArrowColor
@ -100,4 +100,12 @@
&& enabled == model.enabled
&& readOnly == model.readOnly
}
public override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false }
return peakingUI == model.peakingUI
&& peakingArrowColor == model.peakingArrowColor
&& enabled == model.enabled
&& readOnly == model.readOnly
}
}

View File

@ -8,7 +8,7 @@
// A base class that has common list item boilerplate model stuffs.
import MVMCore
@objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol {
@objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol, ModelComparisonProtocol, MoleculeModelComparisonProtocol {
//--------------------------------------------------
// MARK: - Properties
@ -23,6 +23,7 @@ import MVMCore
public var accessibilityTraits: UIAccessibilityTraits?
public var accessibilityValue: String?
public var accessibilityText: String?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -129,4 +130,29 @@ import MVMCore
try container.encodeIfPresent(accessibilityValue, forKey: .accessibilityValue)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& hideArrow == model.hideArrow
&& style == model.style
&& gone == model.gone
&& accessibilityText == model.accessibilityText
&& accessibilityValue == model.accessibilityValue
&& accessibilityTraits == model.accessibilityTraits
&& line.isEqual(to: model.line)
&& action.isEqual(to: model.action)
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& hideArrow == model.hideArrow
&& style == model.style
&& gone == model.gone
&& accessibilityText == model.accessibilityText
&& accessibilityValue == model.accessibilityValue
&& accessibilityTraits == model.accessibilityTraits
&& line.isVisuallyEquivalent(to: model.line)
}
}

View File

@ -74,9 +74,14 @@
try super.encode(to: encoder)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return action.isEqual(to: model.action)
&& border == border
return border == border
&& action.isEqual(to: model.action)
}
public override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false }
return border == border
}
}

View File

@ -53,17 +53,13 @@ import MVMCore
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
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return molecule.isEqual(to: model)
}
public override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false }
return molecule.isVisuallyEquivalent(to: model.molecule)
}
}

View File

@ -59,10 +59,16 @@
try container.encode(gone, forKey: .gone)
}
public override func isEqual(to model: any ModelProtocol) -> Bool {
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard super.isEqual(to: model), let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& spacing == model.spacing
return spacing == model.spacing
&& percent == model.percent
&& gone == model.gone
}
public override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false }
return spacing == model.spacing
&& percent == model.percent
&& gone == model.gone
}

View File

@ -30,7 +30,10 @@ import UIKit
}
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
MoleculeContainer.nameForReuse(with: model, delegateObject)
if let listModel = model as? ListItemModel, listModel.hasStableId {
return "\(MoleculeContainer.nameForReuse(with: model, delegateObject) ?? "")<\(listModel.id)>"
}
return MoleculeContainer.nameForReuse(with: model, delegateObject)
}
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {

View File

@ -37,7 +37,7 @@
fatalError("init(from:) has not been implemented")
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& spacing == model.spacing

View File

@ -62,9 +62,14 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return molecule.isEqual(to: model.molecule)
&& backgroundColor == model.backgroundColor
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
}
}

View File

@ -107,9 +107,9 @@ public class EyebrowHeadlineBodyLinkModel: ParentMoleculeModelProtocol {
try container.encodeIfPresent(link, forKey: .link)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& children.areEqual(to: model.children)
&& children.isEqual(to: model.children)
}
}

View File

@ -94,7 +94,7 @@ open class HeadlineBodyModel: ParentMoleculeModelProtocol {
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return headline.isEqual(to: model.headline)
&& body.isEqual(to: model.body)

View File

@ -166,9 +166,19 @@ open class Carousel: View {
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.delegateObject = delegateObject
let originalModel = self.model as? CarouselModel
super.set(with: model, delegateObject, additionalData)
guard let carouselModel = model as? CarouselModel else { return }
if #available(iOS 15.0, *) {
if let originalModel, carouselModel.isVisuallyEquivalent(to: originalModel) {
collectionView.reconfigureItems(at: collectionView.indexPathsForVisibleItems)
FormValidator.setupValidation(for: carouselModel, delegate: delegateObject?.formHolderDelegate)
return
}
}
accessibilityLabel = carouselModel.accessibilityText
collectionView.layer.borderColor = UIColor.mvmCoolGray3.cgColor
collectionView.layer.borderWidth = (carouselModel.border ?? false) ? 1 : 0

View File

@ -172,10 +172,10 @@ import UIKit
try container.encode(readOnly, forKey: .readOnly)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == backgroundColor
&& molecules.areEqual(to: model.molecules)
&& molecules.isEqual(to: model.molecules)
&& spacing == model.spacing
&& border == model.border
&& loop == model.loop
@ -194,6 +194,27 @@ import UIKit
&& enabled == model.enabled
&& readOnly == model.readOnly
}
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == backgroundColor
&& spacing == model.spacing
&& border == model.border
&& loop == model.loop
&& height == model.height
&& itemWidthPercent == model.itemWidthPercent
&& itemAlignment == model.itemAlignment
&& paging == model.paging
&& useHorizontalMargins == model.useHorizontalMargins
&& leftPadding == model.leftPadding
&& rightPadding == model.rightPadding
&& accessibilityText == model.accessibilityText
&& baseValue == model.baseValue
&& enabled == model.enabled
&& readOnly == model.readOnly
&& pagingMolecule.isVisuallyEquivalent(to: model.pagingMolecule)
&& molecules.isVisuallyEquivalent(to: model.molecules)
}
}
extension CarouselModel {

View File

@ -79,10 +79,10 @@
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
public func isEqual(to model: any ModelProtocol) -> Bool {
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return backgroundColor == model.backgroundColor
&& molecules.areEqual(to: model.molecules)
&& molecules.isEqual(to: model.molecules)
&& axis == model.axis
&& spacing == model.spacing
}

View File

@ -8,11 +8,12 @@
import Foundation
public protocol MoleculeModelComparisonProtocol: ModelProtocol {
public protocol MoleculeModelComparisonProtocol: ModelComparisonProtocol {
/** True if there are no visual differences between models.
/**
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.
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
}
@ -23,3 +24,39 @@ extension MoleculeModelComparisonProtocol {
return isEqual(to: model)
}
}
public extension Optional {
/// Checks if the curent model is equal to another model.
func isVisuallyEquivalent(to model: MoleculeModelComparisonProtocol?) -> Bool {
guard let self = self as? MoleculeModelComparisonProtocol else {
return model == nil
}
guard let model = model else {
return false
}
return self.isVisuallyEquivalent(to: model)
}
}
public extension Collection {
/// Checks if all the models in the given collection match another given collection.
func isVisuallyEquivalent(to models: [MoleculeModelComparisonProtocol]) -> Bool {
guard count == models.count, let self = self as? [MoleculeModelComparisonProtocol] else { return false }
return models.indices.allSatisfy { index in
self[index].isVisuallyEquivalent(to: models[index])
}
}
}
public extension Optional where Wrapped: Collection {
func isVisuallyEquivalent(to models: [MoleculeModelComparisonProtocol]?) -> Bool {
guard let self = self as? [MoleculeModelComparisonProtocol] else {
return models == nil
}
guard let models = models else {
return false
}
return self.isVisuallyEquivalent(to: models)
}
}

View File

@ -19,7 +19,7 @@ public extension MoleculeModelProtocol {
static var categoryCodingKey: String { "moleculeName" }
func isEqual(to model: any ModelProtocol) -> Bool {
func isEqual(to model: ModelProtocol) -> Bool {
guard let model = model as? Self else { return false }
return id == model.id
}

View File

@ -69,7 +69,12 @@ 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)
return model.children.isEqual(to: model.children)
}
func areVisuallyEquivalent(to model: any ModelProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.children.isVisuallyEquivalent(to: model.children)
}
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result {
@ -119,7 +124,14 @@ public extension ParentMoleculeModelProtocol {
extension ParentModelProtocol {
func deepCompare(_ anotherParent: ParentModelProtocol, with test: (ModelProtocol, ModelProtocol)->Bool) -> (Bool, myChild: ModelProtocol?, theirChild: ModelProtocol?) {
public typealias DeepCompareResult = (matched: Bool, myChild: ModelProtocol?, theirChild: ModelProtocol?)
public func deepEquals(to model: any ModelProtocol) -> DeepCompareResult {
guard let model = model as? ParentModelProtocol else { return (false, self, model) }
return deepCompare(model) { $0.isEqual(to: $1) }
}
func deepCompare(_ anotherParent: ParentModelProtocol, with test: (ModelProtocol, ModelProtocol)->Bool) -> DeepCompareResult {
guard test(self, anotherParent) else { return (false, myChild: self, theirChild: self)}

View File

@ -522,7 +522,8 @@ import MVMCore
return (model, replacedMolecule)
}
let uiUpdatedModels: [MoleculeModelProtocol] = replacedModels.compactMap { new, existing in
guard !new.isVisuallyEquivalent(to: existing) else {
guard !new.isEqual(to: existing) else {
MVMCoreLoggingHandler.shared()?.handleDebugMessage("UI for molecules: \(new) is the same. Skip UI update.")
return nil
}
return new

View File

@ -14,6 +14,7 @@ open class ContainerModel: ContainerModelProtocol, Codable {
//--------------------------------------------------
public var id: String = UUID().uuidString
public var hasStableId = false
public var horizontalAlignment: UIStackView.Alignment?
public var useHorizontalMargins: Bool?
@ -78,7 +79,10 @@ open class ContainerModel: ContainerModelProtocol, Codable {
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
if let id = try typeContainer.decodeIfPresent(String.self, forKey: .id) {
self.id = id
hasStableId = true
}
if let verticalAlignmentString = try typeContainer.decodeIfPresent(String.self, forKey: .verticalAlignment) {
verticalAlignment = ContainerHelper.getAlignment(for: verticalAlignmentString)