From 3245223b24d650528dc78976d36380f8782bac67 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 19 Aug 2019 15:45:52 -0500 Subject: [PATCH] Add Select Feed context menu --- iOS/AppAssets.swift | 8 +++ iOS/AppCoordinator.swift | 5 ++ iOS/MasterFeed/MasterFeedViewController.swift | 67 ++++++++++++------- .../MasterTimelineViewController.swift | 36 +++++++++- 4 files changed, 89 insertions(+), 27 deletions(-) diff --git a/iOS/AppAssets.swift b/iOS/AppAssets.swift index 08b3a814f..dc4e68dbe 100644 --- a/iOS/AppAssets.swift +++ b/iOS/AppAssets.swift @@ -64,10 +64,18 @@ struct AppAssets { return UIImage(systemName: "folder.fill")! }() + static var moreImage: UIImage = { + return UIImage(systemName: "ellipsis.circle")! + }() + static var netNewsWireBlueColor: UIColor = { return UIColor(named: "netNewsWireBlueColor")! }() + static var openInSidebarImage: UIImage = { + return UIImage(systemName: "arrow.turn.down.left")! + }() + static var safariImage: UIImage = { return UIImage(systemName: "safari")! }() diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 544e0e156..d0c3dcd31 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -567,6 +567,11 @@ class AppCoordinator: NSObject, UndoableCommandRunner { } } + func discloseFeed(_ feed: Feed) { + masterNavigationController.popViewController(animated: true) + masterFeedViewController.discloseFeed(feed) + } + func showSettings() { let settingsNavViewController = UIStoryboard.settings.instantiateInitialViewController() as! UINavigationController settingsNavViewController.modalPresentationStyle = .formSheet diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 6eb954082..99720237c 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -121,32 +121,10 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } @objc func userDidAddFeed(_ notification: Notification) { - - guard let feed = notification.userInfo?[UserInfoKey.feed], - let node = coordinator.rootNode.descendantNodeRepresentingObject(feed as AnyObject) else { - return - } - - if let indexPath = coordinator.indexPathFor(node) { - tableView.scrollToRow(at: indexPath, at: .middle, animated: true) + guard let feed = notification.userInfo?[UserInfoKey.feed] as? Feed else { return } - - // It wasn't already visable, so expand its folder and try again - guard let parent = node.parent, let indexPath = coordinator.indexPathFor(parent) else { - return - } - - coordinator.expand(indexPath) { [weak self] indexPaths in - self?.tableView.beginUpdates() - self?.tableView.insertRows(at: indexPaths, with: .automatic) - self?.tableView.endUpdates() - } - - if let indexPath = coordinator.indexPathFor(node) { - tableView.scrollToRow(at: indexPath, at: .middle, animated: true) - } - + discloseFeed(feed) } @objc func accountsDidChange(_ notification: Notification) { @@ -510,6 +488,39 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { AccountManager.shared.refreshAll(errorHandler: ErrorHandler.present(self)) } } + + // MARK: API + + func discloseFeed(_ feed: Feed) { + + guard let node = coordinator.rootNode.descendantNodeRepresentingObject(feed as AnyObject) else { + return + } + + if let indexPath = coordinator.indexPathFor(node) { + tableView.scrollToRow(at: indexPath, at: .middle, animated: true) + coordinator.selectFeed(indexPath) + return + } + + // It wasn't already visable, so expand its folder and try again + guard let parent = node.parent, let indexPath = coordinator.indexPathFor(parent) else { + return + } + + coordinator.expand(indexPath) { [weak self] indexPaths in + self?.tableView.beginUpdates() + tableView.reloadRows(at: [indexPath], with: .automatic) + self?.tableView.insertRows(at: indexPaths, with: .automatic) + self?.tableView.endUpdates() + } + + if let indexPath = coordinator.indexPathFor(node) { + tableView.scrollToRow(at: indexPath, at: .middle, animated: true) + coordinator.selectFeed(indexPath) + } + + } } @@ -644,7 +655,9 @@ private extension MasterFeedViewController { } func makeFeedContextMenu(indexPath: IndexPath, includeDeleteRename: Bool) -> UIContextMenuConfiguration { - return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { suggestedActions in + return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { [ weak self] suggestedActions in + + guard let self = self else { return nil } var actions = [UIAction]() @@ -673,8 +686,10 @@ private extension MasterFeedViewController { } func makeFolderContextMenu(indexPath: IndexPath) -> UIContextMenuConfiguration { - return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { suggestedActions in + return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { [weak self] suggestedActions in + guard let self = self else { return nil } + var actions = [UIAction]() actions.append(self.deleteAction(indexPath: indexPath)) actions.append(self.renameAction(indexPath: indexPath)) diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index f67d76f5a..5d4d6ef30 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -164,6 +164,10 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner alert.addAction(self.markOlderAsReadAlertAction(indexPath: indexPath, completionHandler: completionHandler)) + if let action = self.discloseFeedAlertAction(indexPath: indexPath, completionHandler: completionHandler) { + alert.addAction(action) + } + let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel") alert.addAction(UIAlertAction(title: cancelTitle, style: .cancel) { _ in completionHandler(true) @@ -175,6 +179,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner } + moreAction.image = AppAssets.moreImage moreAction.backgroundColor = UIColor.systemGray let configuration = UISwipeActionsConfiguration(actions: [readAction, starAction, moreAction]) @@ -184,13 +189,19 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { - return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { suggestedActions in + return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { [weak self] suggestedActions in + guard let self = self else { return nil } + var actions = [UIAction]() actions.append(self.toggleArticleReadStatusAction(indexPath: indexPath)) actions.append(self.toggleArticleStarStatusAction(indexPath: indexPath)) actions.append(self.markOlderAsReadAction(indexPath: indexPath)) + if let action = self.discloseFeedAction(indexPath: indexPath) { + actions.append(action) + } + let title = NSLocalizedString("Timeline Menu", comment: "Timeline Menu") return UIMenu(title: title, children: actions) @@ -559,4 +570,27 @@ private extension MasterTimelineViewController { return action } + func discloseFeedAction(indexPath: IndexPath) -> UIAction? { + guard let feed = coordinator.articles[indexPath.row].feed else { + return nil + } + let title = NSLocalizedString("Select Feed", comment: "Select Feed") + let action = UIAction(title: title, image: AppAssets.openInSidebarImage) { [weak self] action in + self?.coordinator.discloseFeed(feed) + } + return action + } + + func discloseFeedAlertAction(indexPath: IndexPath, completionHandler: @escaping (Bool) -> Void) -> UIAlertAction? { + guard let feed = coordinator.articles[indexPath.row].feed else { + return nil + } + let title = NSLocalizedString("Select Feed", comment: "Select Feed") + let action = UIAlertAction(title: title, style: .default) { [weak self] action in + self?.coordinator.discloseFeed(feed) + completionHandler(true) + } + return action + } + }