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
|
&& fontName == model.fontName
|
||||||
&& fontSize == model.fontSize
|
&& fontSize == model.fontSize
|
||||||
&& textAlignment == model.textAlignment
|
&& textAlignment == model.textAlignment
|
||||||
&& attributes.isEqual(to: model.attributes)
|
&& attributes.isVisuallyEquivalent(to: model.attributes)
|
||||||
&& html == model.html
|
&& html == model.html
|
||||||
&& hero == model.hero
|
&& hero == model.hero
|
||||||
&& makeWholeViewClickable == model.makeWholeViewClickable
|
&& makeWholeViewClickable == model.makeWholeViewClickable
|
||||||
|
|||||||
@ -106,9 +106,28 @@ open class TabBarModel: MoleculeModelProtocol {
|
|||||||
try container.encode(selectedTab, forKey: .selectedTab)
|
try container.encode(selectedTab, forKey: .selectedTab)
|
||||||
try container.encodeIfPresent(style, forKey: .style)
|
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 title: String?
|
||||||
open var image: String
|
open var image: String
|
||||||
open var action: ActionModelProtocol
|
open var action: ActionModelProtocol
|
||||||
@ -142,4 +161,18 @@ open class TabBarItemModel: Codable {
|
|||||||
try container.encodeModel(action, forKey: .action)
|
try container.encodeModel(action, forKey: .action)
|
||||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
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.encode(borderLine, forKey: .borderLine)
|
||||||
try container.encodeIfPresent(minWidth, forKey: .minWidth)
|
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, Equatable, MoleculeModelComparisonProtocol {
|
||||||
|
|
||||||
open class TabItemModel: Codable {
|
|
||||||
open var label: LabelModel
|
open var label: LabelModel
|
||||||
open var action: ActionModelProtocol?
|
open var action: ActionModelProtocol?
|
||||||
|
|
||||||
@ -146,4 +174,14 @@ open class TabItemModel: Codable {
|
|||||||
try container.encodeModel(label, forKey: .label)
|
try container.encodeModel(label, forKey: .label)
|
||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
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 }
|
return molecules.flatMap { $0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> Bool {
|
public func replaceChildMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? {
|
||||||
guard let replacementMolecule = replacementMolecule as? ListItemModelProtocol & MoleculeModelProtocol else { return false }
|
guard let replacementMolecule = replacementMolecule as? ListItemModelProtocol & MoleculeModelProtocol else { return nil }
|
||||||
for (tabIndex, _) in molecules.enumerated() {
|
for (tabIndex, _) in molecules.enumerated() {
|
||||||
for (elementIndex, _) in molecules[tabIndex].enumerated() {
|
for (elementIndex, _) in molecules[tabIndex].enumerated() {
|
||||||
if molecules[tabIndex][elementIndex].id == replacementMolecule.id {
|
if molecules[tabIndex][elementIndex].id == replacementMolecule.id {
|
||||||
|
let replacedMolecule = molecules[tabIndex][elementIndex]
|
||||||
molecules[tabIndex][elementIndex] = replacementMolecule
|
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.encode(tabs, forKey: .tabs)
|
||||||
try container.encodeModels2D(molecules, forKey: .molecules)
|
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 {
|
extension TabsListItemModel: PageBehaviorProtocolRequirer {
|
||||||
|
|||||||
@ -141,6 +141,17 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
|
|||||||
try container.encodeIfPresent(style, forKey: .style)
|
try container.encodeIfPresent(style, forKey: .style)
|
||||||
try container.encodeIfPresent(titleOffset, forKey: .titleOffset)
|
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 {
|
extension NavigationItemModel: ParentMoleculeModelProtocol {
|
||||||
|
|||||||
@ -101,6 +101,14 @@ open class HeadlineBodyModel: ParentMoleculeModelProtocol {
|
|||||||
&& style == style
|
&& style == style
|
||||||
&& backgroundColor == backgroundColor
|
&& 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 {
|
public extension HeadlineBodyModel {
|
||||||
|
|||||||
@ -86,4 +86,12 @@
|
|||||||
&& axis == model.axis
|
&& axis == model.axis
|
||||||
&& spacing == model.spacing
|
&& 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) {
|
func printMolecules(options: TreeTraversalOptions = .parentFirst) {
|
||||||
depthFirstTraverse(options: options, depth: 1) { depth, molecule, stop in
|
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]? {
|
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
|
var hasReplacement = false
|
||||||
let updatedRootMolecules = rootMolecules.map { rootMolecule in
|
let updatedRootMolecules = rootMolecules.map { rootMolecule in
|
||||||
|
|
||||||
// Top level check to return a new root molecule.
|
// Top level check to return a new root molecule.
|
||||||
if let updatedMolecule = moleculeModels.first(where: { rootMolecule.id == $0.id }) {
|
if let updatedMolecule = moleculeModels.first(where: { rootMolecule.id == $0.id }) {
|
||||||
guard !updatedMolecule.isEqual(to: rootMolecule) else {
|
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
|
return rootMolecule
|
||||||
}
|
}
|
||||||
debugLog("onPageNew replacing \(rootMolecule) with \(updatedMolecule)")
|
debugLog("replacing \(rootMolecule) with \(updatedMolecule)")
|
||||||
logUpdated(molecule: updatedMolecule)
|
logUpdated(molecule: updatedMolecule)
|
||||||
hasReplacement = true
|
hasReplacement = true
|
||||||
return updatedMolecule
|
return updatedMolecule
|
||||||
@ -89,10 +89,10 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) {
|
if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) {
|
||||||
guard !replacedMolecule.isEqual(to: newMolecule) else {
|
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.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
debugLog("onPageNew replacing \(replacedMolecule) with \(newMolecule)")
|
debugLog("replacing \(replacedMolecule) with \(newMolecule)")
|
||||||
logUpdated(molecule: newMolecule)
|
logUpdated(molecule: newMolecule)
|
||||||
hasReplacement = true
|
hasReplacement = true
|
||||||
}
|
}
|
||||||
@ -106,6 +106,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
}
|
}
|
||||||
return parentMolecule
|
return parentMolecule
|
||||||
}
|
}
|
||||||
|
debugLog("replacing \(hasReplacement ? updatedRootMolecules.count : 0) molecules")
|
||||||
return hasReplacement ? updatedRootMolecules : nil
|
return hasReplacement ? updatedRootMolecules : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user