add and remove clean up, tabs addition
This commit is contained in:
parent
e853647367
commit
dc12612c6f
@ -513,6 +513,7 @@
|
||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
|
||||
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; };
|
||||
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */; };
|
||||
D2E0FFF826AF68530085D696 /* UITableViewRowAnimation+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */; };
|
||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
||||
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; };
|
||||
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; };
|
||||
@ -1082,6 +1083,7 @@
|
||||
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
|
||||
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = "<group>"; };
|
||||
D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainerProtocol.swift; sourceTree = "<group>"; };
|
||||
D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewRowAnimation+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
||||
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = "<group>"; };
|
||||
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||
@ -1486,6 +1488,7 @@
|
||||
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
|
||||
D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */,
|
||||
D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */,
|
||||
D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -2942,6 +2945,7 @@
|
||||
BB2BF0EC2452A9D5001D0FC2 /* ListDeviceComplexButtonSmallModel.swift in Sources */,
|
||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */,
|
||||
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
|
||||
D2E0FFF826AF68530085D696 /* UITableViewRowAnimation+Extension.swift in Sources */,
|
||||
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */,
|
||||
AA07EA912510A442009A2AE3 /* StarModel.swift in Sources */,
|
||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
//
|
||||
// UITableViewRowAnimation.swift
|
||||
// UITableViewRowAnimation+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 7/26/21.
|
||||
// Copyright © 2021 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
extension UITableView.RowAnimation: Codable {}
|
||||
|
||||
@ -68,22 +68,22 @@ class AccordionListItemModel: MoleculeListItemModel {
|
||||
|
||||
extension AccordionListItemModel: PageBehaviorProtocolRequirer {
|
||||
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||
return [AddRemoveMoleculeBehaviorModel()]
|
||||
return [AddRemoveMoleculesBehaviorModel()]
|
||||
}
|
||||
}
|
||||
|
||||
extension AccordionListItemModel: AddMolecules {
|
||||
public func moleculesToAdd() -> ([ListItemModelProtocol & MoleculeModelProtocol], AddMoleculePosition, UITableView.RowAnimation?)? {
|
||||
public func moleculesToAdd() -> AddMolecules.AddParameters? {
|
||||
guard !added, selected else { return nil }
|
||||
added = true
|
||||
return (molecules, .below, .automatic)
|
||||
return (molecules, .below)
|
||||
}
|
||||
}
|
||||
|
||||
extension AccordionListItemModel: RemoveMolecules {
|
||||
public func moleculesToRemove() -> ([ListItemModelProtocol & MoleculeModelProtocol], UITableView.RowAnimation?)? {
|
||||
public func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||
guard added else { return nil }
|
||||
added = false
|
||||
return (molecules, .automatic)
|
||||
return molecules
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@
|
||||
model.selected = accordionButton.isSelected
|
||||
|
||||
if accordionButton.isSelected {
|
||||
MVMCoreActionHandler.shared()?.handleAction(AddMoleculesActionModel.identifier, actionInformation: nil, additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||
MVMCoreActionHandler.shared()?.asyncHandleAction(with: AddMoleculesActionModel(.automatic), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||
} else {
|
||||
MVMCoreActionHandler.shared()?.handleAction(RemoveMoleculesActionModel.identifier, actionInformation: nil, additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||
MVMCoreActionHandler.shared()?.asyncHandleAction(with: RemoveMoleculesActionModel(.automatic), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) {
|
||||
@ -60,5 +60,10 @@
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? AccordionListItemModel else { return }
|
||||
accordionButton.isSelected = model.selected
|
||||
accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal)
|
||||
|
||||
if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) {
|
||||
bottomSeparatorView?.isHidden = accordionButton.isSelected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,10 +32,9 @@ import UIKit
|
||||
MVMCoreDispatchUtility.performBlock(inBackground: {
|
||||
if let oldValue = oldValue,
|
||||
oldValue.count > 0 {
|
||||
MVMCoreUIActionHandler.shared()?.synchronouslyHandleAction(RemoveMoleculesActionModel.identifier, actionInformation: nil, additionalData: [KeySourceModel: model], delegateObject: self.delegateObject)
|
||||
MVMCoreActionHandler.shared()?.syncHandleAction(with: RemoveMoleculesActionModel(.fade), additionalData: [KeySourceModel: model], delegateObject: self.delegateObject)
|
||||
}
|
||||
|
||||
MVMCoreActionHandler.shared()?.handleAction(AddMoleculesActionModel.identifier, actionInformation: nil, additionalData: [KeySourceModel: model], delegateObject: self.delegateObject)
|
||||
MVMCoreActionHandler.shared()?.syncHandleAction(with: AddMoleculesActionModel(.fade), additionalData: [KeySourceModel: model], delegateObject: self.delegateObject)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,24 +86,24 @@ import Foundation
|
||||
|
||||
extension DropDownListItemModel: PageBehaviorProtocolRequirer {
|
||||
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||
return [AddRemoveMoleculeBehaviorModel()]
|
||||
return [AddRemoveMoleculesBehaviorModel()]
|
||||
}
|
||||
}
|
||||
|
||||
extension DropDownListItemModel: AddMolecules {
|
||||
public func moleculesToAdd() -> ([ListItemModelProtocol & MoleculeModelProtocol], AddMoleculePosition, UITableView.RowAnimation?)? {
|
||||
public func moleculesToAdd() -> AddMolecules.AddParameters? {
|
||||
guard addedMolecules == nil,
|
||||
let index = dropDown.selectedIndex else { return nil }
|
||||
let addedMolecules = molecules[index]
|
||||
self.addedMolecules = addedMolecules
|
||||
return (addedMolecules, .below, .fade)
|
||||
return (addedMolecules, .below)
|
||||
}
|
||||
}
|
||||
|
||||
extension DropDownListItemModel: RemoveMolecules {
|
||||
public func moleculesToRemove() -> ([ListItemModelProtocol & MoleculeModelProtocol], UITableView.RowAnimation?)? {
|
||||
public func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||
guard let addedMolecules = addedMolecules else { return nil }
|
||||
self.addedMolecules = nil
|
||||
return (addedMolecules, .fade)
|
||||
return addedMolecules
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,8 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "tabsListItem"
|
||||
var tabs: TabsModel
|
||||
var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
|
||||
|
||||
private var addedMolecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
@ -70,3 +71,26 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
|
||||
try container.encodeModels2D(molecules, forKey: .molecules)
|
||||
}
|
||||
}
|
||||
|
||||
extension TabsListItemModel: PageBehaviorProtocolRequirer {
|
||||
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||
return [AddRemoveMoleculesBehaviorModel()]
|
||||
}
|
||||
}
|
||||
|
||||
extension TabsListItemModel: AddMolecules {
|
||||
public func moleculesToAdd() -> AddMolecules.AddParameters? {
|
||||
guard addedMolecules == nil else { return nil }
|
||||
let addedMolecules = molecules[tabs.selectedIndex]
|
||||
self.addedMolecules = addedMolecules
|
||||
return (addedMolecules, .below)
|
||||
}
|
||||
}
|
||||
|
||||
extension TabsListItemModel: RemoveMolecules {
|
||||
public func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||
guard let addedMolecules = addedMolecules else { return nil }
|
||||
self.addedMolecules = nil
|
||||
return addedMolecules
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,9 +55,9 @@ import UIKit
|
||||
// TODO: Move to AddRemoveMoleculeBehaviorModel
|
||||
extension TabsTableViewCell: TabsDelegate {
|
||||
public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
|
||||
guard indexPath.row != tabs.selectedIndex else { return false }
|
||||
if let model = tabsListItemModel {
|
||||
let molecules = model.molecules[tabs.selectedIndex]
|
||||
delegateObject?.moleculeListDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left)
|
||||
MVMCoreActionHandler.shared()?.asyncHandleAction(with: RemoveMoleculesActionModel(indexPath.row < tabs.selectedIndex ? .right : .left), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||
}
|
||||
previousTabIndex = tabs.selectedIndex
|
||||
return true
|
||||
@ -65,12 +65,9 @@ extension TabsTableViewCell: TabsDelegate {
|
||||
|
||||
public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) {
|
||||
let index = indexPath.row
|
||||
if let model = tabsListItemModel,
|
||||
index < model.molecules.count,
|
||||
let cellIndexPath = delegateObject?.moleculeListDelegate?.getIndexPath(for: model) {
|
||||
let molecules = model.molecules[index]
|
||||
delegateObject?.moleculeListDelegate?.addMolecules(molecules, indexPath: cellIndexPath, animation: index < previousTabIndex ? .left : .right)
|
||||
}
|
||||
guard let model = tabsListItemModel,
|
||||
index < model.molecules.count else { return }
|
||||
MVMCoreActionHandler.shared()?.asyncHandleAction(with: AddMoleculesActionModel(index < previousTabIndex ? .left : .right), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -182,44 +182,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
// MARK: - MoleculeDelegateProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
|
||||
guard let tableView = tableView else { return }
|
||||
if let indexPath = tableView.indexPathForRow(at: molecule.center), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
|
||||
performTableViewUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
open override func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||
//TODO: check for molecule protocol eqaulity
|
||||
let json = moleculeInfo.molecule.toJSON()
|
||||
return json == molecule.toJSON()
|
||||
}) else { return nil }
|
||||
|
||||
return IndexPath(row: index, section: 0)
|
||||
}
|
||||
|
||||
open override func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
|
||||
DispatchQueue.main.async {
|
||||
var indexPaths: [IndexPath] = []
|
||||
|
||||
for molecule in molecules {
|
||||
if let info = self.createMoleculeInfo(with: molecule) {
|
||||
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
||||
let index = indexPath.row + 1 + indexPaths.count
|
||||
self.moleculesInfo?.insert(info, at: index)
|
||||
indexPaths.append(IndexPath(row: index, section: 0))
|
||||
}
|
||||
}
|
||||
|
||||
guard indexPaths.count > 0 else { return }
|
||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||
self.updateViewConstraints()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
open func newData(for molecule: MoleculeModelProtocol) {
|
||||
//TODO: expand for header, navigation, etc
|
||||
let json = molecule.toJSON()
|
||||
@ -252,23 +214,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
tableView.selectRow(at: selectedIndex, animated: false, scrollPosition: .none)
|
||||
}
|
||||
}
|
||||
|
||||
open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {
|
||||
var indexPaths: [IndexPath] = []
|
||||
//TODO: check for molecule protocol equality
|
||||
|
||||
for molecule in molecules {
|
||||
if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
|
||||
moleculesInfo?.remove(at: removeIndex)
|
||||
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
|
||||
}
|
||||
}
|
||||
|
||||
guard indexPaths.count > 0 else { return }
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
updateViewConstraints()
|
||||
view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Convenience
|
||||
@ -337,91 +282,57 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
|
||||
extension MoleculeListTemplate: MoleculeListProtocol {
|
||||
open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
|
||||
guard let tableView = tableView else { return }
|
||||
if let indexPath = tableView.indexPathForRow(at: molecule.center), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
|
||||
performTableViewUpdates()
|
||||
}
|
||||
}
|
||||
open func removeMolecules(at indexPaths: [IndexPath], animation: UITableView.RowAnimation?) {
|
||||
for (index, indexPath) in indexPaths.sorted().enumerated() {
|
||||
let removeIndex = indexPath.row - index
|
||||
moleculesInfo?.remove(at: removeIndex)
|
||||
}
|
||||
|
||||
open override func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||
//TODO: check for molecule protocol eqaulity
|
||||
let json = moleculeInfo.molecule.toJSON()
|
||||
return json == molecule.toJSON()
|
||||
}) else { return nil }
|
||||
guard let animation = animation,
|
||||
indexPaths.count > 0 else { return }
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
updateViewConstraints()
|
||||
view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation?) {
|
||||
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
|
||||
DispatchQueue.main.async {
|
||||
var indexPaths: [IndexPath] = []
|
||||
|
||||
return IndexPath(row: index, section: 0)
|
||||
}
|
||||
for molecule in molecules {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
open override func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
|
||||
DispatchQueue.main.async {
|
||||
var indexPaths: [IndexPath] = []
|
||||
guard let animation = animation,
|
||||
indexPaths.count > 0 else { return }
|
||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||
self.updateViewConstraints()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||
//TODO: check for molecule protocol eqaulity
|
||||
let json = moleculeInfo.molecule.toJSON()
|
||||
return json == molecule.toJSON()
|
||||
}) else { return nil }
|
||||
|
||||
return IndexPath(row: index, section: 0)
|
||||
}
|
||||
|
||||
for molecule in molecules {
|
||||
if let info = self.createMoleculeInfo(with: molecule) {
|
||||
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
||||
let index = indexPath.row + 1 + indexPaths.count
|
||||
self.moleculesInfo?.insert(info, at: index)
|
||||
indexPaths.append(IndexPath(row: index, section: 0))
|
||||
}
|
||||
}
|
||||
open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
|
||||
guard let tableView = tableView else { return }
|
||||
|
||||
guard indexPaths.count > 0 else { return }
|
||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||
self.updateViewConstraints()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
open func newData(for molecule: MoleculeModelProtocol) {
|
||||
//TODO: expand for header, navigation, etc
|
||||
let json = molecule.toJSON()
|
||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||
//TODO: check for molecule protocol eqaulity
|
||||
if json == moleculeInfo.molecule.toJSON() {
|
||||
return true
|
||||
} else if let parent = moleculeInfo.molecule as? ParentMoleculeModelProtocol {
|
||||
// Get all molecules of the same type for faster check.
|
||||
let molecules: [MoleculeModelProtocol] = parent.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, currentMolecule, depth) in
|
||||
if currentMolecule.moleculeName == molecule.moleculeName {
|
||||
return accumulator + [currentMolecule]
|
||||
}
|
||||
return accumulator
|
||||
}
|
||||
for molecule in molecules {
|
||||
if json == molecule.toJSON() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}) else { return }
|
||||
|
||||
// Refresh the cell. (reload loses cell selection)
|
||||
let selectedIndex = tableView.indexPathForSelectedRow
|
||||
let indexPath = IndexPath(row: index, section: 0)
|
||||
tableView.reloadRows(at: [indexPath], with: .automatic)
|
||||
if let selectedIndex = selectedIndex {
|
||||
tableView.selectRow(at: selectedIndex, animated: false, scrollPosition: .none)
|
||||
}
|
||||
}
|
||||
|
||||
open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {
|
||||
var indexPaths: [IndexPath] = []
|
||||
//TODO: check for molecule protocol equality
|
||||
|
||||
for molecule in molecules {
|
||||
if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
|
||||
moleculesInfo?.remove(at: removeIndex)
|
||||
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
|
||||
}
|
||||
}
|
||||
|
||||
guard indexPaths.count > 0 else { return }
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
updateViewConstraints()
|
||||
view.layoutIfNeeded()
|
||||
}
|
||||
let point = molecule.convert(molecule.bounds.origin, to: tableView)
|
||||
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
|
||||
performTableViewUpdates()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,25 +8,28 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum AddMoleculePosition {
|
||||
public enum AddMoleculesPosition {
|
||||
case above
|
||||
case below
|
||||
}
|
||||
|
||||
/// Protocol for adding items to a list
|
||||
public protocol AddMolecules {
|
||||
typealias AddParameters = ([ListItemModelProtocol & MoleculeModelProtocol], AddMoleculesPosition)
|
||||
|
||||
/// Get the molecules that need to be added, the position to add them to, and the animation to use
|
||||
func moleculesToAdd() -> ([ListItemModelProtocol & MoleculeModelProtocol], AddMoleculePosition, UITableView.RowAnimation?)?
|
||||
func moleculesToAdd() -> AddParameters?
|
||||
}
|
||||
|
||||
/// Protocol for removing items to a list
|
||||
public protocol RemoveMolecules {
|
||||
/// Get the molecules that need to be removed, and the animation to use
|
||||
func moleculesToRemove() -> ([ListItemModelProtocol & MoleculeModelProtocol], UITableView.RowAnimation?)?
|
||||
func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||
}
|
||||
|
||||
public extension AddMolecules {
|
||||
|
||||
/// Gets the molecules that need to be added, recursively checking for additional molecules to add.
|
||||
func getRecursiveMoleculesToAdd() -> ([ListItemModelProtocol & MoleculeModelProtocol], AddMoleculePosition, UITableView.RowAnimation?)? {
|
||||
/// Convenience function that gets the molecules that need to be added, recursively checking for additional molecules to add.
|
||||
func getRecursiveMoleculesToAdd() -> AddMolecules.AddParameters? {
|
||||
guard let moleculesToAdd = moleculesToAdd() else { return nil }
|
||||
var newMolecules: [ListItemModelProtocol & MoleculeModelProtocol] = []
|
||||
for molecule in moleculesToAdd.0 {
|
||||
@ -41,30 +44,30 @@ public extension AddMolecules {
|
||||
}
|
||||
newMolecules.append(molecule)
|
||||
}
|
||||
return (newMolecules, moleculesToAdd.1, moleculesToAdd.2)
|
||||
return (newMolecules, moleculesToAdd.1)
|
||||
}
|
||||
}
|
||||
|
||||
public extension RemoveMolecules {
|
||||
/// Gets the molecules that need to be removed, recursively checking for additional molecules to remove.
|
||||
func getRecursiveMoleculesToRemove() -> ([ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation?)? {
|
||||
/// Convenience function that gets the molecules that need to be removed, recursively checking for additional molecules to remove.
|
||||
func getRecursiveMoleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||
guard let moleculesToRemove = moleculesToRemove() else { return nil }
|
||||
var newMolecules: [ListItemModelProtocol & MoleculeModelProtocol] = moleculesToRemove.0
|
||||
for case let molecule as (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules) in moleculesToRemove.0 {
|
||||
var newMolecules: [ListItemModelProtocol & MoleculeModelProtocol] = moleculesToRemove
|
||||
for case let molecule as (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules) in moleculesToRemove {
|
||||
guard let moreMolecules = molecule.getRecursiveMoleculesToRemove() else { continue }
|
||||
newMolecules.append(contentsOf: moreMolecules.0)
|
||||
newMolecules.append(contentsOf: moreMolecules)
|
||||
}
|
||||
return (newMolecules, moleculesToRemove.1)
|
||||
return newMolecules
|
||||
}
|
||||
}
|
||||
|
||||
public class AddRemoveMoleculeBehaviorModel: PageBehaviorModelProtocol {
|
||||
public class AddRemoveMoleculesBehaviorModel: PageBehaviorModelProtocol {
|
||||
public class var identifier: String { "addRemoveListItemBehavior" }
|
||||
public var shouldAllowMultipleInstances: Bool { false }
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public class AddRemoveMoleculeBehavior: PageCustomActionHandlerBehavior {
|
||||
public class AddRemoveMoleculesBehavior: PageCustomActionHandlerBehavior, PageMoleculeTransformationBehavior {
|
||||
|
||||
var delegate: MVMCoreUIDelegateObject?
|
||||
|
||||
@ -72,22 +75,34 @@ public class AddRemoveMoleculeBehavior: PageCustomActionHandlerBehavior {
|
||||
self.delegate = delegateObject
|
||||
}
|
||||
|
||||
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) {
|
||||
guard let list = delegate?.moleculeListDelegate else { return }
|
||||
for case let model as (MoleculeModelProtocol & ListItemModelProtocol & AddMolecules) in rootMolecules {
|
||||
if let moleculesToAdd = model.getRecursiveMoleculesToAdd(),
|
||||
let indexPath = list.getAdjustedIndexPath(for: model, position: moleculesToAdd.1) {
|
||||
list.addMolecules(moleculesToAdd.0, indexPath: indexPath, animation: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func handleAction(type actionType: String?, information: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) -> Bool {
|
||||
if actionType == AddMoleculesActionModel.identifier {
|
||||
guard let list = delegate?.moleculeListDelegate,
|
||||
let model = additionalData?[KeySourceModel] as? (ListItemModelProtocol & MoleculeModelProtocol & AddMolecules),
|
||||
let moleculesToAdd = model.getRecursiveMoleculesToAdd(),
|
||||
let indexPath = list.getAdjustedIndexPath(for: model, position: moleculesToAdd.1) else { return true }
|
||||
let indexPath = list.getAdjustedIndexPath(for: model, position: moleculesToAdd.1),
|
||||
let animation = information?["animation"] as? Int else { return true }
|
||||
DispatchQueue.main.async {
|
||||
list.addMolecules(moleculesToAdd.0, indexPath: indexPath, animation: moleculesToAdd.2)
|
||||
list.addMolecules(moleculesToAdd.0, indexPath: indexPath, animation: UITableView.RowAnimation(rawValue: animation))
|
||||
}
|
||||
return true
|
||||
} else if actionType == RemoveMoleculesActionModel.identifier {
|
||||
guard let list = delegate?.moleculeListDelegate,
|
||||
let model = additionalData?[KeySourceModel] as? (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules),
|
||||
let moleculesToRemove = model.getRecursiveMoleculesToRemove() else { return true }
|
||||
let moleculesToRemove = model.getRecursiveMoleculesToRemove(),
|
||||
let animation = information?["animation"] as? Int else { return true }
|
||||
DispatchQueue.main.async {
|
||||
list.removeMolecules(moleculesToRemove.0, animation: moleculesToRemove.1)
|
||||
list.removeMolecules(moleculesToRemove, animation: UITableView.RowAnimation(rawValue: animation))
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -97,7 +112,7 @@ public class AddRemoveMoleculeBehavior: PageCustomActionHandlerBehavior {
|
||||
|
||||
private extension MoleculeListProtocol {
|
||||
/// Convenience function to get the index path adjusted for position.
|
||||
func getAdjustedIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol, position: AddMoleculePosition) -> IndexPath? {
|
||||
func getAdjustedIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol, position: AddMoleculesPosition) -> IndexPath? {
|
||||
guard let indexPath = getIndexPath(for: molecule) else { return nil }
|
||||
if position == .below {
|
||||
return IndexPath(row: indexPath.row + 1, section: indexPath.section)
|
||||
@ -109,6 +124,7 @@ private extension MoleculeListProtocol {
|
||||
public class AddMoleculesActionModel: ActionModelProtocol {
|
||||
public static var identifier: String = "addMoleculesAction"
|
||||
public var actionType: String = AddMoleculesActionModel.identifier
|
||||
public var animation: UITableView.RowAnimation = .automatic
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
@ -116,15 +132,26 @@ public class AddMoleculesActionModel: ActionModelProtocol {
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(_ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoveMoleculesActionModel: ActionModelProtocol {
|
||||
public static var identifier: String = "removeMoleculesAction"
|
||||
public var actionType: String = RemoveMoleculesActionModel.identifier
|
||||
public var animation: UITableView.RowAnimation = .automatic
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
@ -132,8 +159,18 @@ public class RemoveMoleculesActionModel: ActionModelProtocol {
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(_ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@ open class CoreUIModelMapping: ModelMapping {
|
||||
open class func registerBehaviors() {
|
||||
ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self)
|
||||
ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self)
|
||||
ModelRegistry.register(handler: AddRemoveMoleculeBehavior.self, for: AddRemoveMoleculeBehaviorModel.self)
|
||||
ModelRegistry.register(handler: AddRemoveMoleculesBehavior.self, for: AddRemoveMoleculesBehaviorModel.self)
|
||||
}
|
||||
|
||||
open override class func registerActions() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user