Digital PCT265 story PCT-135: More isEquals. Fix replaceChildMolecule signature for TabsListItemModel.
This commit is contained in:
parent
cd5d9b0c4a
commit
ffc36c309f
@ -162,7 +162,7 @@ import VDS
|
||||
&& fontName == model.fontName
|
||||
&& fontSize == model.fontSize
|
||||
&& textAlignment == model.textAlignment
|
||||
&& attributes.isEqual(to: model.attributes)
|
||||
&& attributes.isVisuallyEquivalent(to: model.attributes)
|
||||
&& html == model.html
|
||||
&& hero == model.hero
|
||||
&& makeWholeViewClickable == model.makeWholeViewClickable
|
||||
|
||||
@ -106,9 +106,28 @@ open class TabBarModel: MoleculeModelProtocol {
|
||||
try container.encode(selectedTab, forKey: .selectedTab)
|
||||
try container.encodeIfPresent(style, forKey: .style)
|
||||
}
|
||||
|
||||
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return backgroundColor == model.backgroundColor
|
||||
&& selectedColor == model.selectedColor
|
||||
&& selectedTab == model.selectedTab
|
||||
&& style == model.style
|
||||
&& tabs == model.tabs
|
||||
}
|
||||
|
||||
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return backgroundColor == model.backgroundColor
|
||||
&& selectedColor == model.selectedColor
|
||||
&& selectedTab == model.selectedTab
|
||||
&& style == model.style
|
||||
&& tabs.isVisuallyEquivalent(to: model.tabs)
|
||||
}
|
||||
}
|
||||
|
||||
open class TabBarItemModel: Codable {
|
||||
open class TabBarItemModel: Codable, Equatable, MoleculeModelComparisonProtocol {
|
||||
|
||||
open var title: String?
|
||||
open var image: String
|
||||
open var action: ActionModelProtocol
|
||||
@ -142,4 +161,18 @@ open class TabBarItemModel: Codable {
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
}
|
||||
|
||||
public static func == (lhs: TabBarItemModel, rhs: TabBarItemModel) -> Bool {
|
||||
return lhs.title == rhs.title
|
||||
&& lhs.image == rhs.image
|
||||
&& lhs.accessibilityText == rhs.accessibilityText
|
||||
&& lhs.action.isEqual(to: rhs.action)
|
||||
}
|
||||
|
||||
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return image == model.image
|
||||
&& accessibilityText == model.accessibilityText
|
||||
&& title == model.title
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,11 +105,39 @@ open class TabsModel: MoleculeModelProtocol {
|
||||
try container.encode(borderLine, forKey: .borderLine)
|
||||
try container.encodeIfPresent(minWidth, forKey: .minWidth)
|
||||
}
|
||||
|
||||
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return backgroundColor == model.backgroundColor
|
||||
&& style == model.style
|
||||
&& orientation == model.orientation
|
||||
&& indicatorPosition == model.indicatorPosition
|
||||
&& overflow == model.overflow
|
||||
&& fillContainer == model.fillContainer
|
||||
&& size == model.size
|
||||
&& borderLine == model.borderLine
|
||||
&& minWidth == model.minWidth
|
||||
&& selectedIndex == model.selectedIndex
|
||||
&& tabs.isEqual(to: model.tabs)
|
||||
}
|
||||
|
||||
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return backgroundColor == model.backgroundColor
|
||||
&& style == model.style
|
||||
&& orientation == model.orientation
|
||||
&& indicatorPosition == model.indicatorPosition
|
||||
&& overflow == model.overflow
|
||||
&& fillContainer == model.fillContainer
|
||||
&& size == model.size
|
||||
&& borderLine == model.borderLine
|
||||
&& minWidth == model.minWidth
|
||||
//&& selectedIndex == model.selectedIndex // Selected index could have been either reset locally or by server. For now ignore.c
|
||||
&& tabs.isVisuallyEquivalent(to: model.tabs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
open class TabItemModel: Codable {
|
||||
open class TabItemModel: Codable, Equatable, MoleculeModelComparisonProtocol {
|
||||
open var label: LabelModel
|
||||
open var action: ActionModelProtocol?
|
||||
|
||||
@ -146,4 +174,14 @@ open class TabItemModel: Codable {
|
||||
try container.encodeModel(label, forKey: .label)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
}
|
||||
|
||||
public static func == (lhs: TabItemModel, rhs: TabItemModel) -> Bool {
|
||||
return lhs.label.isEqual(to: rhs.label)
|
||||
&& lhs.action.isEqual(to: rhs.action)
|
||||
}
|
||||
|
||||
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return label.isVisuallyEquivalent(to: model.label)
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,17 +23,18 @@ public class TabsListItemModel: ListItemModel, ParentMoleculeModelProtocol {
|
||||
return molecules.flatMap { $0 }
|
||||
}
|
||||
|
||||
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
||||
guard let replacementMolecule = replacementMolecule as? ListItemModelProtocol & MoleculeModelProtocol else { return false }
|
||||
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||
guard let replacementMolecule = replacementMolecule as? ListItemModelProtocol & MoleculeModelProtocol else { return nil }
|
||||
for (tabIndex, _) in molecules.enumerated() {
|
||||
for (elementIndex, _) in molecules[tabIndex].enumerated() {
|
||||
if molecules[tabIndex][elementIndex].id == replacementMolecule.id {
|
||||
let replacedMolecule = molecules[tabIndex][elementIndex]
|
||||
molecules[tabIndex][elementIndex] = replacementMolecule
|
||||
return true
|
||||
return replacedMolecule
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -90,6 +91,20 @@ public class TabsListItemModel: ListItemModel, ParentMoleculeModelProtocol {
|
||||
try container.encode(tabs, forKey: .tabs)
|
||||
try container.encodeModels2D(molecules, forKey: .molecules)
|
||||
}
|
||||
|
||||
public override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||
return tabs.isEqual(to: model.tabs)
|
||||
&& molecules.count == model.molecules.count
|
||||
&& zip(molecules, model.molecules).allSatisfy({ $0.0.isEqual(to: $0.1) })
|
||||
}
|
||||
|
||||
public override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false }
|
||||
return tabs.isVisuallyEquivalent(to: model.tabs)
|
||||
&& molecules.count == model.molecules.count
|
||||
&& zip(molecules, model.molecules).allSatisfy({ $0.0.isVisuallyEquivalent(to: $0.1) })
|
||||
}
|
||||
}
|
||||
|
||||
extension TabsListItemModel: PageBehaviorProtocolRequirer {
|
||||
|
||||
@ -141,6 +141,17 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
|
||||
try container.encodeIfPresent(style, forKey: .style)
|
||||
try container.encodeIfPresent(titleOffset, forKey: .titleOffset)
|
||||
}
|
||||
|
||||
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return backgroundColor == model.backgroundColor
|
||||
&& title == model.title
|
||||
&& hidden == model.hidden
|
||||
&& tintColor == model.tintColor
|
||||
&& line.isEqual(to: model.line)
|
||||
&& hidesSystemBackButton == model.hidesSystemBackButton
|
||||
&& style == model.style
|
||||
}
|
||||
}
|
||||
|
||||
extension NavigationItemModel: ParentMoleculeModelProtocol {
|
||||
|
||||
@ -101,6 +101,14 @@ open class HeadlineBodyModel: ParentMoleculeModelProtocol {
|
||||
&& style == style
|
||||
&& backgroundColor == backgroundColor
|
||||
}
|
||||
|
||||
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return headline.isVisuallyEquivalent(to: model.headline)
|
||||
&& body.isVisuallyEquivalent(to: model.body)
|
||||
&& style == style
|
||||
&& backgroundColor == backgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
public extension HeadlineBodyModel {
|
||||
|
||||
@ -86,4 +86,12 @@
|
||||
&& axis == model.axis
|
||||
&& spacing == model.spacing
|
||||
}
|
||||
|
||||
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||
guard let model = model as? Self else { return false }
|
||||
return backgroundColor == model.backgroundColor
|
||||
&& molecules.isVisuallyEquivalent(to: model.molecules)
|
||||
&& axis == model.axis
|
||||
&& spacing == model.spacing
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ public extension MoleculeTreeTraversalProtocol {
|
||||
|
||||
func printMolecules(options: TreeTraversalOptions = .parentFirst) {
|
||||
depthFirstTraverse(options: options, depth: 1) { depth, molecule, stop in
|
||||
print("\(String(repeating: ">>", count: depth)) \"\(molecule.moleculeName)\" [\(molecule): \(molecule.id)]")
|
||||
print("\(String(repeating: ">>", count: depth)) \"\(molecule.moleculeName)\" [\(molecule)]")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -65,17 +65,17 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
}
|
||||
|
||||
fileprivate func findAndReplace(_ moleculeModels: [any MoleculeModelProtocol], in rootMolecules: [any MoleculeModelProtocol]) -> [any MoleculeModelProtocol]? {
|
||||
debugLog("onPageNew replacing \(moleculeModels.map { $0.id })")
|
||||
debugLog("attempting to replace \(moleculeModels.map { $0.id }) in \(rootMolecules)")
|
||||
var hasReplacement = false
|
||||
let updatedRootMolecules = rootMolecules.map { rootMolecule in
|
||||
|
||||
// Top level check to return a new root molecule.
|
||||
if let updatedMolecule = moleculeModels.first(where: { rootMolecule.id == $0.id }) {
|
||||
guard !updatedMolecule.isEqual(to: rootMolecule) else {
|
||||
debugLog("onPageNew molecule \(updatedMolecule) is the same as \(rootMolecule). skipping...")
|
||||
debugLog("molecule \(updatedMolecule) is the same as \(rootMolecule). skipping...")
|
||||
return rootMolecule
|
||||
}
|
||||
debugLog("onPageNew replacing \(rootMolecule) with \(updatedMolecule)")
|
||||
debugLog("replacing \(rootMolecule) with \(updatedMolecule)")
|
||||
logUpdated(molecule: updatedMolecule)
|
||||
hasReplacement = true
|
||||
return updatedMolecule
|
||||
@ -89,10 +89,10 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) {
|
||||
guard !replacedMolecule.isEqual(to: newMolecule) else {
|
||||
// Note: Slight risk here of replacing the something in the original tree and misreporting that is it not replaced based on equality.
|
||||
debugLog("onPageNew molecule \(newMolecule) is the same as \(replacedMolecule). skipping...")
|
||||
debugLog("molecule \(newMolecule) is the same as \(replacedMolecule). skipping...")
|
||||
return
|
||||
}
|
||||
debugLog("onPageNew replacing \(replacedMolecule) with \(newMolecule)")
|
||||
debugLog("replacing \(replacedMolecule) with \(newMolecule)")
|
||||
logUpdated(molecule: newMolecule)
|
||||
hasReplacement = true
|
||||
}
|
||||
@ -106,6 +106,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
}
|
||||
return parentMolecule
|
||||
}
|
||||
debugLog("replacing \(hasReplacement ? updatedRootMolecules.count : 0) molecules")
|
||||
return hasReplacement ? updatedRootMolecules : nil
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user