Merge branch 'bugfix/CXTDT-538262' into 'develop'
Digital ACT191 defect CXTDT-538262 - 'Fix tab selection flicker.' ### Summary Update the tab selection logic to occur in a single table transaction to animate smoothly. ### JIRA Ticket https://onejira.verizon.com/browse/CXTDT-538262 Co-authored-by: Hedden, Kyle Matthew <kyle.hedden@verizonwireless.com> See merge request https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui/-/merge_requests/1089
This commit is contained in:
commit
52f93e86cc
@ -54,9 +54,6 @@ import UIKit
|
||||
extension TabsTableViewCell: TabsDelegate {
|
||||
public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
|
||||
guard indexPath.row != tabs.selectedIndex else { return false }
|
||||
if let model = tabsListItemModel {
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: RemoveMoleculesActionModel(indexPath.row < tabs.selectedIndex ? .right : .left), sourceModel: model, additionalData: nil, delegateObject: delegateObject)
|
||||
}
|
||||
previousTabIndex = tabs.selectedIndex
|
||||
return true
|
||||
}
|
||||
@ -68,7 +65,7 @@ extension TabsTableViewCell: TabsDelegate {
|
||||
if let action = model.tabs.tabs[index].action {
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: model.tabs, additionalData: nil, delegateObject: delegateObject)
|
||||
}
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: AddMoleculesActionModel(index < previousTabIndex ? .left : .right), sourceModel: model, additionalData: nil, delegateObject: delegateObject)
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: SwapMoleculesActionModel(index < previousTabIndex ? .left : .right), sourceModel: model, additionalData: nil, delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,9 @@ public protocol MoleculeListProtocol {
|
||||
|
||||
/// Asks the delegate to remove molecules.
|
||||
func removeMolecules(at indexPaths: [IndexPath], animation: UITableView.RowAnimation?)
|
||||
|
||||
/// Asks the delegate to swap batches of molecules.
|
||||
func swapMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], with replacements: [ListItemModelProtocol & MoleculeModelProtocol], at indexPath: IndexPath, animation: UITableView.RowAnimation?)
|
||||
}
|
||||
|
||||
extension MoleculeListProtocol {
|
||||
|
||||
@ -375,6 +375,54 @@ extension MoleculeListTemplate: MoleculeListProtocol {
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
public func swapMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], with replacements: [ListItemModelProtocol & MoleculeModelProtocol], at indexPath: IndexPath, animation: UITableView.RowAnimation?) {
|
||||
|
||||
tableView.beginUpdates()
|
||||
|
||||
var indexPaths: [IndexPath] = []
|
||||
for molecule in molecules {
|
||||
guard let indexPath = getIndexPath(for: molecule) else { continue }
|
||||
indexPaths.append(indexPath)
|
||||
}
|
||||
for (index, indexPath) in indexPaths.sorted().enumerated() {
|
||||
let removeIndex = indexPath.row - index
|
||||
moleculesInfo?.remove(at: removeIndex)
|
||||
}
|
||||
|
||||
var exitAnimation = UITableView.RowAnimation.automatic
|
||||
switch animation {
|
||||
case .left: exitAnimation = .right
|
||||
case .right: exitAnimation = .left
|
||||
case .top: exitAnimation = .bottom
|
||||
case .bottom: exitAnimation = .top
|
||||
default: break
|
||||
}
|
||||
|
||||
if indexPaths.count > 0 {
|
||||
tableView?.deleteRows(at: indexPaths, with: exitAnimation)
|
||||
}
|
||||
|
||||
indexPaths = []
|
||||
for molecule in replacements {
|
||||
if let info = self.createMoleculeInfo(with: molecule) {
|
||||
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
||||
let index = indexPath.row + indexPaths.count
|
||||
self.moleculesInfo?.insert(info, at: index)
|
||||
indexPaths.append(IndexPath(row: index, section: 0))
|
||||
}
|
||||
}
|
||||
|
||||
if let animation = animation,
|
||||
indexPaths.count > 0 {
|
||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||
}
|
||||
|
||||
tableView.endUpdates()
|
||||
|
||||
self.updateViewConstraints()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
public func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||
return equal(moleculeA: molecule, moleculeB: moleculeInfo.molecule)
|
||||
|
||||
@ -87,25 +87,38 @@ public class AddRemoveMoleculesBehavior: PageCustomActionHandlerBehavior, PageMo
|
||||
}
|
||||
|
||||
public func canHandleAction(with model: ActionModelProtocol, additionalData: [AnyHashable : Any]?) -> Bool {
|
||||
return model.actionType == AddMoleculesActionModel.identifier || model.actionType == RemoveMoleculesActionModel.identifier
|
||||
return [AddMoleculesActionModel.identifier, RemoveMoleculesActionModel.identifier, SwapMoleculesActionModel.identifier].contains(model.actionType)
|
||||
}
|
||||
|
||||
public func handleAction(with model: ActionModelProtocol, additionalData: [AnyHashable : Any]?) async throws {
|
||||
if let model = model as? AddMoleculesActionModel,
|
||||
let list = delegate?.moleculeListDelegate,
|
||||
let sourceModel = MVMCoreUIActionHandler.getSourceModel(from: additionalData) as? (ListItemModelProtocol & MoleculeModelProtocol & AddMolecules),
|
||||
let moleculesToAdd = sourceModel.getRecursiveMoleculesToAdd(),
|
||||
let indexPath = list.getAdjustedIndexPath(for: sourceModel, position: moleculesToAdd.1) {
|
||||
switch model {
|
||||
case let model as AddMoleculesActionModel:
|
||||
guard let list = delegate?.moleculeListDelegate,
|
||||
let sourceModel = MVMCoreUIActionHandler.getSourceModel(from: additionalData) as? (ListItemModelProtocol & MoleculeModelProtocol & AddMolecules),
|
||||
let moleculesToAdd = sourceModel.getRecursiveMoleculesToAdd(),
|
||||
let indexPath = list.getAdjustedIndexPath(for: sourceModel, position: moleculesToAdd.1) else { break }
|
||||
await MainActor.run {
|
||||
list.addMolecules(moleculesToAdd.0, indexPath: indexPath, animation: model.animation)
|
||||
}
|
||||
} else if let model = model as? RemoveMoleculesActionModel,
|
||||
let list = delegate?.moleculeListDelegate,
|
||||
case let model as RemoveMoleculesActionModel:
|
||||
guard let list = delegate?.moleculeListDelegate,
|
||||
let sourceModel = MVMCoreUIActionHandler.getSourceModel(from: additionalData) as? (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules),
|
||||
let moleculesToRemove = sourceModel.getRecursiveMoleculesToRemove() {
|
||||
let moleculesToRemove = sourceModel.getRecursiveMoleculesToRemove() else { break }
|
||||
await MainActor.run {
|
||||
list.removeMolecules(moleculesToRemove, animation: model.animation)
|
||||
}
|
||||
case let model as SwapMoleculesActionModel:
|
||||
guard let list = delegate?.moleculeListDelegate,
|
||||
let sourceModel = MVMCoreUIActionHandler.getSourceModel(from: additionalData) as? (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules & AddMolecules),
|
||||
let moleculesToRemove = sourceModel.getRecursiveMoleculesToRemove(),
|
||||
let moleculesToAdd = sourceModel.getRecursiveMoleculesToAdd(),
|
||||
let indexPath = list.getAdjustedIndexPath(for: sourceModel, position: moleculesToAdd.1)
|
||||
else { break }
|
||||
await MainActor.run {
|
||||
list.swapMolecules(moleculesToRemove, with: moleculesToAdd.0, at: indexPath, animation: model.animation)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,3 +187,30 @@ public class RemoveMoleculesActionModel: ActionModelProtocol {
|
||||
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
|
||||
}
|
||||
}
|
||||
|
||||
public class SwapMoleculesActionModel: ActionModelProtocol {
|
||||
public static var identifier: String = "swapMoleculesAction"
|
||||
public var actionType: String = SwapMoleculesActionModel.identifier
|
||||
public var animation: UITableView.RowAnimation = .automatic
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(_ animation: UITableView.RowAnimation, extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
self.animation = animation
|
||||
self.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
}
|
||||
|
||||
public required init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
if let animation = try typeContainer.decodeIfPresent(UITableView.RowAnimation.self, forKey: .animation) {
|
||||
self.animation = animation
|
||||
}
|
||||
extraParameters = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .extraParameters)
|
||||
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user