Create .shared of FaviconDownloader, AuthorAvatarDownloader, FeedIconDownloader, and ImageDownloader.

This commit is contained in:
Brent Simmons 2024-06-26 23:12:26 -07:00
parent 840147aee3
commit 8cd69d7509
4 changed files with 28 additions and 24 deletions

View File

@ -17,13 +17,12 @@ public extension Notification.Name {
@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 waitingForAvatarURLs = Set<String>()
public init(imageDownloader: ImageDownloader) {
self.imageDownloader = imageDownloader
init() {
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: imageDownloader)
}

View File

@ -13,6 +13,7 @@ import Account
import UniformTypeIdentifiers
import Core
import ParserObjC
import AppConfig
public extension Notification.Name {
static let FaviconDidBecomeAvailable = Notification.Name("FaviconDidBecomeAvailableNotification") // userInfo key: FaviconDownloader.UserInfoKey.faviconURL
@ -27,16 +28,18 @@ public protocol FaviconDownloaderDelegate {
@MainActor public final class FaviconDownloader {
public static let shared = FaviconDownloader()
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 var singleFaviconDownloaderCache = [String: SingleFaviconDownloader]() // faviconURL: SingleFaviconDownloader
private var remainingFaviconURLs = [String: ArraySlice<String>]() // homePageURL: array of faviconURLs that haven't been checked yet
private var currentHomePageHasOnlyFaviconICO = false
private var homePageToFaviconURLCache = [String: String]() //homePageURL: faviconURL
private var homePageToFaviconURLCachePath: String
private var homePageToFaviconURLCachePath: URL
private var homePageToFaviconURLCacheDirty = false {
didSet {
queueSaveHomePageToFaviconURLCacheIfNeeded()
@ -44,7 +47,7 @@ public protocol FaviconDownloaderDelegate {
}
private var homePageURLsWithNoFaviconURLCache = Set<String>()
private var homePageURLsWithNoFaviconURLCachePath: String
private var homePageURLsWithNoFaviconURLCachePath: URL
private var homePageURLsWithNoFaviconURLCacheDirty = false {
didSet {
queueSaveHomePageURLsWithNoFaviconURLCacheIfNeeded()
@ -60,14 +63,14 @@ public protocol FaviconDownloaderDelegate {
static let faviconURL = "faviconURL"
}
public init(folder: String) {
public init() {
self.folder = folder
self.diskCache = BinaryDiskCache(folder: folder)
self.folder = AppLocations.faviconsFolder
self.diskCache = BinaryDiskCache(folder: folder.path)
self.queue = DispatchQueue(label: "FaviconDownloader serial queue - \(folder)")
self.homePageToFaviconURLCachePath = (folder as NSString).appendingPathComponent("HomePageToFaviconURLCache.plist")
self.homePageURLsWithNoFaviconURLCachePath = (folder as NSString).appendingPathComponent("HomePageURLsWithNoFaviconURLCache.plist")
self.homePageToFaviconURLCachePath = folder.appendingPathComponent("HomePageToFaviconURLCache.plist")
self.homePageURLsWithNoFaviconURLCachePath = folder.appendingPathComponent("HomePageURLsWithNoFaviconURLCache.plist")
loadHomePageToFaviconURLCache()
loadHomePageURLsWithNoFaviconURLCache()
@ -262,8 +265,7 @@ private extension FaviconDownloader {
}
func loadHomePageToFaviconURLCache() {
let url = URL(fileURLWithPath: homePageToFaviconURLCachePath)
guard let data = try? Data(contentsOf: url) else {
guard let data = try? Data(contentsOf: homePageToFaviconURLCachePath) else {
return
}
let decoder = PropertyListDecoder()
@ -271,8 +273,7 @@ private extension FaviconDownloader {
}
func loadHomePageURLsWithNoFaviconURLCache() {
let url = URL(fileURLWithPath: homePageURLsWithNoFaviconURLCachePath)
guard let data = try? Data(contentsOf: url) else {
guard let data = try? Data(contentsOf: homePageURLsWithNoFaviconURLCachePath) else {
return
}
let decoder = PropertyListDecoder()
@ -297,10 +298,9 @@ private extension FaviconDownloader {
let encoder = PropertyListEncoder()
encoder.outputFormat = .binary
let url = URL(fileURLWithPath: homePageToFaviconURLCachePath)
do {
let data = try encoder.encode(homePageToFaviconURLCache)
try data.write(to: url)
try data.write(to: homePageToFaviconURLCachePath)
} catch {
assertionFailure(error.localizedDescription)
}
@ -311,10 +311,9 @@ private extension FaviconDownloader {
let encoder = PropertyListEncoder()
encoder.outputFormat = .binary
let url = URL(fileURLWithPath: homePageURLsWithNoFaviconURLCachePath)
do {
let data = try encoder.encode(Array(homePageURLsWithNoFaviconURLCache))
try data.write(to: url)
try data.write(to: homePageURLsWithNoFaviconURLCachePath)
} catch {
assertionFailure(error.localizedDescription)
}

View File

@ -28,11 +28,13 @@ public protocol FeedIconDownloaderDelegate: Sendable {
@MainActor public final class FeedIconDownloader {
public static let shared = FeedIconDownloader()
public static let feedKey = "url"
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 feedURLToIconURLCachePath: String
@ -68,8 +70,8 @@ public protocol FeedIconDownloaderDelegate: Sendable {
public var delegate: FeedIconDownloaderDelegate?
public init(imageDownloader: ImageDownloader, folder: String) {
self.imageDownloader = imageDownloader
public init(folder: String) {
self.feedURLToIconURLCachePath = (folder as NSString).appendingPathComponent("FeedURLToIconURLCache.plist")
self.homePageToIconURLCachePath = (folder as NSString).appendingPathComponent("HomePageToIconURLCache.plist")
self.homePagesWithNoIconURLCachePath = (folder as NSString).appendingPathComponent("HomePagesWithNoIconURLCache.plist")

View File

@ -11,6 +11,7 @@ import os.log
import Web
import FoundationExtras
import Core
import AppConfig
public extension Notification.Name {
@ -19,6 +20,8 @@ public extension Notification.Name {
@MainActor public final class ImageDownloader {
public static let shared = ImageDownloader()
public static let imageURLKey = "url"
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 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)
}