mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Use ItemIdentifier and itemID instead of FeedIdentifier and feedID. (FeedIdentifier was renamed to ItemIdentifier.)
This commit is contained in:
@@ -100,7 +100,7 @@ protocol SidebarDelegate: AnyObject {
|
||||
func saveState(to state: inout [AnyHashable : Any]) {
|
||||
state[UserInfoKey.readFeedsFilterState] = isReadFiltered
|
||||
state[UserInfoKey.containerExpandedWindowState] = expandedTable.map { $0.userInfo }
|
||||
state[UserInfoKey.selectedFeedsState] = selectedFeeds.compactMap { $0.feedID?.userInfo }
|
||||
state[UserInfoKey.selectedFeedsState] = selectedFeeds.compactMap { $0.itemID?.userInfo }
|
||||
}
|
||||
|
||||
func restoreState(from state: [AnyHashable : Any]) {
|
||||
@@ -114,22 +114,22 @@ protocol SidebarDelegate: AnyObject {
|
||||
return
|
||||
}
|
||||
|
||||
let selectedFeedIdentifers = Set(selectedFeedsState.compactMap( { FeedIdentifier(userInfo: $0) }))
|
||||
selectedFeedIdentifers.forEach { treeControllerDelegate.addFilterException($0) }
|
||||
let selectedItemIdentifers = Set(selectedFeedsState.compactMap( { ItemIdentifier(userInfo: $0) }))
|
||||
selectedItemIdentifers.forEach { treeControllerDelegate.addFilterException($0) }
|
||||
|
||||
rebuildTreeAndReloadDataIfNeeded()
|
||||
|
||||
var selectIndexes = IndexSet()
|
||||
|
||||
func selectFeedsVisitor(node: Node) {
|
||||
if let feedID = (node.representedObject as? FeedIdentifiable)?.feedID {
|
||||
if selectedFeedIdentifers.contains(feedID) {
|
||||
func selectItemsVisitor(node: Node) {
|
||||
if let itemID = (node.representedObject as? ItemIdentifiable)?.itemID {
|
||||
if selectedItemIdentifers.contains(itemID) {
|
||||
selectIndexes.insert(outlineView.row(forItem: node) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
treeController.visitNodes(selectFeedsVisitor(node:))
|
||||
treeController.visitNodes(selectItemsVisitor(node:))
|
||||
outlineView.selectRowIndexes(selectIndexes, byExtendingSelection: false)
|
||||
focus()
|
||||
|
||||
@@ -456,13 +456,13 @@ protocol SidebarDelegate: AnyObject {
|
||||
// MARK: - API
|
||||
|
||||
func selectFeed(_ feed: FeedProtocol) {
|
||||
if isReadFiltered, let feedID = feed.feedID {
|
||||
self.treeControllerDelegate.addFilterException(feedID)
|
||||
if isReadFiltered, let itemID = feed.itemID {
|
||||
self.treeControllerDelegate.addFilterException(itemID)
|
||||
|
||||
if let webFeed = feed as? WebFeed, let account = webFeed.account {
|
||||
let parentFolder = account.sortedFolders?.first(where: { $0.objectIsChild(webFeed) })
|
||||
if let parentFolderFeedID = parentFolder?.feedID {
|
||||
self.treeControllerDelegate.addFilterException(parentFolderFeedID)
|
||||
if let parentFolderItemID = parentFolder?.itemID {
|
||||
self.treeControllerDelegate.addFilterException(parentFolderItemID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,16 +544,16 @@ private extension SidebarViewController {
|
||||
}
|
||||
|
||||
func addToFilterExeptionsIfNecessary(_ feed: FeedProtocol?) {
|
||||
if isReadFiltered, let feedID = feed?.feedID {
|
||||
if isReadFiltered, let itemID = feed?.itemID {
|
||||
if feed is PseudoFeed {
|
||||
treeControllerDelegate.addFilterException(feedID)
|
||||
treeControllerDelegate.addFilterException(itemID)
|
||||
} else if let folderFeed = feed as? Folder {
|
||||
if folderFeed.account?.existingFolder(withID: folderFeed.folderID) != nil {
|
||||
treeControllerDelegate.addFilterException(feedID)
|
||||
treeControllerDelegate.addFilterException(itemID)
|
||||
}
|
||||
} else if let webFeed = feed as? WebFeed {
|
||||
if webFeed.account?.existingWebFeed(withWebFeedID: webFeed.webFeedID) != nil {
|
||||
treeControllerDelegate.addFilterException(feedID)
|
||||
treeControllerDelegate.addFilterException(itemID)
|
||||
addParentFolderToFilterExceptions(webFeed)
|
||||
}
|
||||
}
|
||||
@@ -563,11 +563,11 @@ private extension SidebarViewController {
|
||||
func addParentFolderToFilterExceptions(_ feed: FeedProtocol) {
|
||||
guard let node = treeController.rootNode.descendantNodeRepresentingObject(feed as AnyObject),
|
||||
let folder = node.parent?.representedObject as? Folder,
|
||||
let folderFeedID = folder.feedID else {
|
||||
let folderItemID = folder.itemID else {
|
||||
return
|
||||
}
|
||||
|
||||
treeControllerDelegate.addFilterException(folderFeedID)
|
||||
treeControllerDelegate.addFilterException(folderItemID)
|
||||
}
|
||||
|
||||
|
||||
@@ -621,8 +621,8 @@ private extension SidebarViewController {
|
||||
}
|
||||
|
||||
func addTreeControllerToFilterExceptionsVisitor(node: Node) {
|
||||
if let feed = node.representedObject as? FeedProtocol, let feedID = feed.feedID {
|
||||
treeControllerDelegate.addFilterException(feedID)
|
||||
if let feed = node.representedObject as? FeedProtocol, let itemID = feed.itemID {
|
||||
treeControllerDelegate.addFilterException(itemID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
|
||||
@IBOutlet var tableView: TimelineTableView!
|
||||
|
||||
private var readFilterEnabledTable = [FeedIdentifier: Bool]()
|
||||
private var readFilterEnabledTable = [ItemIdentifier: Bool]()
|
||||
var isReadFiltered: Bool? {
|
||||
guard representedObjects?.count == 1, let timelineFeed = representedObjects?.first as? FeedProtocol else {
|
||||
return nil
|
||||
@@ -35,7 +35,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
guard timelineFeed.defaultReadFilterType != .alwaysRead else {
|
||||
return nil
|
||||
}
|
||||
if let feedID = timelineFeed.feedID, let readFilterEnabled = readFilterEnabledTable[feedID] {
|
||||
if let itemID = timelineFeed.itemID, let readFilterEnabled = readFilterEnabledTable[itemID] {
|
||||
return readFilterEnabled
|
||||
} else {
|
||||
return timelineFeed.defaultReadFilterType == .read
|
||||
@@ -281,8 +281,8 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
}
|
||||
|
||||
func toggleReadFilter() {
|
||||
guard let filter = isReadFiltered, let feedID = (representedObjects?.first as? FeedProtocol)?.feedID else { return }
|
||||
readFilterEnabledTable[feedID] = !filter
|
||||
guard let filter = isReadFiltered, let itemID = (representedObjects?.first as? FeedProtocol)?.itemID else { return }
|
||||
readFilterEnabledTable[itemID] = !filter
|
||||
delegate?.timelineInvalidatedRestorationState(self)
|
||||
fetchAndReplacePreservingSelection()
|
||||
}
|
||||
@@ -305,8 +305,8 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
}
|
||||
|
||||
for i in 0..<readArticlesFilterStateKeys.count {
|
||||
if let feedIdentifier = FeedIdentifier(userInfo: readArticlesFilterStateKeys[i]) {
|
||||
readFilterEnabledTable[feedIdentifier] = readArticlesFilterStateValues[i]
|
||||
if let itemIdentifier = ItemIdentifier(userInfo: readArticlesFilterStateKeys[i]) {
|
||||
readFilterEnabledTable[itemIdentifier] = readArticlesFilterStateValues[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,11 +172,11 @@ private extension ActivityManager {
|
||||
activity.keywords = Set(makeKeywords(title))
|
||||
activity.isEligibleForSearch = true
|
||||
|
||||
let articleFetcherIdentifierUserInfo = feed.feedID?.userInfo ?? [AnyHashable: Any]()
|
||||
activity.userInfo = [UserInfoKey.feedIdentifier: articleFetcherIdentifierUserInfo]
|
||||
let articleFetcherIdentifierUserInfo = feed.itemID?.userInfo ?? [AnyHashable: Any]()
|
||||
activity.userInfo = [UserInfoKey.itemIdentifier: articleFetcherIdentifierUserInfo]
|
||||
activity.requiredUserInfoKeys = Set(activity.userInfo!.keys.map { $0 as! String })
|
||||
|
||||
activity.persistentIdentifier = feed.feedID?.description ?? ""
|
||||
activity.persistentIdentifier = feed.itemID?.description ?? ""
|
||||
|
||||
#if os(iOS)
|
||||
activity.suggestedInvocationPhrase = title
|
||||
@@ -192,9 +192,9 @@ private extension ActivityManager {
|
||||
activity.title = ArticleStringFormatter.truncatedTitle(article)
|
||||
|
||||
if let feed = feed {
|
||||
let articleFetcherIdentifierUserInfo = feed.feedID?.userInfo ?? [AnyHashable: Any]()
|
||||
let articleFetcherIdentifierUserInfo = feed.itemID?.userInfo ?? [AnyHashable: Any]()
|
||||
let articlePathUserInfo = article.pathUserInfo
|
||||
activity.userInfo = [UserInfoKey.feedIdentifier: articleFetcherIdentifierUserInfo, UserInfoKey.articlePath: articlePathUserInfo]
|
||||
activity.userInfo = [UserInfoKey.itemIdentifier: articleFetcherIdentifierUserInfo, UserInfoKey.articlePath: articlePathUserInfo]
|
||||
} else {
|
||||
activity.userInfo = [UserInfoKey.articlePath: article.pathUserInfo]
|
||||
}
|
||||
|
||||
@@ -14,35 +14,35 @@ class IconImageCache {
|
||||
|
||||
static var shared = IconImageCache()
|
||||
|
||||
private var smartFeedIconImageCache = [FeedIdentifier: IconImage]()
|
||||
private var webFeedIconImageCache = [FeedIdentifier: IconImage]()
|
||||
private var faviconImageCache = [FeedIdentifier: IconImage]()
|
||||
private var smallIconImageCache = [FeedIdentifier: IconImage]()
|
||||
private var smartFeedIconImageCache = [ItemIdentifier: IconImage]()
|
||||
private var webFeedIconImageCache = [ItemIdentifier: IconImage]()
|
||||
private var faviconImageCache = [ItemIdentifier: IconImage]()
|
||||
private var smallIconImageCache = [ItemIdentifier: IconImage]()
|
||||
private var authorIconImageCache = [Author: IconImage]()
|
||||
|
||||
func imageFor(_ feedID: FeedIdentifier) -> IconImage? {
|
||||
if let smartFeed = SmartFeedsController.shared.find(by: feedID) {
|
||||
func imageFor(_ itemID: ItemIdentifier) -> IconImage? {
|
||||
if let smartFeed = SmartFeedsController.shared.find(by: itemID) {
|
||||
return imageForFeed(smartFeed)
|
||||
}
|
||||
if let feed = AccountManager.shared.existingFeed(with: feedID) {
|
||||
if let feed = AccountManager.shared.existingFeed(with: itemID) {
|
||||
return imageForFeed(feed)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageForFeed(_ feed: FeedProtocol) -> IconImage? {
|
||||
guard let feedID = feed.feedID else {
|
||||
guard let itemID = feed.itemID else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if let smartFeed = feed as? PseudoFeed {
|
||||
return imageForSmartFeed(smartFeed, feedID)
|
||||
return imageForSmartFeed(smartFeed, itemID)
|
||||
}
|
||||
if let webFeed = feed as? WebFeed, let iconImage = imageForWebFeed(webFeed, feedID) {
|
||||
if let webFeed = feed as? WebFeed, let iconImage = imageForWebFeed(webFeed, itemID) {
|
||||
return iconImage
|
||||
}
|
||||
if let smallIconProvider = feed as? SmallIconProvider {
|
||||
return imageForSmallIconProvider(smallIconProvider, feedID)
|
||||
return imageForSmallIconProvider(smallIconProvider, itemID)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -59,51 +59,51 @@ class IconImageCache {
|
||||
}
|
||||
|
||||
func emptyCache() {
|
||||
smartFeedIconImageCache = [FeedIdentifier: IconImage]()
|
||||
webFeedIconImageCache = [FeedIdentifier: IconImage]()
|
||||
faviconImageCache = [FeedIdentifier: IconImage]()
|
||||
smallIconImageCache = [FeedIdentifier: IconImage]()
|
||||
smartFeedIconImageCache = [ItemIdentifier: IconImage]()
|
||||
webFeedIconImageCache = [ItemIdentifier: IconImage]()
|
||||
faviconImageCache = [ItemIdentifier: IconImage]()
|
||||
smallIconImageCache = [ItemIdentifier: IconImage]()
|
||||
authorIconImageCache = [Author: IconImage]()
|
||||
}
|
||||
}
|
||||
|
||||
private extension IconImageCache {
|
||||
|
||||
func imageForSmartFeed(_ smartFeed: PseudoFeed, _ feedID: FeedIdentifier) -> IconImage? {
|
||||
if let iconImage = smartFeedIconImageCache[feedID] {
|
||||
func imageForSmartFeed(_ smartFeed: PseudoFeed, _ itemID: ItemIdentifier) -> IconImage? {
|
||||
if let iconImage = smartFeedIconImageCache[itemID] {
|
||||
return iconImage
|
||||
}
|
||||
if let iconImage = smartFeed.smallIcon {
|
||||
smartFeedIconImageCache[feedID] = iconImage
|
||||
smartFeedIconImageCache[itemID] = iconImage
|
||||
return iconImage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageForWebFeed(_ webFeed: WebFeed, _ feedID: FeedIdentifier) -> IconImage? {
|
||||
if let iconImage = webFeedIconImageCache[feedID] {
|
||||
func imageForWebFeed(_ webFeed: WebFeed, _ itemID: ItemIdentifier) -> IconImage? {
|
||||
if let iconImage = webFeedIconImageCache[itemID] {
|
||||
return iconImage
|
||||
}
|
||||
if let iconImage = appDelegate.webFeedIconDownloader.icon(for: webFeed) {
|
||||
webFeedIconImageCache[feedID] = iconImage
|
||||
webFeedIconImageCache[itemID] = iconImage
|
||||
return iconImage
|
||||
}
|
||||
if let faviconImage = faviconImageCache[feedID] {
|
||||
if let faviconImage = faviconImageCache[itemID] {
|
||||
return faviconImage
|
||||
}
|
||||
if let faviconImage = appDelegate.faviconDownloader.faviconAsIcon(for: webFeed) {
|
||||
faviconImageCache[feedID] = faviconImage
|
||||
faviconImageCache[itemID] = faviconImage
|
||||
return faviconImage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageForSmallIconProvider(_ provider: SmallIconProvider, _ feedID: FeedIdentifier) -> IconImage? {
|
||||
if let iconImage = smallIconImageCache[feedID] {
|
||||
func imageForSmallIconProvider(_ provider: SmallIconProvider, _ itemID: ItemIdentifier) -> IconImage? {
|
||||
if let iconImage = smallIconImageCache[itemID] {
|
||||
return iconImage
|
||||
}
|
||||
if let iconImage = provider.smallIcon {
|
||||
smallIconImageCache[feedID] = iconImage
|
||||
smallIconImageCache[itemID] = iconImage
|
||||
return iconImage
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -14,8 +14,8 @@ import ArticlesDatabase
|
||||
|
||||
struct SearchFeedDelegate: SmartFeedDelegate {
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
return FeedIdentifier.smartFeed(String(describing: SearchFeedDelegate.self))
|
||||
var itemID: ItemIdentifier? {
|
||||
return ItemIdentifier.smartFeed(String(describing: SearchFeedDelegate.self))
|
||||
}
|
||||
|
||||
var nameForDisplay: String {
|
||||
|
||||
@@ -14,8 +14,8 @@ import ArticlesDatabase
|
||||
|
||||
struct SearchTimelineFeedDelegate: SmartFeedDelegate {
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
return FeedIdentifier.smartFeed(String(describing: SearchTimelineFeedDelegate.self))
|
||||
var itemID: ItemIdentifier? {
|
||||
return ItemIdentifier.smartFeed(String(describing: SearchTimelineFeedDelegate.self))
|
||||
}
|
||||
|
||||
var nameForDisplay: String {
|
||||
|
||||
@@ -20,8 +20,8 @@ final class SmartFeed: PseudoFeed {
|
||||
return .none
|
||||
}
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
delegate.feedID
|
||||
var itemID: ItemIdentifier? {
|
||||
delegate.itemID
|
||||
}
|
||||
|
||||
var nameForDisplay: String {
|
||||
|
||||
@@ -12,7 +12,7 @@ import Articles
|
||||
import ArticlesDatabase
|
||||
import RSCore
|
||||
|
||||
protocol SmartFeedDelegate: FeedIdentifiable, DisplayNameProvider, ArticleFetcher, SmallIconProvider {
|
||||
protocol SmartFeedDelegate: ItemIdentifiable, DisplayNameProvider, ArticleFetcher, SmallIconProvider {
|
||||
var fetchType: FetchType { get }
|
||||
func fetchUnreadCount(for: Account, completion: @escaping SingleUnreadCountCompletionBlock)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ final class SmartFeedsController: DisplayNameProvider, ContainerIdentifiable {
|
||||
self.smartFeeds = [todayFeed, unreadFeed, starredFeed]
|
||||
}
|
||||
|
||||
func find(by identifier: FeedIdentifier) -> PseudoFeed? {
|
||||
func find(by identifier: ItemIdentifier) -> PseudoFeed? {
|
||||
switch identifier {
|
||||
case .smartFeed(let stringIdentifer):
|
||||
switch stringIdentifer {
|
||||
|
||||
@@ -16,8 +16,8 @@ import Account
|
||||
|
||||
struct StarredFeedDelegate: SmartFeedDelegate {
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
return FeedIdentifier.smartFeed(String(describing: StarredFeedDelegate.self))
|
||||
var itemID: ItemIdentifier? {
|
||||
return ItemIdentifier.smartFeed(String(describing: StarredFeedDelegate.self))
|
||||
}
|
||||
|
||||
let nameForDisplay = NSLocalizedString("smartfeed.title.starred", comment: "Starred pseudo-feed title")
|
||||
|
||||
@@ -14,8 +14,8 @@ import Account
|
||||
|
||||
struct TodayFeedDelegate: SmartFeedDelegate {
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
return FeedIdentifier.smartFeed(String(describing: TodayFeedDelegate.self))
|
||||
var itemID: ItemIdentifier? {
|
||||
return ItemIdentifier.smartFeed(String(describing: TodayFeedDelegate.self))
|
||||
}
|
||||
|
||||
let nameForDisplay = NSLocalizedString("smartfeed.title.today", comment: "Today pseudo-feed title")
|
||||
|
||||
@@ -26,8 +26,8 @@ final class UnreadFeed: PseudoFeed {
|
||||
return .alwaysRead
|
||||
}
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
return FeedIdentifier.smartFeed(String(describing: UnreadFeed.self))
|
||||
var itemID: ItemIdentifier? {
|
||||
return ItemIdentifier.smartFeed(String(describing: UnreadFeed.self))
|
||||
}
|
||||
|
||||
let nameForDisplay = NSLocalizedString("smartfeed.title.allunread", comment: "All Unread pseudo-feed title")
|
||||
|
||||
@@ -19,13 +19,13 @@ typealias FetchRequestOperationResultBlock = (Set<Article>, FetchRequestOperatio
|
||||
final class FetchRequestOperation {
|
||||
|
||||
let id: Int
|
||||
let readFilterEnabledTable: [FeedIdentifier: Bool]
|
||||
let readFilterEnabledTable: [ItemIdentifier: Bool]
|
||||
let resultBlock: FetchRequestOperationResultBlock
|
||||
var isCanceled = false
|
||||
var isFinished = false
|
||||
private let fetchers: [ArticleFetcher]
|
||||
|
||||
init(id: Int, readFilterEnabledTable: [FeedIdentifier: Bool], fetchers: [ArticleFetcher], resultBlock: @escaping FetchRequestOperationResultBlock) {
|
||||
init(id: Int, readFilterEnabledTable: [ItemIdentifier: Bool], fetchers: [ArticleFetcher], resultBlock: @escaping FetchRequestOperationResultBlock) {
|
||||
precondition(Thread.isMainThread)
|
||||
self.id = id
|
||||
self.readFilterEnabledTable = readFilterEnabledTable
|
||||
|
||||
@@ -13,15 +13,15 @@ import Account
|
||||
|
||||
final class FeedTreeControllerDelegate: TreeControllerDelegate {
|
||||
|
||||
private var filterExceptions = Set<FeedIdentifier>()
|
||||
private var filterExceptions = Set<ItemIdentifier>()
|
||||
var isReadFiltered = false
|
||||
|
||||
func addFilterException(_ feedID: FeedIdentifier) {
|
||||
filterExceptions.insert(feedID)
|
||||
func addFilterException(_ itemID: ItemIdentifier) {
|
||||
filterExceptions.insert(itemID)
|
||||
}
|
||||
|
||||
func resetFilterExceptions() {
|
||||
filterExceptions = Set<FeedIdentifier>()
|
||||
filterExceptions = Set<ItemIdentifier>()
|
||||
}
|
||||
|
||||
func treeController(treeController: TreeController, childNodesFor node: Node) -> [Node]? {
|
||||
@@ -67,14 +67,14 @@ private extension FeedTreeControllerDelegate {
|
||||
var children = [AnyObject]()
|
||||
|
||||
for webFeed in container.topLevelWebFeeds {
|
||||
if let feedID = webFeed.feedID, !(!filterExceptions.contains(feedID) && isReadFiltered && webFeed.unreadCount == 0) {
|
||||
if let itemID = webFeed.itemID, !(!filterExceptions.contains(itemID) && isReadFiltered && webFeed.unreadCount == 0) {
|
||||
children.append(webFeed)
|
||||
}
|
||||
}
|
||||
|
||||
if let folders = container.folders {
|
||||
for folder in folders {
|
||||
if let feedID = folder.feedID, !(!filterExceptions.contains(feedID) && isReadFiltered && folder.unreadCount == 0) {
|
||||
if let itemID = folder.itemID, !(!filterExceptions.contains(itemID) && isReadFiltered && folder.unreadCount == 0) {
|
||||
children.append(folder)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ struct UserInfoKey {
|
||||
static let webFeed = "webFeed"
|
||||
static let url = "url"
|
||||
static let articlePath = "articlePath"
|
||||
static let feedIdentifier = "feedIdentifier"
|
||||
static let itemIdentifier = "itemIdentifier"
|
||||
|
||||
static let windowState = "windowState"
|
||||
static let windowFullScreenState = "windowFullScreenState"
|
||||
|
||||
@@ -39,7 +39,7 @@ enum ShowFeedName {
|
||||
|
||||
struct FeedNode: Hashable {
|
||||
var node: Node
|
||||
var feedID: FeedIdentifier
|
||||
var itemID: ItemIdentifier
|
||||
|
||||
init?(_ node: Node) {
|
||||
guard let feed = node.representedObject as? FeedProtocol else { return nil }
|
||||
@@ -81,7 +81,7 @@ final class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
private var lastExpandedTable = Set<ContainerIdentifier>()
|
||||
|
||||
// Which Feeds have the Read Articles Filter enabled
|
||||
private var readFilterEnabledTable = [FeedIdentifier: Bool]()
|
||||
private var readFilterEnabledTable = [ItemIdentifier: Bool]()
|
||||
|
||||
// Flattened tree structure for the Sidebar
|
||||
private var shadowTable = [(sectionID: String, feedNodes: [FeedNode])]()
|
||||
@@ -345,8 +345,8 @@ final class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
|
||||
if let readArticlesFilterState = windowState[UserInfoKey.readArticlesFilterState] as? [[AnyHashable: AnyHashable]: Bool] {
|
||||
for key in readArticlesFilterState.keys {
|
||||
if let feedIdentifier = FeedIdentifier(userInfo: key) {
|
||||
readFilterEnabledTable[feedIdentifier] = readArticlesFilterState[key]
|
||||
if let itemIdentifier = ItemIdentifier(userInfo: key) {
|
||||
readFilterEnabledTable[itemIdentifier] = readArticlesFilterState[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,10 +618,10 @@ final class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
refreshTimeline(resetScroll: false)
|
||||
}
|
||||
|
||||
func nodeFor(feedID: FeedIdentifier) -> Node? {
|
||||
func nodeFor(itemID: ItemIdentifier) -> Node? {
|
||||
return treeController.rootNode.descendantNode(where: { node in
|
||||
if let feed = node.representedObject as? FeedProtocol {
|
||||
return feed.feedID == feedID
|
||||
return feed.itemID == itemID
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@@ -2129,17 +2129,17 @@ private extension SceneCoordinator {
|
||||
|
||||
func handleSelectFeed(_ userInfo: [AnyHashable : Any]?) {
|
||||
guard let userInfo = userInfo,
|
||||
let feedIdentifierUserInfo = userInfo[UserInfoKey.feedIdentifier] as? [AnyHashable : AnyHashable],
|
||||
let feedIdentifier = FeedIdentifier(userInfo: feedIdentifierUserInfo) else {
|
||||
let itemIdentifierUserInfo = userInfo[UserInfoKey.itemIdentifier] as? [AnyHashable : AnyHashable],
|
||||
let itemIdentifier = ItemIdentifier(userInfo: itemIdentifierUserInfo) else {
|
||||
return
|
||||
}
|
||||
|
||||
treeControllerDelegate.addFilterException(feedIdentifier)
|
||||
treeControllerDelegate.addFilterException(itemIdentifier)
|
||||
|
||||
switch feedIdentifier {
|
||||
switch itemIdentifier {
|
||||
|
||||
case .smartFeed:
|
||||
guard let smartFeed = SmartFeedsController.shared.find(by: feedIdentifier) else { return }
|
||||
guard let smartFeed = SmartFeedsController.shared.find(by: itemIdentifier) else { return }
|
||||
|
||||
markExpanded(SmartFeedsController.shared)
|
||||
rebuildBackingStores(initialLoad: true, completion: {
|
||||
@@ -2214,31 +2214,31 @@ private extension SceneCoordinator {
|
||||
}
|
||||
|
||||
func restoreFeedSelection(_ userInfo: [AnyHashable : Any], accountID: String, webFeedID: String, articleID: String) -> Bool {
|
||||
guard let feedIdentifierUserInfo = userInfo[UserInfoKey.feedIdentifier] as? [AnyHashable : AnyHashable],
|
||||
let feedIdentifier = FeedIdentifier(userInfo: feedIdentifierUserInfo),
|
||||
guard let itemIdentifierUserInfo = userInfo[UserInfoKey.itemIdentifier] as? [AnyHashable : AnyHashable],
|
||||
let itemIdentifier = ItemIdentifier(userInfo: itemIdentifierUserInfo),
|
||||
let isShowingExtractedArticle = userInfo[UserInfoKey.isShowingExtractedArticle] as? Bool,
|
||||
let articleWindowScrollY = userInfo[UserInfoKey.articleWindowScrollY] as? Int else {
|
||||
return false
|
||||
}
|
||||
|
||||
switch feedIdentifier {
|
||||
switch itemIdentifier {
|
||||
|
||||
case .script:
|
||||
return false
|
||||
|
||||
case .smartFeed, .folder:
|
||||
let found = selectFeedAndArticle(feedIdentifier: feedIdentifier, articleID: articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)
|
||||
let found = selectFeedAndArticle(itemIdentifier: itemIdentifier, articleID: articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)
|
||||
if found {
|
||||
treeControllerDelegate.addFilterException(feedIdentifier)
|
||||
treeControllerDelegate.addFilterException(itemIdentifier)
|
||||
}
|
||||
return found
|
||||
|
||||
case .webFeed:
|
||||
let found = selectFeedAndArticle(feedIdentifier: feedIdentifier, articleID: articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)
|
||||
let found = selectFeedAndArticle(itemIdentifier: itemIdentifier, articleID: articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)
|
||||
if found {
|
||||
treeControllerDelegate.addFilterException(feedIdentifier)
|
||||
if let webFeedNode = nodeFor(feedID: feedIdentifier), let folder = webFeedNode.parent?.representedObject as? Folder, let folderFeedID = folder.feedID {
|
||||
treeControllerDelegate.addFilterException(folderFeedID)
|
||||
treeControllerDelegate.addFilterException(itemIdentifier)
|
||||
if let webFeedNode = nodeFor(itemID: itemIdentifier), let folder = webFeedNode.parent?.representedObject as? Folder, let folderItemID = folder.itemID {
|
||||
treeControllerDelegate.addFilterException(folderItemID)
|
||||
}
|
||||
}
|
||||
return found
|
||||
@@ -2273,8 +2273,8 @@ private extension SceneCoordinator {
|
||||
return nil
|
||||
}
|
||||
|
||||
func selectFeedAndArticle(feedIdentifier: FeedIdentifier, articleID: String, isShowingExtractedArticle: Bool, articleWindowScrollY: Int) -> Bool {
|
||||
guard let feedNode = nodeFor(feedID: feedIdentifier), let feedIndexPath = indexPathFor(feedNode) else { return false }
|
||||
func selectFeedAndArticle(itemIdentifier: ItemIdentifier, articleID: String, isShowingExtractedArticle: Bool, articleWindowScrollY: Int) -> Bool {
|
||||
guard let feedNode = nodeFor(itemID: itemIdentifier), let feedIndexPath = indexPathFor(feedNode) else { return false }
|
||||
|
||||
selectFeed(indexPath: feedIndexPath) {
|
||||
self.selectArticleInCurrentFeed(articleID, isShowingExtractedArticle: isShowingExtractedArticle, articleWindowScrollY: articleWindowScrollY)
|
||||
|
||||
Reference in New Issue
Block a user