// // FeaturedImageDownloader.swift // NetNewsWire // // Created by Brent Simmons on 11/26/17. // Copyright © 2017 Ranchero Software. All rights reserved. // import Foundation import Articles import RSCore import RSParser final class FeaturedImageDownloader { private let imageDownloader: ImageDownloader private var articleURLToFeaturedImageURLCache = [String: String]() private var articleURLsWithNoFeaturedImage = Set() private var urlsInProgress = Set() init(imageDownloader: ImageDownloader) { self.imageDownloader = imageDownloader } func image(for article: Article) -> RSImage? { if let url = article.imageURL { return image(forFeaturedImageURL: url) } if let articleURL = article.url { return image(forArticleURL: articleURL) } return nil } func image(forArticleURL articleURL: String) -> RSImage? { if articleURLsWithNoFeaturedImage.contains(articleURL) { return nil } if let featuredImageURL = cachedURL(for: articleURL) { return image(forFeaturedImageURL: featuredImageURL) } findFeaturedImageURL(for: articleURL) return nil } func image(forFeaturedImageURL featuredImageURL: String) -> RSImage? { if let data = imageDownloader.image(for: featuredImageURL) { return RSImage(data: data) } return nil } } private extension FeaturedImageDownloader { func cachedURL(for articleURL: String) -> String? { return articleURLToFeaturedImageURLCache[articleURL] } func cacheURL(for articleURL: String, _ featuredImageURL: String) { articleURLsWithNoFeaturedImage.remove(articleURL) articleURLToFeaturedImageURLCache[articleURL] = featuredImageURL } func findFeaturedImageURL(for articleURL: String) { guard !urlsInProgress.contains(articleURL) else { return } urlsInProgress.insert(articleURL) HTMLMetadataDownloader.downloadMetadata(for: articleURL) { (metadata) in self.urlsInProgress.remove(articleURL) guard let metadata = metadata else { return } self.pullFeaturedImageURL(from: metadata, articleURL: articleURL) } } func pullFeaturedImageURL(from metadata: RSHTMLMetadata, articleURL: String) { if let url = metadata.bestFeaturedImageURL() { cacheURL(for: articleURL, url) let _ = image(forFeaturedImageURL: url) return } articleURLsWithNoFeaturedImage.insert(articleURL) } }