diff --git a/Account/Sources/Account/AccountManager.swift b/Account/Sources/Account/AccountManager.swift index 351a3479e..2decbd3f4 100644 --- a/Account/Sources/Account/AccountManager.swift +++ b/Account/Sources/Account/AccountManager.swift @@ -197,7 +197,7 @@ public final class AccountManager: UnreadCountProvider { return nil } - public func existingFeed(with feedID: FeedIdentifier) -> Feed? { + public func existingFeed(with feedID: FeedIdentifier) -> SidebarItem? { switch feedID { case .folder(let accountID, let folderName): if let account = existingAccount(with: accountID) { diff --git a/Account/Sources/Account/Folder.swift b/Account/Sources/Account/Folder.swift index 1cff74267..5d98c671f 100644 --- a/Account/Sources/Account/Folder.swift +++ b/Account/Sources/Account/Folder.swift @@ -10,7 +10,7 @@ import Foundation import Articles import RSCore -public final class Folder: Feed, Renamable, Container, Hashable { +public final class Folder: SidebarItem, Renamable, Container, Hashable { public var defaultReadFilterType: ReadFilterType { return .read diff --git a/Account/Sources/Account/Feed.swift b/Account/Sources/Account/SidebarItem.swift similarity index 80% rename from Account/Sources/Account/Feed.swift rename to Account/Sources/Account/SidebarItem.swift index 23d842f0a..fa476d2cf 100644 --- a/Account/Sources/Account/Feed.swift +++ b/Account/Sources/Account/SidebarItem.swift @@ -1,5 +1,5 @@ // -// Feed.swift +// SidebarItem.swift // Account // // Created by Maurice Parker on 11/15/19. @@ -15,14 +15,14 @@ public enum ReadFilterType { case alwaysRead } -public protocol Feed: FeedIdentifiable, ArticleFetcher, DisplayNameProvider, UnreadCountProvider { +public protocol SidebarItem: FeedIdentifiable, ArticleFetcher, DisplayNameProvider, UnreadCountProvider { var account: Account? { get } var defaultReadFilterType: ReadFilterType { get } } -public extension Feed { +public extension SidebarItem { func readFiltered(readFilterEnabledTable: [FeedIdentifier: Bool]) -> Bool { guard defaultReadFilterType != .alwaysRead else { diff --git a/Account/Sources/Account/WebFeed.swift b/Account/Sources/Account/WebFeed.swift index 119010291..b19166ade 100644 --- a/Account/Sources/Account/WebFeed.swift +++ b/Account/Sources/Account/WebFeed.swift @@ -11,7 +11,7 @@ import RSCore import RSWeb import Articles -public final class WebFeed: Feed, Renamable, Hashable { +public final class WebFeed: SidebarItem, Renamable, Hashable { public var defaultReadFilterType: ReadFilterType { return .none diff --git a/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift b/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift index 899c29cf1..96d325044 100644 --- a/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift +++ b/Mac/MainWindow/Sidebar/SidebarDeleteItemsAlert.swift @@ -22,7 +22,7 @@ enum SidebarDeleteItemsAlert { alert.messageText = NSLocalizedString("Delete Folder", comment: "Delete Folder") let localizedInformativeText = NSLocalizedString("Are you sure you want to delete the “%@” folder?", comment: "Folder delete text") alert.informativeText = NSString.localizedStringWithFormat(localizedInformativeText as NSString, folder.nameForDisplay) as String - } else if let feed = nodes.first?.representedObject as? Feed { + } else if let feed = nodes.first?.representedObject as? SidebarItem { alert.messageText = NSLocalizedString("Delete Feed", comment: "Delete Feed") let localizedInformativeText = NSLocalizedString("Are you sure you want to delete the “%@” feed?", comment: "Feed delete text") alert.informativeText = NSString.localizedStringWithFormat(localizedInformativeText as NSString, feed.nameForDisplay) as String diff --git a/Mac/MainWindow/Sidebar/SidebarViewController.swift b/Mac/MainWindow/Sidebar/SidebarViewController.swift index 26077cae8..68bc03474 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController.swift @@ -447,7 +447,7 @@ protocol SidebarDelegate: AnyObject { // MARK: - API - func selectFeed(_ feed: Feed) { + func selectFeed(_ feed: SidebarItem) { if isReadFiltered, let feedID = feed.feedID { self.treeControllerDelegate.addFilterException(feedID) @@ -468,7 +468,7 @@ protocol SidebarDelegate: AnyObject { func deepLinkRevealAndSelect(for userInfo: [AnyHashable : Any]) { guard let accountNode = findAccountNode(userInfo), let feedNode = findFeedNode(userInfo, beginningAt: accountNode), - let feed = feedNode.representedObject as? Feed else { + let feed = feedNode.representedObject as? SidebarItem else { return } selectFeed(feed) @@ -513,8 +513,8 @@ private extension SidebarViewController { return [Node]() } - var selectedFeeds: [Feed] { - selectedNodes.compactMap { $0.representedObject as? Feed } + var selectedFeeds: [SidebarItem] { + selectedNodes.compactMap { $0.representedObject as? SidebarItem } } var singleSelectedNode: Node? { @@ -535,7 +535,7 @@ private extension SidebarViewController { selectedFeeds.forEach { addToFilterExeptionsIfNecessary($0) } } - func addToFilterExeptionsIfNecessary(_ feed: Feed?) { + func addToFilterExeptionsIfNecessary(_ feed: SidebarItem?) { if isReadFiltered, let feedID = feed?.feedID { if feed is PseudoFeed { treeControllerDelegate.addFilterException(feedID) @@ -552,7 +552,7 @@ private extension SidebarViewController { } } - func addParentFolderToFilterExceptions(_ feed: Feed) { + func addParentFolderToFilterExceptions(_ feed: SidebarItem) { guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject), let folder = node.parent?.representedObject as? Folder, let folderFeedID = folder.feedID else { @@ -613,7 +613,7 @@ private extension SidebarViewController { } func addTreeControllerToFilterExceptionsVisitor(node: Node) { - if let feed = node.representedObject as? Feed, let feedID = feed.feedID { + if let feed = node.representedObject as? SidebarItem, let feedID = feed.feedID { treeControllerDelegate.addFilterException(feedID) } } diff --git a/Mac/MainWindow/Timeline/TimelineViewController.swift b/Mac/MainWindow/Timeline/TimelineViewController.swift index 1467649e4..a7f76502a 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController.swift @@ -30,7 +30,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr private var readFilterEnabledTable = [FeedIdentifier: Bool]() var isReadFiltered: Bool? { - guard representedObjects?.count == 1, let timelineFeed = representedObjects?.first as? Feed else { + guard representedObjects?.count == 1, let timelineFeed = representedObjects?.first as? SidebarItem else { return nil } guard timelineFeed.defaultReadFilterType != .alwaysRead else { @@ -46,7 +46,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr var isCleanUpAvailable: Bool { let isEligibleForCleanUp: Bool? - if representedObjects?.count == 1, let timelineFeed = representedObjects?.first as? Feed, timelineFeed.defaultReadFilterType == .alwaysRead { + if representedObjects?.count == 1, let timelineFeed = representedObjects?.first as? SidebarItem, timelineFeed.defaultReadFilterType == .alwaysRead { isEligibleForCleanUp = true } else { isEligibleForCleanUp = isReadFiltered @@ -263,7 +263,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } func toggleReadFilter() { - guard let filter = isReadFiltered, let feedID = (representedObjects?.first as? Feed)?.feedID else { return } + guard let filter = isReadFiltered, let feedID = (representedObjects?.first as? SidebarItem)?.feedID else { return } readFilterEnabledTable[feedID] = !filter delegate?.timelineInvalidatedRestorationState(self) fetchAndReplacePreservingSelection() @@ -1151,7 +1151,7 @@ private extension TimelineViewController { var fetchedArticles = Set
() for fetchers in fetchers { - if (fetchers as? Feed)?.readFiltered(readFilterEnabledTable: readFilterEnabledTable) ?? true { + if (fetchers as? SidebarItem)?.readFiltered(readFilterEnabledTable: readFilterEnabledTable) ?? true { if let articles = try? fetchers.fetchUnreadArticles() { fetchedArticles.formUnion(articles) } diff --git a/Shared/Activity/ActivityManager.swift b/Shared/Activity/ActivityManager.swift index c1f685b4e..a428506af 100644 --- a/Shared/Activity/ActivityManager.swift +++ b/Shared/Activity/ActivityManager.swift @@ -49,7 +49,7 @@ class ActivityManager { invalidateNextUnread() } - func selecting(feed: Feed) { + func selecting(feed: SidebarItem) { invalidateCurrentActivities() selectingActivity = makeSelectFeedActivity(feed: feed) @@ -87,7 +87,7 @@ class ActivityManager { nextUnreadActivity = nil } - func reading(feed: Feed?, article: Article?) { + func reading(feed: SidebarItem?, article: Article?) { invalidateReading() invalidateNextUnread() @@ -162,7 +162,7 @@ class ActivityManager { private extension ActivityManager { - func makeSelectFeedActivity(feed: Feed) -> NSUserActivity { + func makeSelectFeedActivity(feed: SidebarItem) -> NSUserActivity { let activity = NSUserActivity(activityType: ActivityType.selectFeed.rawValue) let localizedText = NSLocalizedString("See articles in “%@”", comment: "See articles in Folder") @@ -187,7 +187,7 @@ private extension ActivityManager { return activity } - func makeReadArticleActivity(feed: Feed?, article: Article) -> NSUserActivity { + func makeReadArticleActivity(feed: SidebarItem?, article: Article) -> NSUserActivity { let activity = NSUserActivity(activityType: ActivityType.readArticle.rawValue) activity.title = ArticleStringFormatter.truncatedTitle(article) diff --git a/Shared/IconImageCache.swift b/Shared/IconImageCache.swift index 1a7bc1826..2086e34c1 100644 --- a/Shared/IconImageCache.swift +++ b/Shared/IconImageCache.swift @@ -30,7 +30,7 @@ class IconImageCache { return nil } - func imageForFeed(_ feed: Feed) -> IconImage? { + func imageForFeed(_ feed: SidebarItem) -> IconImage? { guard let feedID = feed.feedID else { return nil } diff --git a/Shared/SmartFeeds/PseudoFeed.swift b/Shared/SmartFeeds/PseudoFeed.swift index 2d49603f2..94436c66b 100644 --- a/Shared/SmartFeeds/PseudoFeed.swift +++ b/Shared/SmartFeeds/PseudoFeed.swift @@ -13,7 +13,7 @@ import Articles import Account import RSCore -protocol PseudoFeed: AnyObject, Feed, SmallIconProvider, PasteboardWriterOwner { +protocol PseudoFeed: AnyObject, SidebarItem, SmallIconProvider, PasteboardWriterOwner { } @@ -24,7 +24,7 @@ import Articles import Account import RSCore -protocol PseudoFeed: AnyObject, Feed, SmallIconProvider { +protocol PseudoFeed: AnyObject, SidebarItem, SmallIconProvider { } diff --git a/Shared/SmartFeeds/SmartFeedsController.swift b/Shared/SmartFeeds/SmartFeedsController.swift index 75288e496..0fcf2541c 100644 --- a/Shared/SmartFeeds/SmartFeedsController.swift +++ b/Shared/SmartFeeds/SmartFeedsController.swift @@ -19,7 +19,7 @@ final class SmartFeedsController: DisplayNameProvider, ContainerIdentifiable { public static let shared = SmartFeedsController() let nameForDisplay = NSLocalizedString("Smart Feeds", comment: "Smart Feeds group title") - var smartFeeds = [Feed]() + var smartFeeds = [SidebarItem]() let todayFeed = SmartFeed(delegate: TodayFeedDelegate()) let unreadFeed = UnreadFeed() let starredFeed = SmartFeed(delegate: StarredFeedDelegate()) diff --git a/Shared/Timeline/FetchRequestOperation.swift b/Shared/Timeline/FetchRequestOperation.swift index 74ba5d098..054ff961c 100644 --- a/Shared/Timeline/FetchRequestOperation.swift +++ b/Shared/Timeline/FetchRequestOperation.swift @@ -81,7 +81,7 @@ final class FetchRequestOperation { } for fetcher in fetchers { - if (fetcher as? Feed)?.readFiltered(readFilterEnabledTable: readFilterEnabledTable) ?? true { + if (fetcher as? SidebarItem)?.readFiltered(readFilterEnabledTable: readFilterEnabledTable) ?? true { fetcher.fetchUnreadArticlesAsync { articleSetResult in let articles = (try? articleSetResult.get()) ?? Set
() process(articles) diff --git a/iOS/MasterFeed/MasterFeedViewController+Drop.swift b/iOS/MasterFeed/MasterFeedViewController+Drop.swift index c7f925c07..a3551fb2f 100644 --- a/iOS/MasterFeed/MasterFeedViewController+Drop.swift +++ b/iOS/MasterFeed/MasterFeedViewController+Drop.swift @@ -22,7 +22,7 @@ extension MasterFeedViewController: UITableViewDropDelegate { return UITableViewDropProposal(operation: .forbidden) } - guard let destFeed = coordinator.nodeFor(destIndexPath)?.representedObject as? Feed, + guard let destFeed = coordinator.nodeFor(destIndexPath)?.representedObject as? SidebarItem, let destAccount = destFeed.account, let destCell = tableView.cellForRow(at: destIndexPath) else { return UITableViewDropProposal(operation: .forbidden) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index c458d3cae..2ec52d7ce 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -320,7 +320,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { - guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? Feed else { + guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? SidebarItem else { return nil } if feed is WebFeed { @@ -781,7 +781,7 @@ private extension MasterFeedViewController { cell.isDisclosureAvailable = false } - if let feed = node.representedObject as? Feed { + if let feed = node.representedObject as? SidebarItem { cell.name = feed.nameForDisplay cell.unreadCount = feed.unreadCount } @@ -798,7 +798,7 @@ private extension MasterFeedViewController { } func configureIcon(_ cell: MasterFeedTableViewCell, _ indexPath: IndexPath) { - guard let node = coordinator.nodeFor(indexPath), let feed = node.representedObject as? Feed, let feedID = feed.feedID else { + guard let node = coordinator.nodeFor(indexPath), let feed = node.representedObject as? SidebarItem, let feedID = feed.feedID else { return } cell.iconImage = IconImageCache.shared.imageFor(feedID) @@ -818,8 +818,8 @@ private extension MasterFeedViewController { func applyToCellsForRepresentedObject(_ representedObject: AnyObject, _ completion: (MasterFeedTableViewCell, IndexPath) -> Void) { applyToAvailableCells { (cell, indexPath) in if let node = coordinator.nodeFor(indexPath), - let representedFeed = representedObject as? Feed, - let candidate = node.representedObject as? Feed, + let representedFeed = representedObject as? SidebarItem, + let candidate = node.representedObject as? SidebarItem, representedFeed.feedID == candidate.feedID { completion(cell, indexPath) } @@ -1123,7 +1123,7 @@ private extension MasterFeedViewController { } func markAllAsReadAction(indexPath: IndexPath) -> UIAction? { - guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? Feed, + guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? SidebarItem, let contentView = self.tableView.cellForRow(at: indexPath)?.contentView, feed.unreadCount > 0 else { return nil @@ -1165,7 +1165,7 @@ private extension MasterFeedViewController { func rename(indexPath: IndexPath) { - guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? Feed else { return } + guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? SidebarItem else { return } let formatString = NSLocalizedString("Rename “%@”", comment: "Rename feed") let title = NSString.localizedStringWithFormat(formatString as NSString, feed.nameForDisplay) as String @@ -1219,7 +1219,7 @@ private extension MasterFeedViewController { } func delete(indexPath: IndexPath) { - guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? Feed else { return } + guard let feed = coordinator.nodeFor(indexPath)?.representedObject as? SidebarItem else { return } let title: String let message: String diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 0649bd2c8..9b8ff1e85 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -37,7 +37,7 @@ struct FeedNode: Hashable { init(_ node: Node) { self.node = node - self.feedID = (node.representedObject as! Feed).feedID! + self.feedID = (node.representedObject as! SidebarItem).feedID! } func hash(into hasher: inout Hasher) { @@ -91,7 +91,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { private var readFilterEnabledTable = [FeedIdentifier: Bool]() private var shadowTable = [(sectionID: String, feedNodes: [FeedNode])]() - private(set) var preSearchTimelineFeed: Feed? + private(set) var preSearchTimelineFeed: SidebarItem? private var lastSearchString = "" private var lastSearchScope: SearchScope? = nil private var isSearching: Bool = false @@ -175,7 +175,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { } private var exceptionArticleFetcher: ArticleFetcher? - private(set) var timelineFeed: Feed? + private(set) var timelineFeed: SidebarItem? var timelineMiddleIndexPath: IndexPath? @@ -632,7 +632,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { func nodeFor(feedID: FeedIdentifier) -> Node? { return treeController.rootNode.descendantNode(where: { node in - if let feed = node.representedObject as? Feed { + if let feed = node.representedObject as? SidebarItem { return feed.feedID == feedID } else { return false @@ -766,7 +766,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { return indexPathFor(node) } - func selectFeed(_ feed: Feed?, animations: Animations = [], deselectArticle: Bool = true, completion: (() -> Void)? = nil) { + func selectFeed(_ feed: SidebarItem?, animations: Animations = [], deselectArticle: Bool = true, completion: (() -> Void)? = nil) { let indexPath: IndexPath? = { if let feed = feed, let indexPath = indexPathFor(feed as AnyObject) { return indexPath @@ -790,7 +790,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner { selectArticle(nil) } - if let ip = indexPath, let node = nodeFor(ip), let feed = node.representedObject as? Feed { + if let ip = indexPath, let node = nodeFor(ip), let feed = node.representedObject as? SidebarItem { self.activityManager.selecting(feed: feed) self.installTimelineControllerIfNecessary(animated: animations.contains(.navigation)) @@ -1439,7 +1439,7 @@ private extension SceneCoordinator { articleDictionaryNeedsUpdate = false } - func ensureFeedIsAvailableToSelect(_ feed: Feed, completion: @escaping () -> Void) { + func ensureFeedIsAvailableToSelect(_ feed: SidebarItem, completion: @escaping () -> Void) { addToFilterExeptionsIfNecessary(feed) addShadowTableToFilterExceptions() @@ -1449,7 +1449,7 @@ private extension SceneCoordinator { }) } - func addToFilterExeptionsIfNecessary(_ feed: Feed?) { + func addToFilterExeptionsIfNecessary(_ feed: SidebarItem?) { if isReadFeedsFiltered, let feedID = feed?.feedID { if feed is SmartFeed { treeControllerDelegate.addFilterException(feedID) @@ -1466,7 +1466,7 @@ private extension SceneCoordinator { } } - func addParentFolderToFilterExceptions(_ feed: Feed) { + func addParentFolderToFilterExceptions(_ feed: SidebarItem) { guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject), let folder = node.parent?.representedObject as? Folder, let folderFeedID = folder.feedID else { @@ -1479,7 +1479,7 @@ private extension SceneCoordinator { func addShadowTableToFilterExceptions() { for section in shadowTable { for feedNode in section.feedNodes { - if let feed = feedNode.node.representedObject as? Feed, let feedID = feed.feedID { + if let feed = feedNode.node.representedObject as? SidebarItem, let feedID = feed.feedID { treeControllerDelegate.addFilterException(feedID) } } @@ -1595,10 +1595,10 @@ private extension SceneCoordinator { return ShadowTableChanges(deletes: deletes, inserts: inserts, moves: moves, rowChanges: changes) } - func shadowTableContains(_ feed: Feed) -> Bool { + func shadowTableContains(_ feed: SidebarItem) -> Bool { for section in shadowTable { for feedNode in section.feedNodes { - if let nodeFeed = feedNode.node.representedObject as? Feed, nodeFeed.feedID == feed.feedID { + if let nodeFeed = feedNode.node.representedObject as? SidebarItem, nodeFeed.feedID == feed.feedID { return true } } @@ -1619,7 +1619,7 @@ private extension SceneCoordinator { return indexPathFor(node) } - func setTimelineFeed(_ feed: Feed?, animated: Bool, completion: (() -> Void)? = nil) { + func setTimelineFeed(_ feed: SidebarItem?, animated: Bool, completion: (() -> Void)? = nil) { timelineFeed = feed fetchAndReplaceArticlesAsync(animated: animated) {