From f403e34d7d98136a8c98171f5c73514efb940cae Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Tue, 21 May 2024 14:00:07 -0400 Subject: [PATCH] Digital PCT265 story PCT-135: Change filtering fix, disable partial page updates, move manager newDataReceived. --- .../BaseControllers/ViewController.swift | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 1579a790..928a9390 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -105,10 +105,6 @@ import MVMCore hasDataUpdate = true loadObject.pageJSON = pagesLoaded.optionalDictionaryForKey(pageType) - // TODO: Parse parsePageJSON modifies the page model on a different thread than - // the UI update which could cause discrepancies. Parse should return the resulting - // object and assignment should be synchronized on handleNewData(model: ). - // Separate page updates from the module updates to avoid unecessary resets to behaviors and full re-renders. do { pageModel = try parsePageJSON(loadObject: loadObject) @@ -262,11 +258,13 @@ import MVMCore // Replace again in case there is a template level child. if let replaced = try? newTemplateModel.replaceChildMolecule(with: molecule) { // Only recognize the molecules that actually changed. - debugLog("Behavior updated \(changes) in template model.") - changes = changes.filter({ model in - behaviorUpdatedModels.contains { $0.id == model.id } - }) - behaviorUpdatedModels.append(contentsOf: changes) + if changes.count > 0 { + debugLog("\(behavior) updated \(changes) in template model.") + changes = changes.filter({ model in + !behaviorUpdatedModels.contains { $0.id == model.id } + }) + behaviorUpdatedModels.append(contentsOf: changes) + } } else { debugLog("Failed to replace \(molecule) in the template model.") } @@ -289,37 +287,36 @@ import MVMCore if let originalModel, // We had a prior. let newPageModel = newPageModel as? TemplateModelProtocol, originalModel.id != newPageModel.id { - let diffs = newPageModel.deepCompare(against: originalModel) { new, old in - !new.isEqual(to: old) - } - debugLog("Page molecule updates\n\(diffs.map {"\($0.mine) vs. \($0.theirs)"}.joined(separator: "\n"))") - pageUpdatedModels = diffs.compactMap { $0.theirs as? MoleculeModelProtocol } + // This isn't ready yet. handleNewData for the ListTemplate triggers a row item reset and full rebuild + StackTemplate isn't targeting individual refreshes anyway. +// pageUpdatedModels = originalModel.findAllTheirsNotEqual(against: newPageModel) +// debugLog("Page molecule updates\n\(pageUpdatedModels)") + isFirstRender = true // Instead force a full render whenever there is a page data change. } - let allUpdatedMolecules = isFirstRender ? [] : behaviorUpdatedModels + pageUpdatedModels + let allUpdatedMolecules = behaviorUpdatedModels //+ pageUpdatedModels - isFirstRender = false + // Notify the manager of new data. + // Warning: Some flows cause table reloads. Until the UI update is decoupled, should be after the updateUI. + manager?.newDataReceived?(in: self) // Dispatch to decouple execution. First massage data through template classes, then render. Task { @MainActor in - if allUpdatedMolecules.isEmpty { + if allUpdatedMolecules.isEmpty || isFirstRender { debugLog("Performing full page render...") updateUI() } else { debugLog("Performing partial render of \(allUpdatedMolecules) molecules...") updateUI(for: allUpdatedMolecules) } - - // Notify the manager of new data. - // Warning: Some flows cause table reloads. Until the UI update is decoupled, should be after the updateUI. - manager?.newDataReceived?(in: self) } } /// Applies the latest model to the UI. open func updateUI(for molecules: [MoleculeModelProtocol]? = nil) { + isFirstRender = false + executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in behavior.willRender(rootMolecules: molecules ?? getRootMolecules(), delegateObjectIVar) }