From a50c6ffed51f87271a9946fb75bb228ec3209b0b Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Fri, 13 Sep 2024 17:23:00 -0400 Subject: [PATCH] Digital PCT265 defect MVAPCT-272: Adjust molecule adds and swapping. --- .../Templates/MoleculeListTemplate.swift | 127 +++++++----------- 1 file changed, 45 insertions(+), 82 deletions(-) diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index 939c0d7c..c6ba5b1e 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -8,7 +8,7 @@ import UIKit -public struct MoleculeInfo: Hashable { +public struct MoleculeInfo: Hashable, CustomDebugStringConvertible { public func hash(into hasher: inout Hasher) { hasher.combine(id) @@ -44,6 +44,10 @@ public struct MoleculeInfo: Hashable { } }) } + + public var debugDescription: String { + return "\(Self.self) \(id)" + } } extension Array where Element == MoleculeInfo { @@ -52,14 +56,15 @@ extension Array where Element == MoleculeInfo { filter { listItemRef in molecules.contains { $0.id == listItemRef.model.id } } } - func registerTypes(with tableView: UITableView) { + func registerTypes(with tableView: UITableView) -> [MoleculeInfo] { forEach { tableView.register($0.cellType, forCellReuseIdentifier: $0.cellReuseId) } + return self } } extension Array where Element == ListItemModelProtocol & MoleculeModelProtocol { - func asMoleculeInfoRef() -> [MoleculeInfo] { - compactMap { MoleculeInfo(listItemModel: $0) } + func asMoleculeInfoRef(delegateObject: MVMCoreUIDelegateObject?) -> [MoleculeInfo] { + compactMap { MoleculeInfo(listItemModel: $0, delegateObject: delegateObject) } } } @@ -208,16 +213,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Table View //-------------------------------------------------- - open override func registerWithTable() { - super.registerWithTable() - - for moleculeInfo in dataSource.snapshot().itemIdentifiers { - tableView?.register(moleculeInfo.cellType, forCellReuseIdentifier: moleculeInfo.cellReuseId) - } - } - open func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return (dataSource.itemIdentifier(for: indexPath)?.model as? GoneableProtocol)?.gone == true ? 0 : UITableView.automaticDimension + return dataSource.itemIdentifier(for: indexPath)?.model.gone == true ? 0 : UITableView.automaticDimension } open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { @@ -227,28 +224,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol return estimatedHeight } - -// open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { -// debugLog("Number of rows: \(moleculesInfo?.count ?? 0)") -// return moleculesInfo?.count ?? 0 -// } - -// open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { -// -// guard let moleculeInfo = getMoleculeInfo(for: indexPath), -// let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) -// else { return UITableViewCell() } -// cell.isHidden = (getMoleculeInfo(for: indexPath)?.molecule as? GoneableProtocol)?.gone == true -// (cell as? MoleculeViewProtocol)?.reset() -// (cell as? MoleculeListCellProtocol)?.setLines(with: templateModel?.line, delegateObject: delegateObjectIVar, additionalData: nil, indexPath: indexPath) -// if let moleculeView = cell as? MoleculeViewProtocol { -// updateMoleculeView(moleculeView, from: moleculeInfo.molecule) -// } -// (cell as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width) -// // Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells -// cell.setNeedsLayout() -// return cell -// } open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { (cell as? MoleculeListCellProtocol)?.willDisplay() @@ -327,10 +302,11 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var snapshot = dataSource.snapshot() let updatedListItems: [MoleculeInfo] = snapshot.itemIdentifiers.compactMap { listItemRef -> MoleculeInfo? in - var listItemRef = listItemRef guard let matchedMolecule = listItemRef.contains(oneOf: molecules) else { return nil } if let matchedMolecule = matchedMolecule as? (ListItemModelProtocol & MoleculeModelProtocol), listItemRef.doesMatch(matchedMolecule) { + var listItemRef = listItemRef listItemRef.model = matchedMolecule // Replace the top level molecule if it changed. + return listItemRef } return listItemRef } @@ -367,38 +343,13 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Convenience //-------------------------------------------------- - /// Returns the (identifier, class) of the molecule for the indexPath. -// func getMoleculeInfo(for indexPath: IndexPath) -> MoleculeInfo? { -// moleculesInfo?[safe: indexPath.row] -// } - - /// Sets up the molecule list and ensures no errors loading all content. -// func getMoleculeInfoList() -> [MoleculeInfo]? { -// -// var moleculeList: [MoleculeInfo] = [] -// -// if let molecules = templateModel?.molecules { -// for molecule in molecules { -// if let info = MoleculeInfo(with: molecule) { -// moleculeList.append(info) -// } -// } -// } -// -// return moleculeList.count > 0 ? moleculeList : nil -// } - /// Sets up the header, footer, molecule list and ensures no errors loading all content. func setup() { - guard let listItems = templateModel?.molecules?.compactMap({ MoleculeInfo(listItemModel: $0, delegateObject: delegateObject() as? MVMCoreUIDelegateObject)}) else { - debugLog("There is no data to display.") - return - } - + guard let listItems = templateModel?.molecules?.asMoleculeInfoRef(delegateObject: delegateObjectIVar).registerTypes(with: tableView) else { return } var initialDataSnapshot = ListDataSnapshot() initialDataSnapshot.appendSections([0]) initialDataSnapshot.appendItems(listItems) - dataSource.apply(initialDataSnapshot) + dataSource.apply(initialDataSnapshot, animatingDifferences: false) } /// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map. @@ -448,7 +399,7 @@ extension MoleculeListTemplate: MoleculeListProtocol { /// Convenience function that removes the passed molecule public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation?) { var snapshot = dataSource.snapshot() - snapshot.deleteItems(molecules.asMoleculeInfoRef()) + snapshot.deleteItems(molecules.asMoleculeInfoRef(delegateObject: delegateObjectIVar)) dataSource.apply(snapshot, animatingDifferences: true) { self.updateViewConstraints() self.view.setNeedsLayout() @@ -456,20 +407,30 @@ extension MoleculeListTemplate: MoleculeListProtocol { } public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation?) { + let additionalMoleculesRef = molecules.asMoleculeInfoRef(delegateObject: delegateObjectIVar).registerTypes(with: tableView) var snapshot = dataSource.snapshot() - guard let listItemRef = snapshot.itemIdentifiers[safe: indexPath.row] else { return } - snapshot.insertItems(molecules.asMoleculeInfoRef(), afterItem: listItemRef) - dataSource.apply(snapshot, animatingDifferences: true) { + debugLog("[ADD] State before: \(snapshot.itemIdentifiers)") + if let targetMoleculeRef = snapshot.itemIdentifiers[safe: indexPath.row] { + snapshot.insertItems(additionalMoleculesRef, beforeItem: targetMoleculeRef) + debugLog("[ADD] Applying: \(snapshot.itemIdentifiers)") + } else { + snapshot.appendItems(additionalMoleculesRef) + debugLog("[ADD] Applying: \(snapshot.itemIdentifiers)") + } + dataSource.apply(snapshot, animatingDifferences: false) { self.updateViewConstraints() self.view.setNeedsLayout() } } public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], after molecule: (ListItemModelProtocol & MoleculeModelProtocol), animation: UITableView.RowAnimation?) { - guard let listMoleculeRef = MoleculeInfo(listItemModel: molecule) else { return } + guard let targetMoleculeRef = MoleculeInfo(listItemModel: molecule) else { return } + let additionalMoleculesRef = molecules.asMoleculeInfoRef(delegateObject: delegateObjectIVar).registerTypes(with: tableView) var snapshot = dataSource.snapshot() - snapshot.insertItems(molecules.asMoleculeInfoRef(), afterItem: listMoleculeRef) - dataSource.apply(snapshot, animatingDifferences: true) { + debugLog("[ADD] State before: \(snapshot.itemIdentifiers)") + snapshot.insertItems(additionalMoleculesRef, afterItem: targetMoleculeRef) + debugLog("[ADD] Applying: \(snapshot.itemIdentifiers)") + dataSource.apply(snapshot, animatingDifferences: false) { self.updateViewConstraints() self.view.setNeedsLayout() } @@ -478,27 +439,29 @@ extension MoleculeListTemplate: MoleculeListProtocol { public func swapMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], with replacements: [ListItemModelProtocol & MoleculeModelProtocol], at indexPath: IndexPath, animation: UITableView.RowAnimation?) { swapMolecules(molecules, with: replacements, after: dataSource.snapshot().itemIdentifiers[safe: indexPath.row] as? (ListItemModelProtocol & MoleculeModelProtocol), animation: animation) } - + public func swapMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], with replacements: [ListItemModelProtocol & MoleculeModelProtocol], after targetMolecule: (ListItemModelProtocol & MoleculeModelProtocol)?, animation: UITableView.RowAnimation?) { guard let tableView else { return } - let removingRefs = molecules.asMoleculeInfoRef() - var snapshot = dataSource.snapshot() - let replacementRefs = molecules.asMoleculeInfoRef() - replacementRefs.registerTypes(with: tableView) - - if let targetMolecule, let targetRef = MoleculeInfo(listItemModel: targetMolecule) { - snapshot.insertItems(replacementRefs, afterItem: targetRef) - } else if let targetRef = removingRefs.first { - snapshot.insertItems(replacementRefs, beforeItem: targetRef) - } + debugLog("[SWAP] State before: \(snapshot.itemIdentifiers)") + let removingRefs = molecules.asMoleculeInfoRef(delegateObject: delegateObjectIVar) snapshot.deleteItems(removingRefs) - dataSource.apply(snapshot) { + debugLog("[SWAP] State after delete: \(snapshot.itemIdentifiers)") + + if let targetMolecule, let targetRef = MoleculeInfo(listItemModel: targetMolecule) { + let replacementRefs = molecules.asMoleculeInfoRef(delegateObject: delegateObjectIVar).registerTypes(with: tableView) + snapshot.insertItems(replacementRefs, afterItem: targetRef) + } + + debugLog("[SWAP] Applying: \(snapshot.itemIdentifiers)") + dataSource.defaultRowAnimation = animation ?? .automatic + dataSource.apply(snapshot ) { + self.dataSource.defaultRowAnimation = .automatic self.updateViewConstraints() self.view.setNeedsLayout() }