diff --git a/Evergreen/FeedList/FeedListFeed.swift b/Evergreen/FeedList/FeedListFeed.swift index 8a0b658ad..017f32bfb 100644 --- a/Evergreen/FeedList/FeedListFeed.swift +++ b/Evergreen/FeedList/FeedListFeed.swift @@ -8,6 +8,13 @@ import Foundation import RSCore +import RSParser +import RSWeb + +extension Notification.Name { + + public static let FeedListFeedDidBecomeAvailable = Notification.Name(rawValue: "FeedListFeedDidBecomeAvailable") +} final class FeedListFeed: Hashable, DisplayNameProvider { @@ -15,6 +22,13 @@ final class FeedListFeed: Hashable, DisplayNameProvider { let url: String let homePageURL: String let hashValue: Int + var lastDownloadAttemptDate: Date? = nil + + var parsedFeed: ParsedFeed? = nil { + didSet { + postFeedListFeedDidBecomeAvailableNotification() + } + } var nameForDisplay: String { // DisplayNameProvider get { @@ -46,8 +60,52 @@ final class FeedListFeed: Hashable, DisplayNameProvider { self.init(name: name, url: url, homePageURL: homePageURL) } + func downloadIfNeeded() { + + guard let lastDownloadAttemptDate = lastDownloadAttemptDate else { + downloadFeed() + return + } + + let cutoffDate = Date().addingTimeInterval(-(30 * 60)) // 30 minutes in the past + if lastDownloadAttemptDate < cutoffDate { + downloadFeed() + } + } + static func ==(lhs: FeedListFeed, rhs: FeedListFeed) -> Bool { return lhs.hashValue == rhs.hashValue && lhs.url == rhs.url && lhs.name == rhs.name && lhs.homePageURL == rhs.homePageURL } } + +private extension FeedListFeed { + + func postFeedListFeedDidBecomeAvailableNotification() { + + NotificationCenter.default.post(name: .FeedListFeedDidBecomeAvailable, object: self, userInfo: nil) + } + + func downloadFeed() { + + lastDownloadAttemptDate = Date() + guard let feedURL = URL(string: url) else { + return + } + + downloadUsingCache(feedURL) { (data, response, error) in + + guard let data = data, error == nil else { + return + } + + let parserData = ParserData(url: self.url, data: data) + FeedParser.parse(parserData) { (parsedFeed, error) in + + if let parsedFeed = parsedFeed, parsedFeed.items.count > 0 { + self.parsedFeed = parsedFeed + } + } + } + } +} diff --git a/Evergreen/FeedList/FeedListTimelineViewController.swift b/Evergreen/FeedList/FeedListTimelineViewController.swift index 29bcacbbc..534a62410 100644 --- a/Evergreen/FeedList/FeedListTimelineViewController.swift +++ b/Evergreen/FeedList/FeedListTimelineViewController.swift @@ -10,8 +10,47 @@ import Cocoa final class FeedListTimelineViewController: NSViewController { + var selectedFeed: FeedListFeed? = nil { + didSet { + if let selectedFeed = selectedFeed { + selectedFeed.downloadIfNeeded() + } + } + } + override func viewDidLoad() { view.translatesAutoresizingMaskIntoConstraints = false + + NotificationCenter.default.addObserver(self, selector: #selector(sidebarSelectionDidChange(_:)), name: .FeedListSidebarSelectionDidChange, object: nil) + + NotificationCenter.default.addObserver(self, selector: #selector(feedDidBecomeAvailable(_:)), name: .FeedListFeedDidBecomeAvailable, object: nil) + } + + @objc func feedDidBecomeAvailable(_ note: Notification) { + + guard let feed = note.object as? FeedListFeed else { + return + } + + if feed == selectedFeed { + reloadTimeline() + } + } + + @objc func sidebarSelectionDidChange(_ note: Notification) { + + guard let feed = note.userInfo?[FeedListUserInfoKey.selectedObject] as? FeedListFeed else { + selectedFeed = nil + return + } + selectedFeed = feed + } +} + +private extension FeedListTimelineViewController { + + func reloadTimeline() { + // } } diff --git a/Evergreen/FeedList/FeedListViewController.swift b/Evergreen/FeedList/FeedListViewController.swift index ca295dd04..ef1c0abda 100644 --- a/Evergreen/FeedList/FeedListViewController.swift +++ b/Evergreen/FeedList/FeedListViewController.swift @@ -10,6 +10,16 @@ import Cocoa import RSTree import RSCore +extension Notification.Name { + + static let FeedListSidebarSelectionDidChange = Notification.Name(rawValue: "FeedListSidebarSelectionDidChange") +} + +struct FeedListUserInfoKey { + + static let selectedObject = "selectedObject" +} + final class FeedListViewController: NSViewController { @IBOutlet var outlineView: NSOutlineView! @@ -82,18 +92,16 @@ extension FeedListViewController: NSOutlineViewDelegate { func outlineViewSelectionDidChange(_ notification: Notification) { -// // TODO: support multiple selection -// -// let selectedRow = self.outlineView.selectedRow -// -// if selectedRow < 0 || selectedRow == NSNotFound { -// postSidebarSelectionDidChangeNotification(nil) -// return -// } -// -// if let selectedNode = self.outlineView.item(atRow: selectedRow) as? Node { -// postSidebarSelectionDidChangeNotification([selectedNode.representedObject]) -// } + let selectedRow = self.outlineView.selectedRow + + if selectedRow < 0 || selectedRow == NSNotFound { + postSidebarSelectionDidChangeNotification(nil) + return + } + + if let selectedNode = self.outlineView.item(atRow: selectedRow) as? Node { + postSidebarSelectionDidChangeNotification(selectedNode.representedObject) + } } private func configure(_ cell: SidebarCell, _ node: Node) { @@ -157,4 +165,15 @@ private extension FeedListViewController { configure(cell, node) } } + + func postSidebarSelectionDidChangeNotification(_ selectedObject: Any?) { + + var userInfo = [AnyHashable: Any]() + + if let selectedObject = selectedObject { + userInfo[FeedListUserInfoKey.selectedObject] = selectedObject + } + + NotificationCenter.default.post(name: .FeedListSidebarSelectionDidChange, object: self, userInfo: userInfo) + } }