// // MasterFeedDataSource.swift // NetNewsWire-iOS // // Created by Maurice Parker on 8/28/19. // Copyright © 2019 Ranchero Software. All rights reserved. // import UIKit import RSCore import RSTree import Account class MasterFeedDataSource: UITableViewDiffableDataSource where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable { private var coordinator: AppCoordinator! private var errorHandler: ((Error) -> ())! init(coordinator: AppCoordinator, errorHandler: @escaping (Error) -> (), tableView: UITableView, cellProvider: @escaping UITableViewDiffableDataSource.CellProvider) { super.init(tableView: tableView, cellProvider: cellProvider) self.coordinator = coordinator self.errorHandler = errorHandler } override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { guard let node = coordinator.nodeFor(indexPath), !(node.representedObject is PseudoFeed) else { return false } return true } override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { guard let node = coordinator.nodeFor(indexPath) else { return false } return node.representedObject is Feed } override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { guard let sourceNode = coordinator.nodeFor(sourceIndexPath), let feed = sourceNode.representedObject as? Feed else { return } // Based on the drop we have to determine a node to start looking for a parent container. let destNode: Node = { if destinationIndexPath.row == 0 { return coordinator.rootNode.childAtIndex(destinationIndexPath.section)! } else { let movementAdjustment = sourceIndexPath > destinationIndexPath ? 1 : 0 let adjustedDestIndexPath = IndexPath(row: destinationIndexPath.row - movementAdjustment, section: destinationIndexPath.section) return coordinator.nodeFor(adjustedDestIndexPath)! } }() // Now we start looking for the parent container let destParentNode: Node? = { if destNode.representedObject is Container { return destNode } else { if destNode.parent?.representedObject is Container { return destNode.parent! } else { return nil } } }() // Move the Feed guard let source = sourceNode.parent?.representedObject as? Container, let destination = destParentNode?.representedObject as? Container else { return } BatchUpdate.shared.start() source.account?.moveFeed(feed, from: source, to: destination) { result in switch result { case .success: BatchUpdate.shared.end() case .failure(let error): self.errorHandler(error) } } } }