mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2024-12-24 16:51:19 +01:00
Optimize table cell reloading when feed images are made available
This commit is contained in:
parent
c3aebe7868
commit
1a3e2784ae
@ -164,8 +164,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||||||
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(avatarDidBecomeAvailable(_:)), name: .AvatarDidBecomeAvailable, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(avatarDidBecomeAvailable(_:)), name: .AvatarDidBecomeAvailable, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(accountDidDownloadArticles(_:)), name: .AccountDidDownloadArticles, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(accountDidDownloadArticles(_:)), name: .AccountDidDownloadArticles, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(accountStateDidChange(_:)), name: .AccountStateDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(accountStateDidChange(_:)), name: .AccountStateDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .AccountsDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .AccountsDidChange, object: nil)
|
||||||
@ -475,7 +474,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||||||
|
|
||||||
@objc func feedIconDidBecomeAvailable(_ note: Notification) {
|
@objc func feedIconDidBecomeAvailable(_ note: Notification) {
|
||||||
|
|
||||||
guard let feed = note.userInfo?[UserInfoKey.feed] as? Feed else {
|
guard showAvatars, let feed = note.userInfo?[UserInfoKey.feed] as? Feed else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let indexesToReload = tableView.indexesOfAvailableRowsPassingTest { (row) -> Bool in
|
let indexesToReload = tableView.indexesOfAvailableRowsPassingTest { (row) -> Bool in
|
||||||
@ -511,10 +510,19 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func imageDidBecomeAvailable(_ note: Notification) {
|
@objc func faviconDidBecomeAvailable(_ note: Notification) {
|
||||||
|
guard showAvatars, let faviconURL = note.userInfo?[FaviconDownloader.UserInfoKey.faviconURL] as? String else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if showAvatars {
|
let indexesToReload = tableView.indexesOfAvailableRowsPassingTest { (row) -> Bool in
|
||||||
queueReloadAvailableCells()
|
guard let article = articles.articleAtRow(row) else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return article.feed?.faviconURL == faviconURL
|
||||||
|
}
|
||||||
|
if let indexesToReload = indexesToReload {
|
||||||
|
reloadCells(for: indexesToReload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,10 +25,11 @@ public final class FeedIconDownloader {
|
|||||||
private var homePagesWithNoIconURL = Set<String>()
|
private var homePagesWithNoIconURL = Set<String>()
|
||||||
private var urlsInProgress = Set<String>()
|
private var urlsInProgress = Set<String>()
|
||||||
private var cache = [Feed: RSImage]()
|
private var cache = [Feed: RSImage]()
|
||||||
|
private var waitingForFeedURLs = [String: Feed]()
|
||||||
|
|
||||||
init(imageDownloader: ImageDownloader) {
|
init(imageDownloader: ImageDownloader) {
|
||||||
|
|
||||||
self.imageDownloader = imageDownloader
|
self.imageDownloader = imageDownloader
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: imageDownloader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetCache() {
|
func resetCache() {
|
||||||
@ -45,7 +46,7 @@ public final class FeedIconDownloader {
|
|||||||
guard let homePageURL = feed.homePageURL else {
|
guard let homePageURL = feed.homePageURL else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
icon(forHomePageURL: homePageURL) { (image) in
|
icon(forHomePageURL: homePageURL, feed: feed) { (image) in
|
||||||
if let image = image {
|
if let image = image {
|
||||||
self.postFeedIconDidBecomeAvailableNotification(feed)
|
self.postFeedIconDidBecomeAvailableNotification(feed)
|
||||||
self.cache[feed] = image
|
self.cache[feed] = image
|
||||||
@ -54,7 +55,7 @@ public final class FeedIconDownloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let iconURL = feed.iconURL {
|
if let iconURL = feed.iconURL {
|
||||||
icon(forURL: iconURL) { (image) in
|
icon(forURL: iconURL, feed: feed) { (image) in
|
||||||
if let image = image {
|
if let image = image {
|
||||||
self.postFeedIconDidBecomeAvailableNotification(feed)
|
self.postFeedIconDidBecomeAvailableNotification(feed)
|
||||||
self.cache[feed] = image
|
self.cache[feed] = image
|
||||||
@ -71,11 +72,20 @@ public final class FeedIconDownloader {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func imageDidBecomeAvailable(_ note: Notification) {
|
||||||
|
guard let url = note.userInfo?[UserInfoKey.url] as? String, let feed = waitingForFeedURLs[url] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
waitingForFeedURLs[url] = nil
|
||||||
|
_ = icon(for: feed)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension FeedIconDownloader {
|
private extension FeedIconDownloader {
|
||||||
|
|
||||||
func icon(forHomePageURL homePageURL: String, _ imageResultBlock: @escaping (RSImage?) -> Void) {
|
func icon(forHomePageURL homePageURL: String, feed: Feed, _ imageResultBlock: @escaping (RSImage?) -> Void) {
|
||||||
|
|
||||||
if homePagesWithNoIconURL.contains(homePageURL) {
|
if homePagesWithNoIconURL.contains(homePageURL) {
|
||||||
imageResultBlock(nil)
|
imageResultBlock(nil)
|
||||||
@ -83,14 +93,15 @@ private extension FeedIconDownloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let iconURL = cachedIconURL(for: homePageURL) {
|
if let iconURL = cachedIconURL(for: homePageURL) {
|
||||||
icon(forURL: iconURL, imageResultBlock)
|
icon(forURL: iconURL, feed: feed, imageResultBlock)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
findIconURLForHomePageURL(homePageURL)
|
findIconURLForHomePageURL(homePageURL, feed: feed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func icon(forURL url: String, _ imageResultBlock: @escaping (RSImage?) -> Void) {
|
func icon(forURL url: String, feed: Feed, _ imageResultBlock: @escaping (RSImage?) -> Void) {
|
||||||
|
waitingForFeedURLs[url] = feed
|
||||||
guard let imageData = imageDownloader.image(for: url) else {
|
guard let imageData = imageDownloader.image(for: url) else {
|
||||||
imageResultBlock(nil)
|
imageResultBlock(nil)
|
||||||
return
|
return
|
||||||
@ -117,7 +128,7 @@ private extension FeedIconDownloader {
|
|||||||
homePageToIconURLCache[homePageURL] = iconURL
|
homePageToIconURLCache[homePageURL] = iconURL
|
||||||
}
|
}
|
||||||
|
|
||||||
func findIconURLForHomePageURL(_ homePageURL: String) {
|
func findIconURLForHomePageURL(_ homePageURL: String, feed: Feed) {
|
||||||
|
|
||||||
guard !urlsInProgress.contains(homePageURL) else {
|
guard !urlsInProgress.contains(homePageURL) else {
|
||||||
return
|
return
|
||||||
@ -130,15 +141,15 @@ private extension FeedIconDownloader {
|
|||||||
guard let metadata = metadata else {
|
guard let metadata = metadata else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.pullIconURL(from: metadata, homePageURL: homePageURL)
|
self.pullIconURL(from: metadata, homePageURL: homePageURL, feed: feed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pullIconURL(from metadata: RSHTMLMetadata, homePageURL: String) {
|
func pullIconURL(from metadata: RSHTMLMetadata, homePageURL: String, feed: Feed) {
|
||||||
|
|
||||||
if let url = metadata.bestWebsiteIconURL() {
|
if let url = metadata.bestWebsiteIconURL() {
|
||||||
cacheIconURL(for: homePageURL, url)
|
cacheIconURL(for: homePageURL, url)
|
||||||
icon(forURL: url) { (image) in
|
icon(forURL: url, feed: feed) { (image) in
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user