// // CachedImageView.swift // Tusker // // Created by Shadowfacts on 10/4/22. // Copyright © 2022 Shadowfacts. All rights reserved. // import UIKit class CachedImageView: UIImageView { var cache: ImageCache! private var url: URL? private var isGrayscale = false private var fetchTask: Task? private var blurHashTask: DispatchWorkItem? override var image: UIImage? { didSet { blurHashTask?.cancel() } } init(cache: ImageCache) { self.cache = cache super.init(frame: .zero) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil) } func update(for url: URL?, blurhash: String? = nil, placeholder: UIImage? = nil) { if url != self.url || (url != nil && self.image == nil) { self.url = url super.image = placeholder updateBlurhash(blurhash, for: url) updateImage() } } func showOnlyBlurHash(_ blurhash: String, for url: URL) { if url != self.url { self.url = url updateBlurhash(blurhash, for: url) } } @objc private func preferencesChanged() { if isGrayscale != Preferences.shared.grayscaleImages { updateImage() } } private func updateBlurhash(_ blurhash: String?, for url: URL?) { blurHashTask?.cancel() if let blurhash { let aspectRatio = self.bounds.width > 0 ? self.bounds.height / self.bounds.width : 1 blurHashTask = DispatchWorkItem { let size = CGSize(width: 60, height: aspectRatio * 60) let image = UIImage(blurHash: blurhash, size: size) DispatchQueue.main.async { if self.image == nil && self.url == url && self.blurHashTask?.isCancelled == false { self.image = image } } } AttachmentView.queue.async(execute: blurHashTask!) } } private func updateImage() { fetchTask?.cancel() guard let url else { return } fetchTask = Task(priority: .high) { let (_, image) = await cache.get(url) guard let image else { return } try Task.checkCancellation() guard let transformedImage = await ImageGrayscalifier.convertIfNecessary(url: url, image: image) else { return } try Task.checkCancellation() super.image = transformedImage self.isGrayscale = Preferences.shared.grayscaleImages self.blurHashTask?.cancel() } } }