mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2024-12-20 14:33:04 +01:00
Add a cache to HTMLMetadataDownloader; do all parsing off the main thread, for better UI performance. Also: make FaviconURLFinder use HTMLMetadataDownloader, as it should have in the first place.
This commit is contained in:
parent
e091f1c609
commit
81d8532e2c
@ -8,64 +8,20 @@
|
||||
|
||||
import Foundation
|
||||
import RSParser
|
||||
import RSWeb
|
||||
import RSCore
|
||||
|
||||
// The favicon URL may be specified in the head section of the home page.
|
||||
|
||||
struct FaviconURLFinder {
|
||||
|
||||
static var metadataCache = [String: RSHTMLMetadata]()
|
||||
static let serialDispatchQueue = DispatchQueue(label: "FaviconURLFinder")
|
||||
|
||||
static func findFaviconURL(_ homePageURL: String, _ callback: @escaping (String?) -> Void) {
|
||||
|
||||
guard let url = URL(string: homePageURL) else {
|
||||
guard let _ = URL(string: homePageURL) else {
|
||||
callback(nil)
|
||||
return
|
||||
}
|
||||
|
||||
downloadUsingCache(url) { (data, response, error) in
|
||||
|
||||
guard let data = data, let response = response, response.statusIsOK else {
|
||||
callback(nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Use the absoluteString of the response’s URL instead of the homePageURL,
|
||||
// since the homePageURL might actually have been redirected.
|
||||
// Example: Dr. Drang’s feed reports the homePageURL as http://www.leancrew.com/all-this —
|
||||
// but it gets redirected to http://www.leancrew.com/all-this/ — which is correct.
|
||||
// This way any relative link to a favicon in the page’s metadata
|
||||
// will be made absolute correctly.
|
||||
|
||||
let urlToUse = response.url?.absoluteString ?? homePageURL
|
||||
faviconURL(urlToUse, data, callback)
|
||||
}
|
||||
}
|
||||
|
||||
static private func faviconURL(_ url: String, _ webPageData: Data, _ callback: @escaping (String?) -> Void) {
|
||||
|
||||
serialDispatchQueue.async {
|
||||
|
||||
let md5String = (webPageData as NSData).rs_md5HashString()
|
||||
if let md5String = md5String, let cachedMetadata = metadataCache[md5String] {
|
||||
let cachedURL = cachedMetadata.faviconLink
|
||||
DispatchQueue.main.async {
|
||||
callback(cachedURL)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let parserData = ParserData(url: url, data: webPageData)
|
||||
let htmlMetadata = RSHTMLMetadataParser.htmlMetadata(with: parserData)
|
||||
if let md5String = md5String {
|
||||
metadataCache[md5String] = htmlMetadata
|
||||
}
|
||||
let url = htmlMetadata.faviconLink
|
||||
DispatchQueue.main.async {
|
||||
callback(url)
|
||||
}
|
||||
HTMLMetadataDownloader.downloadMetadata(for: homePageURL) { (htmlMetadata) in
|
||||
callback(htmlMetadata?.faviconLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ import RSParser
|
||||
|
||||
struct HTMLMetadataDownloader {
|
||||
|
||||
static var metadataCache = [String: RSHTMLMetadata]()
|
||||
static let serialDispatchQueue = DispatchQueue(label: "HTMLMetadataDownloader")
|
||||
|
||||
static func downloadMetadata(for url: String, _ callback: @escaping (RSHTMLMetadata?) -> Void) {
|
||||
|
||||
guard let actualURL = URL(string: url) else {
|
||||
@ -25,8 +28,7 @@ struct HTMLMetadataDownloader {
|
||||
|
||||
let urlToUse = response.url ?? actualURL
|
||||
let parserData = ParserData(url: urlToUse.absoluteString, data: data)
|
||||
let metadata = RSHTMLMetadataParser.htmlMetadata(with: parserData)
|
||||
callback(metadata)
|
||||
parseMetadata(with: parserData, callback)
|
||||
return
|
||||
}
|
||||
|
||||
@ -37,4 +39,27 @@ struct HTMLMetadataDownloader {
|
||||
callback(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private static func parseMetadata(with parserData: ParserData, _ callback: @escaping (RSHTMLMetadata?) -> Void) {
|
||||
|
||||
serialDispatchQueue.async {
|
||||
|
||||
let md5String = (parserData.data as NSData).rs_md5HashString()
|
||||
if let md5String = md5String, let cachedMetadata = metadataCache[md5String] {
|
||||
DispatchQueue.main.async {
|
||||
callback(cachedMetadata)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let htmlMetadata = RSHTMLMetadataParser.htmlMetadata(with: parserData)
|
||||
if let md5String = md5String {
|
||||
metadataCache[md5String] = htmlMetadata
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
callback(htmlMetadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user