diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 1601acfe..df83fc2a 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -174,7 +174,9 @@ open class Carousel: View { MVMCoreLoggingHandler.shared()?.handleDebugMessage("[\(Self.self)] [\(ObjectIdentifier(self).hashValue)]\noriginal model: \(originalModel?.debugDescription ?? "none")\nnew model: \(model)") if #available(iOS 15.0, *) { - if let originalModel, carouselModel.isDeeplyVisuallyEquivalent(to: originalModel) { + if let originalModel, carouselModel.isDeeplyVisuallyEquivalent(to: originalModel), + originalModel.visibleMolecules.isVisuallyEquivalent(to: molecules ?? []) // Since the carousel model's children are in place replaced and we do not have a deep copy of this model tree, add in this hack to check if the prior captured carousel items match the newly visible ones. + { // Prevents a carousel reset while still updating the cell backing data through reconfigureItems. MVMCoreLoggingHandler.shared()?.handleDebugMessage("[\(Self.self)] Model is visually equivalent. Skipping rebuild...") FormValidator.setupValidation(for: carouselModel, delegate: delegateObject?.formHolderDelegate) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift index affa294b..24a0bb02 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift @@ -17,4 +17,9 @@ public extension CarouselItemModelProtocol { get { nil } set { analyticsData = newValue } } + + var gone: Bool{ + get { false } + set { } + } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift index d0e1c13f..13bb75b3 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/ParentMoleculeModelProtocol.swift @@ -43,7 +43,7 @@ public extension ParentModelProtocol where Self: AnyObject { func replaceChildMolecule(in molecules: inout [T], with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? { var replacedMolecule: MoleculeModelProtocol? - return try replaceChildMolecule(at: &molecules, with: replacementMolecule, replaced: &replacedMolecule) ? replacedMolecule : nil + return try replaceChildMolecule(in: &molecules, with: replacementMolecule, replaced: &replacedMolecule) ? replacedMolecule : nil } /// Helper for replacing a molecule in place within an array. Note the "in". @@ -67,6 +67,26 @@ public protocol ParentMoleculeModelProtocol: ParentModelProtocol, MoleculeModelP public extension ParentMoleculeModelProtocol { + /// Recursively finds and replaces the first child matching the replacement molecule id property. + mutating func deepReplaceMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? { + var replacedMolecule: MoleculeModelProtocol? + var possibleError: Error? + // Dive into each root. + depthFirstTraverse(options: .parentFirst, depth: 0) { depth, molecule, stop in + guard var parentMolecule = molecule as? ParentMoleculeModelProtocol else { return } + do { + replacedMolecule = try parentMolecule.replaceChildMolecule(with: replacementMolecule) + } catch { + possibleError = error + } + stop = replacedMolecule != nil || possibleError != nil + } + if let error = possibleError { + throw error + } + return replacedMolecule + } + func reduceDepthFirstTraverse(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result { var result = initialResult if (options == .parentFirst) { diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift index b598041b..b3d8bb59 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TemplateModelProtocol.swift @@ -40,31 +40,3 @@ public extension TemplateModelProtocol { return rootMolecules.depthFirstTraverse(options: options, depth: depth, onVisit: onVisit) } } - -extension TemplateModelProtocol { - - /// Recursively finds and replaces the first child matching the replacement molecule id property. - mutating func replaceMolecule(with replacementMolecule: MoleculeModelProtocol) throws -> MoleculeModelProtocol? { - // Attempt root level replacement on the template model first. - if let replacedMolecule = try replaceChildMolecule(with: replacementMolecule) { - return replacedMolecule - } - - var replacedMolecule: MoleculeModelProtocol? - var possibleError: Error? - // Dive into each root thereafter. - depthFirstTraverse(options: .parentFirst, depth: 0) { depth, molecule, stop in - guard var parentMolecule = molecule as? ParentMoleculeModelProtocol else { return } - do { - replacedMolecule = try parentMolecule.replaceChildMolecule(with: replacementMolecule) - } catch { - possibleError = error - } - stop = replacedMolecule != nil || possibleError != nil - } - if let error = possibleError { - throw error - } - return replacedMolecule - } -} diff --git a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift index c03594d4..9cbf85ed 100644 --- a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift +++ b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift @@ -41,7 +41,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co self.delegateObject = delegateObject guard let pageType = delegateObject?.moleculeDelegate?.getTemplateModel()?.pageType else { return } MVMCoreViewControllerMappingObject.shared()?.addOptionalModules(toMapping: moleculeIds, forPageType: pageType) - Self.debugLog("Initializing for \((model as! ReplaceableMoleculeBehaviorModel).moleculeIds)") + Self.debugLog("Initializing for \(moleculeIds)") } public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?, changes: inout [MoleculeModelProtocol]) -> [MoleculeModelProtocol]? { @@ -85,7 +85,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co moleculeModels.forEach { newMolecule in do { - if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) { + if let replacedMolecule = try parentMolecule.deepReplaceMolecule(with: newMolecule) { guard !replacedMolecule.deepEquals(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("deep molecule \(newMolecule) is the same as \(replacedMolecule). skipping...")