Rename feedID to sidebarItemID.

This commit is contained in:
Brent Simmons 2024-02-25 21:34:22 -08:00
parent a75e5eb52a
commit b25c9eae94
17 changed files with 64 additions and 64 deletions

View File

@ -24,7 +24,7 @@ public final class Folder: SidebarItem, Renamable, Container, Hashable {
return ContainerIdentifier.folder(accountID, nameForDisplay) return ContainerIdentifier.folder(accountID, nameForDisplay)
} }
public var feedID: SidebarItemIdentifier? { public var sidebarItemID: SidebarItemIdentifier? {
guard let accountID = account?.accountID else { guard let accountID = account?.accountID else {
assertionFailure("Expected feed.account, but got nil.") assertionFailure("Expected feed.account, but got nil.")
return nil return nil

View File

@ -28,7 +28,7 @@ public extension SidebarItem {
guard defaultReadFilterType != .alwaysRead else { guard defaultReadFilterType != .alwaysRead else {
return true return true
} }
if let feedID = feedID, let readFilterEnabled = readFilterEnabledTable[feedID] { if let sidebarItemID, let readFilterEnabled = readFilterEnabledTable[sidebarItemID] {
return readFilterEnabled return readFilterEnabled
} else { } else {
return defaultReadFilterType == .read return defaultReadFilterType == .read

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
public protocol SidebarItemIdentifiable { public protocol SidebarItemIdentifiable {
var feedID: SidebarItemIdentifier? { get } var sidebarItemID: SidebarItemIdentifier? { get }
} }
public enum SidebarItemIdentifier: CustomStringConvertible, Hashable, Equatable { public enum SidebarItemIdentifier: CustomStringConvertible, Hashable, Equatable {

View File

@ -17,7 +17,7 @@ public final class WebFeed: SidebarItem, Renamable, Hashable {
return .none return .none
} }
public var feedID: SidebarItemIdentifier? { public var sidebarItemID: SidebarItemIdentifier? {
guard let accountID = account?.accountID else { guard let accountID = account?.accountID else {
assertionFailure("Expected feed.account, but got nil.") assertionFailure("Expected feed.account, but got nil.")
return nil return nil

View File

@ -97,7 +97,7 @@ protocol SidebarDelegate: AnyObject {
func saveState(to state: inout [AnyHashable : Any]) { func saveState(to state: inout [AnyHashable : Any]) {
state[UserInfoKey.readFeedsFilterState] = isReadFiltered state[UserInfoKey.readFeedsFilterState] = isReadFiltered
state[UserInfoKey.containerExpandedWindowState] = expandedTable.map { $0.userInfo } state[UserInfoKey.containerExpandedWindowState] = expandedTable.map { $0.userInfo }
state[UserInfoKey.selectedFeedsState] = selectedFeeds.compactMap { $0.feedID?.userInfo } state[UserInfoKey.selectedFeedsState] = selectedFeeds.compactMap { $0.sidebarItemID?.userInfo }
} }
func restoreState(from state: [AnyHashable : Any]) { func restoreState(from state: [AnyHashable : Any]) {
@ -119,8 +119,8 @@ protocol SidebarDelegate: AnyObject {
var selectIndexes = IndexSet() var selectIndexes = IndexSet()
func selectFeedsVisitor(node: Node) { func selectFeedsVisitor(node: Node) {
if let feedID = (node.representedObject as? SidebarItemIdentifiable)?.feedID { if let sidebarItemID = (node.representedObject as? SidebarItemIdentifiable)?.sidebarItemID {
if selectedFeedIdentifers.contains(feedID) { if selectedFeedIdentifers.contains(sidebarItemID) {
selectIndexes.insert(outlineView.row(forItem: node) ) selectIndexes.insert(outlineView.row(forItem: node) )
} }
} }
@ -448,12 +448,12 @@ protocol SidebarDelegate: AnyObject {
// MARK: - API // MARK: - API
func selectFeed(_ feed: SidebarItem) { func selectFeed(_ feed: SidebarItem) {
if isReadFiltered, let feedID = feed.feedID { if isReadFiltered, let sidebarItemID = feed.sidebarItemID {
self.treeControllerDelegate.addFilterException(feedID) self.treeControllerDelegate.addFilterException(sidebarItemID)
if let webFeed = feed as? WebFeed, let account = webFeed.account { if let webFeed = feed as? WebFeed, let account = webFeed.account {
let parentFolder = account.sortedFolders?.first(where: { $0.objectIsChild(webFeed) }) let parentFolder = account.sortedFolders?.first(where: { $0.objectIsChild(webFeed) })
if let parentFolderFeedID = parentFolder?.feedID { if let parentFolderFeedID = parentFolder?.sidebarItemID {
self.treeControllerDelegate.addFilterException(parentFolderFeedID) self.treeControllerDelegate.addFilterException(parentFolderFeedID)
} }
} }
@ -536,16 +536,16 @@ private extension SidebarViewController {
} }
func addToFilterExeptionsIfNecessary(_ feed: SidebarItem?) { func addToFilterExeptionsIfNecessary(_ feed: SidebarItem?) {
if isReadFiltered, let feedID = feed?.feedID { if isReadFiltered, let sidebarItemID = feed?.sidebarItemID {
if feed is PseudoFeed { if feed is PseudoFeed {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
} else if let folderFeed = feed as? Folder { } else if let folderFeed = feed as? Folder {
if folderFeed.account?.existingFolder(withID: folderFeed.folderID) != nil { if folderFeed.account?.existingFolder(withID: folderFeed.folderID) != nil {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
} }
} else if let webFeed = feed as? WebFeed { } else if let webFeed = feed as? WebFeed {
if webFeed.account?.existingWebFeed(withWebFeedID: webFeed.webFeedID) != nil { if webFeed.account?.existingWebFeed(withWebFeedID: webFeed.webFeedID) != nil {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
addParentFolderToFilterExceptions(webFeed) addParentFolderToFilterExceptions(webFeed)
} }
} }
@ -555,11 +555,11 @@ private extension SidebarViewController {
func addParentFolderToFilterExceptions(_ feed: SidebarItem) { func addParentFolderToFilterExceptions(_ feed: SidebarItem) {
guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject), guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject),
let folder = node.parent?.representedObject as? Folder, let folder = node.parent?.representedObject as? Folder,
let folderFeedID = folder.feedID else { let folderSidebarItemID = folder.sidebarItemID else {
return return
} }
treeControllerDelegate.addFilterException(folderFeedID) treeControllerDelegate.addFilterException(folderSidebarItemID)
} }
@ -613,8 +613,8 @@ private extension SidebarViewController {
} }
func addTreeControllerToFilterExceptionsVisitor(node: Node) { func addTreeControllerToFilterExceptionsVisitor(node: Node) {
if let feed = node.representedObject as? SidebarItem, let feedID = feed.feedID { if let sidebarItem = node.representedObject as? SidebarItem, let sidebarItemID = sidebarItem.sidebarItemID {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
} }
} }

View File

@ -36,7 +36,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
guard timelineFeed.defaultReadFilterType != .alwaysRead else { guard timelineFeed.defaultReadFilterType != .alwaysRead else {
return nil return nil
} }
if let feedID = timelineFeed.feedID, let readFilterEnabled = readFilterEnabledTable[feedID] { if let sidebarItemID = timelineFeed.sidebarItemID, let readFilterEnabled = readFilterEnabledTable[sidebarItemID] {
return readFilterEnabled return readFilterEnabled
} else { } else {
return timelineFeed.defaultReadFilterType == .read return timelineFeed.defaultReadFilterType == .read
@ -263,8 +263,8 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
} }
func toggleReadFilter() { func toggleReadFilter() {
guard let filter = isReadFiltered, let feedID = (representedObjects?.first as? SidebarItem)?.feedID else { return } guard let filter = isReadFiltered, let sidebarItemID = (representedObjects?.first as? SidebarItem)?.sidebarItemID else { return }
readFilterEnabledTable[feedID] = !filter readFilterEnabledTable[sidebarItemID] = !filter
delegate?.timelineInvalidatedRestorationState(self) delegate?.timelineInvalidatedRestorationState(self)
fetchAndReplacePreservingSelection() fetchAndReplacePreservingSelection()
} }

View File

@ -172,16 +172,16 @@ private extension ActivityManager {
activity.keywords = Set(makeKeywords(title)) activity.keywords = Set(makeKeywords(title))
activity.isEligibleForSearch = true activity.isEligibleForSearch = true
let articleFetcherIdentifierUserInfo = feed.feedID?.userInfo ?? [AnyHashable: Any]() let articleFetcherIdentifierUserInfo = feed.sidebarItemID?.userInfo ?? [AnyHashable: Any]()
activity.userInfo = [UserInfoKey.feedIdentifier: articleFetcherIdentifierUserInfo] activity.userInfo = [UserInfoKey.feedIdentifier: articleFetcherIdentifierUserInfo]
activity.requiredUserInfoKeys = Set(activity.userInfo!.keys.map { $0 as! String }) activity.requiredUserInfoKeys = Set(activity.userInfo!.keys.map { $0 as! String })
activity.persistentIdentifier = feed.feedID?.description ?? "" activity.persistentIdentifier = feed.sidebarItemID?.description ?? ""
#if os(iOS) #if os(iOS)
activity.suggestedInvocationPhrase = title activity.suggestedInvocationPhrase = title
activity.isEligibleForPrediction = true activity.isEligibleForPrediction = true
activity.contentAttributeSet?.relatedUniqueIdentifier = feed.feedID?.description ?? "" activity.contentAttributeSet?.relatedUniqueIdentifier = feed.sidebarItemID?.description ?? ""
#endif #endif
return activity return activity
@ -192,7 +192,7 @@ private extension ActivityManager {
activity.title = ArticleStringFormatter.truncatedTitle(article) activity.title = ArticleStringFormatter.truncatedTitle(article)
if let feed = feed { if let feed = feed {
let articleFetcherIdentifierUserInfo = feed.feedID?.userInfo ?? [AnyHashable: Any]() let articleFetcherIdentifierUserInfo = feed.sidebarItemID?.userInfo ?? [AnyHashable: Any]()
let articlePathUserInfo = article.pathUserInfo let articlePathUserInfo = article.pathUserInfo
activity.userInfo = [UserInfoKey.feedIdentifier: articleFetcherIdentifierUserInfo, UserInfoKey.articlePath: articlePathUserInfo] activity.userInfo = [UserInfoKey.feedIdentifier: articleFetcherIdentifierUserInfo, UserInfoKey.articlePath: articlePathUserInfo]
} else { } else {

View File

@ -30,19 +30,19 @@ class IconImageCache {
return nil return nil
} }
func imageForFeed(_ feed: SidebarItem) -> IconImage? { func imageForFeed(_ sidebarItem: SidebarItem) -> IconImage? {
guard let feedID = feed.feedID else { guard let sidebarItemID = sidebarItem.sidebarItemID else {
return nil return nil
} }
if let smartFeed = feed as? PseudoFeed { if let smartFeed = sidebarItem as? PseudoFeed {
return imageForSmartFeed(smartFeed, feedID) return imageForSmartFeed(smartFeed, sidebarItemID)
} }
if let webFeed = feed as? WebFeed, let iconImage = imageForWebFeed(webFeed, feedID) { if let webFeed = sidebarItem as? WebFeed, let iconImage = imageForWebFeed(webFeed, sidebarItemID) {
return iconImage return iconImage
} }
if let smallIconProvider = feed as? SmallIconProvider { if let smallIconProvider = sidebarItem as? SmallIconProvider {
return imageForSmallIconProvider(smallIconProvider, feedID) return imageForSmallIconProvider(smallIconProvider, sidebarItemID)
} }
return nil return nil

View File

@ -14,7 +14,7 @@ import ArticlesDatabase
struct SearchFeedDelegate: SmartFeedDelegate { struct SearchFeedDelegate: SmartFeedDelegate {
var feedID: SidebarItemIdentifier? { var sidebarItemID: SidebarItemIdentifier? {
return SidebarItemIdentifier.smartFeed(String(describing: SearchFeedDelegate.self)) return SidebarItemIdentifier.smartFeed(String(describing: SearchFeedDelegate.self))
} }

View File

@ -14,7 +14,7 @@ import ArticlesDatabase
struct SearchTimelineFeedDelegate: SmartFeedDelegate { struct SearchTimelineFeedDelegate: SmartFeedDelegate {
var feedID: SidebarItemIdentifier? { var sidebarItemID: SidebarItemIdentifier? {
return SidebarItemIdentifier.smartFeed(String(describing: SearchTimelineFeedDelegate.self)) return SidebarItemIdentifier.smartFeed(String(describing: SearchTimelineFeedDelegate.self))
} }

View File

@ -20,8 +20,8 @@ final class SmartFeed: PseudoFeed {
return .none return .none
} }
var feedID: SidebarItemIdentifier? { var sidebarItemID: SidebarItemIdentifier? {
delegate.feedID delegate.sidebarItemID
} }
var nameForDisplay: String { var nameForDisplay: String {

View File

@ -16,7 +16,7 @@ import Account
struct StarredFeedDelegate: SmartFeedDelegate { struct StarredFeedDelegate: SmartFeedDelegate {
var feedID: SidebarItemIdentifier? { var sidebarItemID: SidebarItemIdentifier? {
return SidebarItemIdentifier.smartFeed(String(describing: StarredFeedDelegate.self)) return SidebarItemIdentifier.smartFeed(String(describing: StarredFeedDelegate.self))
} }

View File

@ -14,7 +14,7 @@ import Account
struct TodayFeedDelegate: SmartFeedDelegate { struct TodayFeedDelegate: SmartFeedDelegate {
var feedID: SidebarItemIdentifier? { var sidebarItemID: SidebarItemIdentifier? {
return SidebarItemIdentifier.smartFeed(String(describing: TodayFeedDelegate.self)) return SidebarItemIdentifier.smartFeed(String(describing: TodayFeedDelegate.self))
} }

View File

@ -26,7 +26,7 @@ final class UnreadFeed: PseudoFeed {
return .alwaysRead return .alwaysRead
} }
var feedID: SidebarItemIdentifier? { var sidebarItemID: SidebarItemIdentifier? {
return SidebarItemIdentifier.smartFeed(String(describing: UnreadFeed.self)) return SidebarItemIdentifier.smartFeed(String(describing: UnreadFeed.self))
} }

View File

@ -67,14 +67,14 @@ private extension WebFeedTreeControllerDelegate {
var children = [AnyObject]() var children = [AnyObject]()
for webFeed in container.topLevelWebFeeds { for webFeed in container.topLevelWebFeeds {
if let feedID = webFeed.feedID, !(!filterExceptions.contains(feedID) && isReadFiltered && webFeed.unreadCount == 0) { if let sidebarItemID = webFeed.sidebarItemID, !(!filterExceptions.contains(sidebarItemID) && isReadFiltered && webFeed.unreadCount == 0) {
children.append(webFeed) children.append(webFeed)
} }
} }
if let folders = container.folders { if let folders = container.folders {
for folder in folders { for folder in folders {
if let feedID = folder.feedID, !(!filterExceptions.contains(feedID) && isReadFiltered && folder.unreadCount == 0) { if let sidebarItemID = folder.sidebarItemID, !(!filterExceptions.contains(sidebarItemID) && isReadFiltered && folder.unreadCount == 0) {
children.append(folder) children.append(folder)
} }
} }

View File

@ -798,10 +798,10 @@ private extension MasterFeedViewController {
} }
func configureIcon(_ cell: MasterFeedTableViewCell, _ indexPath: IndexPath) { func configureIcon(_ cell: MasterFeedTableViewCell, _ indexPath: IndexPath) {
guard let node = coordinator.nodeFor(indexPath), let feed = node.representedObject as? SidebarItem, let feedID = feed.feedID else { guard let node = coordinator.nodeFor(indexPath), let feed = node.representedObject as? SidebarItem, let sidebarItemID = feed.sidebarItemID else {
return return
} }
cell.iconImage = IconImageCache.shared.imageFor(feedID) cell.iconImage = IconImageCache.shared.imageFor(sidebarItemID)
} }
func nameFor(_ node: Node) -> String { func nameFor(_ node: Node) -> String {
@ -820,7 +820,7 @@ private extension MasterFeedViewController {
if let node = coordinator.nodeFor(indexPath), if let node = coordinator.nodeFor(indexPath),
let representedFeed = representedObject as? SidebarItem, let representedFeed = representedObject as? SidebarItem,
let candidate = node.representedObject as? SidebarItem, let candidate = node.representedObject as? SidebarItem,
representedFeed.feedID == candidate.feedID { representedFeed.sidebarItemID == candidate.sidebarItemID {
completion(cell, indexPath) completion(cell, indexPath)
} }
} }

View File

@ -37,7 +37,7 @@ struct FeedNode: Hashable {
init(_ node: Node) { init(_ node: Node) {
self.node = node self.node = node
self.feedID = (node.representedObject as! SidebarItem).feedID! self.feedID = (node.representedObject as! SidebarItem).sidebarItemID!
} }
func hash(into hasher: inout Hasher) { func hash(into hasher: inout Hasher) {
@ -149,7 +149,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
} }
var isReadArticlesFiltered: Bool { var isReadArticlesFiltered: Bool {
if let feedID = timelineFeed?.feedID, let readFilterEnabled = readFilterEnabledTable[feedID] { if let sidebarItemID = timelineFeed?.sidebarItemID, let readFilterEnabled = readFilterEnabledTable[sidebarItemID] {
return readFilterEnabled return readFilterEnabled
} else { } else {
return timelineDefaultReadFilterType != .none return timelineDefaultReadFilterType != .none
@ -617,23 +617,23 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
} }
func toggleReadArticlesFilter() { func toggleReadArticlesFilter() {
guard let feedID = timelineFeed?.feedID else { guard let sidebarItemID = timelineFeed?.sidebarItemID else {
return return
} }
if isReadArticlesFiltered { if isReadArticlesFiltered {
readFilterEnabledTable[feedID] = false readFilterEnabledTable[sidebarItemID] = false
} else { } else {
readFilterEnabledTable[feedID] = true readFilterEnabledTable[sidebarItemID] = true
} }
refreshTimeline(resetScroll: false) refreshTimeline(resetScroll: false)
} }
func nodeFor(feedID: SidebarItemIdentifier) -> Node? { func nodeFor(sidebarItemID: SidebarItemIdentifier) -> Node? {
return treeController.rootNode.descendantNode(where: { node in return treeController.rootNode.descendantNode(where: { node in
if let feed = node.representedObject as? SidebarItem { if let feed = node.representedObject as? SidebarItem {
return feed.feedID == feedID return feed.sidebarItemID == sidebarItemID
} else { } else {
return false return false
} }
@ -1128,10 +1128,10 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
markExpanded(parentFolder) markExpanded(parentFolder)
} }
if let webFeedFeedID = webFeed.feedID { if let webFeedFeedID = webFeed.sidebarItemID {
self.treeControllerDelegate.addFilterException(webFeedFeedID) self.treeControllerDelegate.addFilterException(webFeedFeedID)
} }
if let parentFolderFeedID = parentFolder?.feedID { if let parentFolderFeedID = parentFolder?.sidebarItemID {
self.treeControllerDelegate.addFilterException(parentFolderFeedID) self.treeControllerDelegate.addFilterException(parentFolderFeedID)
} }
@ -1450,16 +1450,16 @@ private extension SceneCoordinator {
} }
func addToFilterExeptionsIfNecessary(_ feed: SidebarItem?) { func addToFilterExeptionsIfNecessary(_ feed: SidebarItem?) {
if isReadFeedsFiltered, let feedID = feed?.feedID { if isReadFeedsFiltered, let sidebarItemID = feed?.sidebarItemID {
if feed is SmartFeed { if feed is SmartFeed {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
} else if let folderFeed = feed as? Folder { } else if let folderFeed = feed as? Folder {
if folderFeed.account?.existingFolder(withID: folderFeed.folderID) != nil { if folderFeed.account?.existingFolder(withID: folderFeed.folderID) != nil {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
} }
} else if let webFeed = feed as? WebFeed { } else if let webFeed = feed as? WebFeed {
if webFeed.account?.existingWebFeed(withWebFeedID: webFeed.webFeedID) != nil { if webFeed.account?.existingWebFeed(withWebFeedID: webFeed.webFeedID) != nil {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(sidebarItemID)
addParentFolderToFilterExceptions(webFeed) addParentFolderToFilterExceptions(webFeed)
} }
} }
@ -1469,7 +1469,7 @@ private extension SceneCoordinator {
func addParentFolderToFilterExceptions(_ feed: SidebarItem) { func addParentFolderToFilterExceptions(_ feed: SidebarItem) {
guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject), guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject),
let folder = node.parent?.representedObject as? Folder, let folder = node.parent?.representedObject as? Folder,
let folderFeedID = folder.feedID else { let folderFeedID = folder.sidebarItemID else {
return return
} }
@ -1479,7 +1479,7 @@ private extension SceneCoordinator {
func addShadowTableToFilterExceptions() { func addShadowTableToFilterExceptions() {
for section in shadowTable { for section in shadowTable {
for feedNode in section.feedNodes { for feedNode in section.feedNodes {
if let feed = feedNode.node.representedObject as? SidebarItem, let feedID = feed.feedID { if let feed = feedNode.node.representedObject as? SidebarItem, let feedID = feed.sidebarItemID {
treeControllerDelegate.addFilterException(feedID) treeControllerDelegate.addFilterException(feedID)
} }
} }
@ -1598,7 +1598,7 @@ private extension SceneCoordinator {
func shadowTableContains(_ feed: SidebarItem) -> Bool { func shadowTableContains(_ feed: SidebarItem) -> Bool {
for section in shadowTable { for section in shadowTable {
for feedNode in section.feedNodes { for feedNode in section.feedNodes {
if let nodeFeed = feedNode.node.representedObject as? SidebarItem, nodeFeed.feedID == feed.feedID { if let nodeFeed = feedNode.node.representedObject as? SidebarItem, nodeFeed.sidebarItemID == feed.sidebarItemID {
return true return true
} }
} }
@ -2316,7 +2316,7 @@ private extension SceneCoordinator {
let found = selectFeedAndArticle(feedIdentifier: feedIdentifier, articleID: articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY) let found = selectFeedAndArticle(feedIdentifier: feedIdentifier, articleID: articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)
if found { if found {
treeControllerDelegate.addFilterException(feedIdentifier) treeControllerDelegate.addFilterException(feedIdentifier)
if let webFeedNode = nodeFor(feedID: feedIdentifier), let folder = webFeedNode.parent?.representedObject as? Folder, let folderFeedID = folder.feedID { if let webFeedNode = nodeFor(sidebarItemID: feedIdentifier), let folder = webFeedNode.parent?.representedObject as? Folder, let folderFeedID = folder.sidebarItemID {
treeControllerDelegate.addFilterException(folderFeedID) treeControllerDelegate.addFilterException(folderFeedID)
} }
} }
@ -2353,7 +2353,7 @@ private extension SceneCoordinator {
} }
func selectFeedAndArticle(feedIdentifier: SidebarItemIdentifier, articleID: String, isShowingExtractedArticle: Bool, articleWindowScrollY: Int) -> Bool { func selectFeedAndArticle(feedIdentifier: SidebarItemIdentifier, articleID: String, isShowingExtractedArticle: Bool, articleWindowScrollY: Int) -> Bool {
guard let feedNode = nodeFor(feedID: feedIdentifier), let feedIndexPath = indexPathFor(feedNode) else { return false } guard let feedNode = nodeFor(sidebarItemID: feedIdentifier), let feedIndexPath = indexPathFor(feedNode) else { return false }
selectFeed(indexPath: feedIndexPath) { selectFeed(indexPath: feedIndexPath) {
self.selectArticleInCurrentFeed(articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY) self.selectArticleInCurrentFeed(articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)