Create .shared of FaviconDownloader, AuthorAvatarDownloader, FeedIconDownloader, and ImageDownloader.
This commit is contained in:
parent
840147aee3
commit
8cd69d7509
|
@ -17,13 +17,12 @@ public extension Notification.Name {
|
||||||
|
|
||||||
@MainActor public final class AuthorAvatarDownloader {
|
@MainActor public final class AuthorAvatarDownloader {
|
||||||
|
|
||||||
private let imageDownloader: ImageDownloader
|
public static let shared = AuthorAvatarDownloader()
|
||||||
|
private let imageDownloader = ImageDownloader.shared
|
||||||
private var cache = [String: IconImage]() // avatarURL: RSImage
|
private var cache = [String: IconImage]() // avatarURL: RSImage
|
||||||
private var waitingForAvatarURLs = Set<String>()
|
private var waitingForAvatarURLs = Set<String>()
|
||||||
|
|
||||||
public init(imageDownloader: ImageDownloader) {
|
init() {
|
||||||
|
|
||||||
self.imageDownloader = imageDownloader
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: imageDownloader)
|
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: imageDownloader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import Account
|
||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
import Core
|
import Core
|
||||||
import ParserObjC
|
import ParserObjC
|
||||||
|
import AppConfig
|
||||||
|
|
||||||
public extension Notification.Name {
|
public extension Notification.Name {
|
||||||
static let FaviconDidBecomeAvailable = Notification.Name("FaviconDidBecomeAvailableNotification") // userInfo key: FaviconDownloader.UserInfoKey.faviconURL
|
static let FaviconDidBecomeAvailable = Notification.Name("FaviconDidBecomeAvailableNotification") // userInfo key: FaviconDownloader.UserInfoKey.faviconURL
|
||||||
|
@ -27,16 +28,18 @@ public protocol FaviconDownloaderDelegate {
|
||||||
|
|
||||||
@MainActor public final class FaviconDownloader {
|
@MainActor public final class FaviconDownloader {
|
||||||
|
|
||||||
|
public static let shared = FaviconDownloader()
|
||||||
|
|
||||||
private static let saveQueue = CoalescingQueue(name: "Cache Save Queue", interval: 1.0)
|
private static let saveQueue = CoalescingQueue(name: "Cache Save Queue", interval: 1.0)
|
||||||
|
|
||||||
private let folder: String
|
private let folder: URL
|
||||||
private let diskCache: BinaryDiskCache
|
private let diskCache: BinaryDiskCache
|
||||||
private var singleFaviconDownloaderCache = [String: SingleFaviconDownloader]() // faviconURL: SingleFaviconDownloader
|
private var singleFaviconDownloaderCache = [String: SingleFaviconDownloader]() // faviconURL: SingleFaviconDownloader
|
||||||
private var remainingFaviconURLs = [String: ArraySlice<String>]() // homePageURL: array of faviconURLs that haven't been checked yet
|
private var remainingFaviconURLs = [String: ArraySlice<String>]() // homePageURL: array of faviconURLs that haven't been checked yet
|
||||||
private var currentHomePageHasOnlyFaviconICO = false
|
private var currentHomePageHasOnlyFaviconICO = false
|
||||||
|
|
||||||
private var homePageToFaviconURLCache = [String: String]() //homePageURL: faviconURL
|
private var homePageToFaviconURLCache = [String: String]() //homePageURL: faviconURL
|
||||||
private var homePageToFaviconURLCachePath: String
|
private var homePageToFaviconURLCachePath: URL
|
||||||
private var homePageToFaviconURLCacheDirty = false {
|
private var homePageToFaviconURLCacheDirty = false {
|
||||||
didSet {
|
didSet {
|
||||||
queueSaveHomePageToFaviconURLCacheIfNeeded()
|
queueSaveHomePageToFaviconURLCacheIfNeeded()
|
||||||
|
@ -44,7 +47,7 @@ public protocol FaviconDownloaderDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
private var homePageURLsWithNoFaviconURLCache = Set<String>()
|
private var homePageURLsWithNoFaviconURLCache = Set<String>()
|
||||||
private var homePageURLsWithNoFaviconURLCachePath: String
|
private var homePageURLsWithNoFaviconURLCachePath: URL
|
||||||
private var homePageURLsWithNoFaviconURLCacheDirty = false {
|
private var homePageURLsWithNoFaviconURLCacheDirty = false {
|
||||||
didSet {
|
didSet {
|
||||||
queueSaveHomePageURLsWithNoFaviconURLCacheIfNeeded()
|
queueSaveHomePageURLsWithNoFaviconURLCacheIfNeeded()
|
||||||
|
@ -60,14 +63,14 @@ public protocol FaviconDownloaderDelegate {
|
||||||
static let faviconURL = "faviconURL"
|
static let faviconURL = "faviconURL"
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(folder: String) {
|
public init() {
|
||||||
|
|
||||||
self.folder = folder
|
self.folder = AppLocations.faviconsFolder
|
||||||
self.diskCache = BinaryDiskCache(folder: folder)
|
self.diskCache = BinaryDiskCache(folder: folder.path)
|
||||||
self.queue = DispatchQueue(label: "FaviconDownloader serial queue - \(folder)")
|
self.queue = DispatchQueue(label: "FaviconDownloader serial queue - \(folder)")
|
||||||
|
|
||||||
self.homePageToFaviconURLCachePath = (folder as NSString).appendingPathComponent("HomePageToFaviconURLCache.plist")
|
self.homePageToFaviconURLCachePath = folder.appendingPathComponent("HomePageToFaviconURLCache.plist")
|
||||||
self.homePageURLsWithNoFaviconURLCachePath = (folder as NSString).appendingPathComponent("HomePageURLsWithNoFaviconURLCache.plist")
|
self.homePageURLsWithNoFaviconURLCachePath = folder.appendingPathComponent("HomePageURLsWithNoFaviconURLCache.plist")
|
||||||
loadHomePageToFaviconURLCache()
|
loadHomePageToFaviconURLCache()
|
||||||
loadHomePageURLsWithNoFaviconURLCache()
|
loadHomePageURLsWithNoFaviconURLCache()
|
||||||
|
|
||||||
|
@ -262,8 +265,7 @@ private extension FaviconDownloader {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadHomePageToFaviconURLCache() {
|
func loadHomePageToFaviconURLCache() {
|
||||||
let url = URL(fileURLWithPath: homePageToFaviconURLCachePath)
|
guard let data = try? Data(contentsOf: homePageToFaviconURLCachePath) else {
|
||||||
guard let data = try? Data(contentsOf: url) else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let decoder = PropertyListDecoder()
|
let decoder = PropertyListDecoder()
|
||||||
|
@ -271,8 +273,7 @@ private extension FaviconDownloader {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadHomePageURLsWithNoFaviconURLCache() {
|
func loadHomePageURLsWithNoFaviconURLCache() {
|
||||||
let url = URL(fileURLWithPath: homePageURLsWithNoFaviconURLCachePath)
|
guard let data = try? Data(contentsOf: homePageURLsWithNoFaviconURLCachePath) else {
|
||||||
guard let data = try? Data(contentsOf: url) else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let decoder = PropertyListDecoder()
|
let decoder = PropertyListDecoder()
|
||||||
|
@ -297,10 +298,9 @@ private extension FaviconDownloader {
|
||||||
|
|
||||||
let encoder = PropertyListEncoder()
|
let encoder = PropertyListEncoder()
|
||||||
encoder.outputFormat = .binary
|
encoder.outputFormat = .binary
|
||||||
let url = URL(fileURLWithPath: homePageToFaviconURLCachePath)
|
|
||||||
do {
|
do {
|
||||||
let data = try encoder.encode(homePageToFaviconURLCache)
|
let data = try encoder.encode(homePageToFaviconURLCache)
|
||||||
try data.write(to: url)
|
try data.write(to: homePageToFaviconURLCachePath)
|
||||||
} catch {
|
} catch {
|
||||||
assertionFailure(error.localizedDescription)
|
assertionFailure(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
@ -311,10 +311,9 @@ private extension FaviconDownloader {
|
||||||
|
|
||||||
let encoder = PropertyListEncoder()
|
let encoder = PropertyListEncoder()
|
||||||
encoder.outputFormat = .binary
|
encoder.outputFormat = .binary
|
||||||
let url = URL(fileURLWithPath: homePageURLsWithNoFaviconURLCachePath)
|
|
||||||
do {
|
do {
|
||||||
let data = try encoder.encode(Array(homePageURLsWithNoFaviconURLCache))
|
let data = try encoder.encode(Array(homePageURLsWithNoFaviconURLCache))
|
||||||
try data.write(to: url)
|
try data.write(to: homePageURLsWithNoFaviconURLCachePath)
|
||||||
} catch {
|
} catch {
|
||||||
assertionFailure(error.localizedDescription)
|
assertionFailure(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,13 @@ public protocol FeedIconDownloaderDelegate: Sendable {
|
||||||
|
|
||||||
@MainActor public final class FeedIconDownloader {
|
@MainActor public final class FeedIconDownloader {
|
||||||
|
|
||||||
|
public static let shared = FeedIconDownloader()
|
||||||
|
|
||||||
public static let feedKey = "url"
|
public static let feedKey = "url"
|
||||||
|
|
||||||
private static let saveQueue = CoalescingQueue(name: "Cache Save Queue", interval: 1.0)
|
private static let saveQueue = CoalescingQueue(name: "Cache Save Queue", interval: 1.0)
|
||||||
|
|
||||||
private let imageDownloader: ImageDownloader
|
private let imageDownloader = ImageDownloader.shared
|
||||||
|
|
||||||
private var feedURLToIconURLCache = [String: String]()
|
private var feedURLToIconURLCache = [String: String]()
|
||||||
private var feedURLToIconURLCachePath: String
|
private var feedURLToIconURLCachePath: String
|
||||||
|
@ -68,8 +70,8 @@ public protocol FeedIconDownloaderDelegate: Sendable {
|
||||||
|
|
||||||
public var delegate: FeedIconDownloaderDelegate?
|
public var delegate: FeedIconDownloaderDelegate?
|
||||||
|
|
||||||
public init(imageDownloader: ImageDownloader, folder: String) {
|
public init(folder: String) {
|
||||||
self.imageDownloader = imageDownloader
|
|
||||||
self.feedURLToIconURLCachePath = (folder as NSString).appendingPathComponent("FeedURLToIconURLCache.plist")
|
self.feedURLToIconURLCachePath = (folder as NSString).appendingPathComponent("FeedURLToIconURLCache.plist")
|
||||||
self.homePageToIconURLCachePath = (folder as NSString).appendingPathComponent("HomePageToIconURLCache.plist")
|
self.homePageToIconURLCachePath = (folder as NSString).appendingPathComponent("HomePageToIconURLCache.plist")
|
||||||
self.homePagesWithNoIconURLCachePath = (folder as NSString).appendingPathComponent("HomePagesWithNoIconURLCache.plist")
|
self.homePagesWithNoIconURLCachePath = (folder as NSString).appendingPathComponent("HomePagesWithNoIconURLCache.plist")
|
||||||
|
|
|
@ -11,6 +11,7 @@ import os.log
|
||||||
import Web
|
import Web
|
||||||
import FoundationExtras
|
import FoundationExtras
|
||||||
import Core
|
import Core
|
||||||
|
import AppConfig
|
||||||
|
|
||||||
public extension Notification.Name {
|
public extension Notification.Name {
|
||||||
|
|
||||||
|
@ -19,6 +20,8 @@ public extension Notification.Name {
|
||||||
|
|
||||||
@MainActor public final class ImageDownloader {
|
@MainActor public final class ImageDownloader {
|
||||||
|
|
||||||
|
public static let shared = ImageDownloader()
|
||||||
|
|
||||||
public static let imageURLKey = "url"
|
public static let imageURLKey = "url"
|
||||||
|
|
||||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ImageDownloader")
|
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ImageDownloader")
|
||||||
|
@ -28,7 +31,8 @@ public extension Notification.Name {
|
||||||
private var urlsInProgress = Set<String>()
|
private var urlsInProgress = Set<String>()
|
||||||
private var badURLs = Set<String>() // That return a 404 or whatever. Just skip them in the future.
|
private var badURLs = Set<String>() // That return a 404 or whatever. Just skip them in the future.
|
||||||
|
|
||||||
public init(folder: String) {
|
init() {
|
||||||
|
let folder = AppLocations.imagesFolder.path
|
||||||
self.diskCache = BinaryDiskCache(folder: folder)
|
self.diskCache = BinaryDiskCache(folder: folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue