Added scrolling to new feed after a user adds it.

This commit is contained in:
Maurice Parker 2019-04-18 09:42:41 -05:00
parent b01b45cf9c
commit 929d7714ab
1 changed files with 65 additions and 29 deletions

View File

@ -43,7 +43,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(userDidAddFeed(_:)), name: .UserDidAddFeed, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
refreshControl = UIRefreshControl() refreshControl = UIRefreshControl()
@ -88,11 +88,11 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
} }
@objc func containerChildrenDidChange(_ note: Notification) { @objc func containerChildrenDidChange(_ note: Notification) {
rebuildTreeAndReloadDataIfNeeded() rebuildBackingStoresAndReloadDataIfNeeded()
} }
@objc func batchUpdateDidPerform(_ notification: Notification) { @objc func batchUpdateDidPerform(_ notification: Notification) {
rebuildTreeAndReloadDataIfNeeded() rebuildBackingStoresAndReloadDataIfNeeded()
} }
@objc func unreadCountDidChange(_ note: Notification) { @objc func unreadCountDidChange(_ note: Notification) {
@ -136,11 +136,36 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
return return
} }
rebuildTreeAndReloadDataIfNeeded() rebuildBackingStoresAndReloadDataIfNeeded()
configureCellsForRepresentedObject(object as AnyObject) configureCellsForRepresentedObject(object as AnyObject)
} }
@objc func userDidAddFeed(_ notification: Notification) {
guard let feed = notification.userInfo?[UserInfoKey.feed],
let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject) else {
return
}
if let indexPath = indexPathFor(node) {
tableView.scrollToRow(at: indexPath, at: .middle, animated: true)
return
}
// It wasn't already visable, so expand its folder and try again
guard let parent = node.parent, let indexPath = indexPathFor(parent) else {
return
}
expand(indexPath)
if let indexPath = indexPathFor(node) {
tableView.scrollToRow(at: indexPath, at: .middle, animated: true)
}
}
// MARK: Table View // MARK: Table View
override func numberOfSections(in tableView: UITableView) -> Int { override func numberOfSections(in tableView: UITableView) -> Int {
@ -172,7 +197,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MasterTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MasterTableViewCell
guard let node = nodeFor(indexPath: indexPath) else { guard let node = nodeFor(indexPath) else {
return cell return cell
} }
@ -182,7 +207,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
} }
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
guard let node = nodeFor(indexPath: indexPath), !(node.representedObject is PseudoFeed) else { guard let node = nodeFor(indexPath), !(node.representedObject is PseudoFeed) else {
return false return false
} }
return true return true
@ -214,7 +239,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let node = nodeFor(indexPath: indexPath) else { guard let node = nodeFor(indexPath) else {
assertionFailure() assertionFailure()
return return
} }
@ -381,7 +406,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
func delete(indexPath: IndexPath) { func delete(indexPath: IndexPath) {
guard let undoManager = undoManager, guard let undoManager = undoManager,
let deleteNode = nodeFor(indexPath: indexPath), let deleteNode = nodeFor(indexPath),
let deleteCommand = DeleteCommand(nodesToDelete: [deleteNode], treeController: treeController, undoManager: undoManager) let deleteCommand = DeleteCommand(nodesToDelete: [deleteNode], treeController: treeController, undoManager: undoManager)
else { else {
return return
@ -399,7 +424,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
func rename(indexPath: IndexPath) { func rename(indexPath: IndexPath) {
let name = (nodeFor(indexPath: indexPath)?.representedObject as? DisplayNameProvider)?.nameForDisplay ?? "" let name = (nodeFor(indexPath)?.representedObject as? DisplayNameProvider)?.nameForDisplay ?? ""
let formatString = NSLocalizedString("Rename “%@”", comment: "Feed finder") let formatString = NSLocalizedString("Rename “%@”", comment: "Feed finder")
let title = NSString.localizedStringWithFormat(formatString as NSString, name) as String let title = NSString.localizedStringWithFormat(formatString as NSString, name) as String
@ -411,7 +436,7 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
let renameTitle = NSLocalizedString("Rename", comment: "Rename") let renameTitle = NSLocalizedString("Rename", comment: "Rename")
let renameAction = UIAlertAction(title: renameTitle, style: .default) { [weak self] action in let renameAction = UIAlertAction(title: renameTitle, style: .default) { [weak self] action in
guard let node = self?.nodeFor(indexPath: indexPath), guard let node = self?.nodeFor(indexPath),
let name = alertController.textFields?[0].text, let name = alertController.textFields?[0].text,
!name.isEmpty else { !name.isEmpty else {
return return
@ -437,10 +462,19 @@ class MasterViewController: UITableViewController, UndoableCommandRunner {
} }
func nodeFor(indexPath: IndexPath) -> Node? { func nodeFor(_ indexPath: IndexPath) -> Node? {
return shadowTable[indexPath.section][indexPath.row] return shadowTable[indexPath.section][indexPath.row]
} }
func indexPathFor(_ node: Node) -> IndexPath? {
for i in 0..<shadowTable.count {
if let row = shadowTable[i].firstIndex(of: node) {
return IndexPath(row: row, section: i)
}
}
return nil
}
} }
// MARK: OPML Document Picker // MARK: OPML Document Picker
@ -467,9 +501,9 @@ extension MasterViewController: MasterTableViewCellDelegate {
func disclosureSelected(_ sender: MasterTableViewCell, expanding: Bool) { func disclosureSelected(_ sender: MasterTableViewCell, expanding: Bool) {
if expanding { if expanding {
expandCell(sender) expand(sender)
} else { } else {
collapseCell(sender) collapse(sender)
} }
} }
@ -479,9 +513,10 @@ extension MasterViewController: MasterTableViewCellDelegate {
private extension MasterViewController { private extension MasterViewController {
func rebuildTreeAndReloadDataIfNeeded() { func rebuildBackingStoresAndReloadDataIfNeeded() {
if !animatingChanges && !BatchUpdate.shared.isPerforming { if !animatingChanges && !BatchUpdate.shared.isPerforming {
rebuildBackingStructures() treeController.rebuild()
rebuildShadowTable()
tableView.reloadData() tableView.reloadData()
} }
} }
@ -505,18 +540,13 @@ private extension MasterViewController {
func applyToAvailableCells(_ callback: (MasterTableViewCell, Node) -> Void) { func applyToAvailableCells(_ callback: (MasterTableViewCell, Node) -> Void) {
tableView.visibleCells.forEach { cell in tableView.visibleCells.forEach { cell in
guard let indexPath = tableView.indexPath(for: cell), let node = nodeFor(indexPath: indexPath) else { guard let indexPath = tableView.indexPath(for: cell), let node = nodeFor(indexPath) else {
return return
} }
callback(cell as! MasterTableViewCell, node) callback(cell as! MasterTableViewCell, node)
} }
} }
func rebuildBackingStructures() {
treeController.rebuild()
rebuildShadowTable()
}
func rebuildShadowTable() { func rebuildShadowTable() {
for i in 0..<treeController.rootNode.numberOfChildNodes { for i in 0..<treeController.rootNode.numberOfChildNodes {
@ -540,13 +570,16 @@ private extension MasterViewController {
} }
func expandCell(_ cell: MasterTableViewCell) { func expand(_ cell: MasterTableViewCell) {
animatingChanges = true
guard let indexPath = tableView.indexPath(for: cell) else { guard let indexPath = tableView.indexPath(for: cell) else {
return return
} }
expand(indexPath)
}
func expand(_ indexPath: IndexPath) {
animatingChanges = true
let expandNode = shadowTable[indexPath.section][indexPath.row] let expandNode = shadowTable[indexPath.section][indexPath.row]
expandedNodes.append(expandNode) expandedNodes.append(expandNode)
@ -568,13 +601,16 @@ private extension MasterViewController {
} }
func collapseCell(_ cell: MasterTableViewCell) { func collapse(_ cell: MasterTableViewCell) {
animatingChanges = true
guard let indexPath = tableView.indexPath(for: cell) else { guard let indexPath = tableView.indexPath(for: cell) else {
return return
} }
collapse(indexPath)
}
func collapse(_ indexPath: IndexPath) {
animatingChanges = true
let collapseNode = shadowTable[indexPath.section][indexPath.row] let collapseNode = shadowTable[indexPath.section][indexPath.row]
if let removeNode = expandedNodes.firstIndex(of: collapseNode) { if let removeNode = expandedNodes.firstIndex(of: collapseNode) {