From 5cbfe3b071420085b35479b364e53b6f83def776 Mon Sep 17 00:00:00 2001 From: Martin Hartl Date: Mon, 30 Dec 2019 09:33:06 +0100 Subject: [PATCH] Include Mark All as Read in Feeds list context menu --- iOS/MasterFeed/MasterFeedViewController.swift | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 2b35586fe..9dce15c03 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -301,13 +301,17 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { - guard let node = dataSource.itemIdentifier(for: indexPath), !(node.representedObject is PseudoFeed) else { + guard let node = dataSource.itemIdentifier(for: indexPath) else { return nil } if node.representedObject is WebFeed { return makeFeedContextMenu(node: node, indexPath: indexPath, includeDeleteRename: true) - } else { + } else if node.representedObject is Folder { return makeFolderContextMenu(node: node, indexPath: indexPath) + } else if node.representedObject is PseudoFeed { + return makePseudoFeedContextMenu(node: node, indexPath: indexPath) + } else { + return nil } } @@ -618,7 +622,14 @@ extension MasterFeedViewController: UIContextMenuInteractionDelegate { return UIContextMenuConfiguration(identifier: sectionIndex as NSCopying, previewProvider: nil) { suggestedActions in let accountInfoAction = self.getAccountInfoAction(account: account) let deactivateAction = self.deactivateAccountAction(account: account) - return UIMenu(title: "", children: [accountInfoAction, deactivateAction]) + + var actions = [accountInfoAction, deactivateAction] + + if let markAllAction = self.markAllAsReadAction(account: account) { + actions.insert(markAllAction, at: 1) + } + + return UIMenu(title: "", children: actions) } } @@ -870,6 +881,10 @@ private extension MasterFeedViewController { actions.append(self.deleteAction(indexPath: indexPath)) actions.append(self.renameAction(indexPath: indexPath)) } + + if let markAllAction = self.markAllAsReadAction(indexPath: indexPath) { + actions.append(markAllAction) + } return UIMenu(title: "", children: actions) @@ -885,12 +900,26 @@ private extension MasterFeedViewController { var actions = [UIAction]() actions.append(self.deleteAction(indexPath: indexPath)) actions.append(self.renameAction(indexPath: indexPath)) + + if let markAllAction = self.markAllAsReadAction(indexPath: indexPath) { + actions.append(markAllAction) + } return UIMenu(title: "", children: actions) }) } + func makePseudoFeedContextMenu(node: Node, indexPath: IndexPath) -> UIContextMenuConfiguration? { + guard let markAllAction = self.markAllAsReadAction(indexPath: indexPath) else { + return nil + } + + return UIContextMenuConfiguration(identifier: node.uniqueID as NSCopying, previewProvider: nil, actionProvider: { suggestedActions in + return UIMenu(title: "", children: [markAllAction]) + }) + } + func homePageAction(indexPath: IndexPath) -> UIAction? { guard coordinator.homePageURLForFeed(indexPath) != nil else { return nil @@ -1033,6 +1062,45 @@ private extension MasterFeedViewController { } return action } + + func markAllAsReadAction(indexPath: IndexPath) -> UIAction? { + guard let node = dataSource.itemIdentifier(for: indexPath), + coordinator.unreadCountFor(node) > 0 else { + return nil + } + + guard let articleFetcher = node.representedObject as? Feed, + let fetchedArticles = try? articleFetcher.fetchArticles() else { + return nil + } + + let articles = Array(fetchedArticles) + return markAllAsReadAction(articles: articles, nameForDisplay: articleFetcher.nameForDisplay) + } + + func markAllAsReadAction(account: Account) -> UIAction? { + guard let fetchedArticles = try? account.fetchArticles(FetchType.unread) else { + return nil + } + + let articles = Array(fetchedArticles) + return markAllAsReadAction(articles: articles, nameForDisplay: account.nameForDisplay) + } + + func markAllAsReadAction(articles: [Article], nameForDisplay: String) -> UIAction? { + guard articles.canMarkAllAsRead() else { + return nil + } + + let localizedMenuText = NSLocalizedString("Mark All as Read in “%@”", comment: "Command") + let title = NSString.localizedStringWithFormat(localizedMenuText as NSString, nameForDisplay) as String + + let action = UIAction(title: title, image: AppAssets.markAllInFeedAsReadImage) { [weak self] action in + self?.coordinator.markAllAsRead(articles) + } + + return action + } func rename(indexPath: IndexPath) {