NetNewsWire/Shared/Images/AuthorAvatarDownloader.swift

95 lines
2.4 KiB
Swift
Raw Normal View History

2017-11-26 22:16:32 +01:00
//
// AuthorAvatarDownloader.swift
2018-08-29 07:18:24 +02:00
// NetNewsWire
2017-11-26 22:16:32 +01:00
//
// Created by Brent Simmons on 11/26/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Foundation
import Articles
import Core
2017-11-26 22:16:32 +01:00
extension Notification.Name {
static let AvatarDidBecomeAvailable = Notification.Name("AvatarDidBecomeAvailableNotification") // UserInfoKey.imageURL (which is an avatarURL)
}
2017-11-26 22:16:32 +01:00
final class AuthorAvatarDownloader {
private let imageDownloader: ImageDownloader
private var cache = [String: IconImage]() // avatarURL: RSImage
private var waitingForAvatarURLs = Set<String>()
2017-11-26 22:16:32 +01:00
init(imageDownloader: ImageDownloader) {
self.imageDownloader = imageDownloader
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: imageDownloader)
2017-11-26 22:16:32 +01:00
}
func resetCache() {
cache = [String: IconImage]()
}
func image(for author: Author) -> IconImage? {
2017-11-26 22:16:32 +01:00
guard let avatarURL = author.avatarURL else {
return nil
}
if let cachedImage = cache[avatarURL] {
return cachedImage
}
if let imageData = imageDownloader.image(for: avatarURL) {
scaleAndCacheImageData(imageData, avatarURL)
}
else {
waitingForAvatarURLs.insert(avatarURL)
}
return nil
}
@objc func imageDidBecomeAvailable(_ note: Notification) {
guard let avatarURL = note.userInfo?[UserInfoKey.url] as? String else {
return
}
guard waitingForAvatarURLs.contains(avatarURL) else {
return
}
guard let imageData = imageDownloader.image(for: avatarURL) else {
return
}
scaleAndCacheImageData(imageData, avatarURL)
}
}
private extension AuthorAvatarDownloader {
func scaleAndCacheImageData(_ imageData: Data, _ avatarURL: String) {
2024-03-25 02:49:39 +01:00
Task { @MainActor in
if let image = await RSImage.scaledForIcon(imageData) {
self.handleImageDidBecomeAvailable(avatarURL, image)
}
}
}
func handleImageDidBecomeAvailable(_ avatarURL: String, _ image: RSImage) {
if cache[avatarURL] == nil {
cache[avatarURL] = IconImage(image)
}
if waitingForAvatarURLs.contains(avatarURL) {
waitingForAvatarURLs.remove(avatarURL)
postAvatarDidBecomeAvailableNotification(avatarURL)
}
}
func postAvatarDidBecomeAvailableNotification(_ avatarURL: String) {
DispatchQueue.main.async {
NotificationCenter.default.post(name: .AvatarDidBecomeAvailable, object: self, userInfo: [UserInfoKey.url: avatarURL])
}
2017-11-26 22:16:32 +01:00
}
}