diff --git a/WordPress/Classes/Utility/Media/AsyncImageView.swift b/WordPress/Classes/Utility/Media/AsyncImageView.swift index 645fb5dd49c0..acc010f1679e 100644 --- a/WordPress/Classes/Utility/Media/AsyncImageView.swift +++ b/WordPress/Classes/Utility/Media/AsyncImageView.swift @@ -5,34 +5,55 @@ import Gifu /// (see ``AnimatedImage``). @MainActor final class AsyncImageView: UIView { - let imageView = GIFImageView() - + private let imageView = GIFImageView() private var errorView: UIImageView? private var spinner: UIActivityIndicatorView? private let controller = ImageViewController() enum LoadingStyle { + /// Shows a secondary background color during the download. case background + /// Shows a spinner during the download. case spinner } - var isErrorViewEnabled = true - var loadingStyle = LoadingStyle.background + struct Configuration { + /// Image tint color. + var tintColor: UIColor? + + /// Image view content mode. + var contentMode: UIView.ContentMode? + + /// Enabled by default and shows an error icon on failures. + var isErrorViewEnabled = true + + /// By default, `background`. + var loadingStyle = LoadingStyle.background + } + + var configuration = Configuration() { + didSet { didUpdateConfiguration(configuration) } + } + /// The currently displayed image. If the image is animated, returns an + /// instance of ``AnimatedImage``. var image: UIImage? { - get { imageView.image } - set { imageView.image = newValue } + didSet { + if let image { + imageView.configure(image: image) + } else { + imageView.prepareForReuse() + } + } } override init(frame: CGRect) { super.init(frame: frame) - setupView() } required init?(coder: NSCoder) { super.init(coder: coder) - setupView() } @@ -50,14 +71,10 @@ final class AsyncImageView: UIView { backgroundColor = .secondarySystemBackground } + /// Removes the current image and stops the outstanding downloads. func prepareForReuse() { controller.prepareForReuse() - - if imageView.isAnimatingGIF { - imageView.prepareForReuse() - } else { - imageView.image = nil - } + image = nil } /// - parameter size: Target image size in pixels. @@ -77,23 +94,32 @@ final class AsyncImageView: UIView { switch state { case .loading: - switch loadingStyle { + switch configuration.loadingStyle { case .background: backgroundColor = .secondarySystemBackground case .spinner: makeSpinner().startAnimating() } case .success(let image): - imageView.configure(image: image) + self.image = image imageView.isHidden = false backgroundColor = .clear case .failure: - if isErrorViewEnabled { + if configuration.isErrorViewEnabled { makeErrorView().isHidden = false } } } + private func didUpdateConfiguration(_ configuration: Configuration) { + if let tintColor = configuration.tintColor { + imageView.tintColor = tintColor + } + if let contentMode = configuration.contentMode { + imageView.contentMode = contentMode + } + } + private func makeSpinner() -> UIActivityIndicatorView { if let spinner { return spinner @@ -130,4 +156,12 @@ extension GIFImageView { self.image = image } } + + private func prepareForReuse() { + if isAnimatingGIF { + prepareForReuse() + } else { + image = nil + } + } } diff --git a/WordPress/Classes/ViewRelated/Reader/Views/ReaderAvatarView.swift b/WordPress/Classes/ViewRelated/Reader/Views/ReaderAvatarView.swift index 0c468580ddc9..7c76771caa4e 100644 --- a/WordPress/Classes/ViewRelated/Reader/Views/ReaderAvatarView.swift +++ b/WordPress/Classes/ViewRelated/Reader/Views/ReaderAvatarView.swift @@ -12,7 +12,7 @@ final class ReaderAvatarView: UIView { layer.borderWidth = 0.5 layer.borderColor = UIColor.opaqueSeparator.withAlphaComponent(0.5).cgColor - asyncImageView.isErrorViewEnabled = false + asyncImageView.configuration.isErrorViewEnabled = false addSubview(asyncImageView) } @@ -33,13 +33,13 @@ final class ReaderAvatarView: UIView { } func setStaticIcon(_ image: UIImage?, tintColor: UIColor) { - asyncImageView.imageView.tintColor = .secondaryLabel - asyncImageView.imageView.contentMode = .center - asyncImageView.imageView.image = image + asyncImageView.configuration.tintColor = .secondaryLabel + asyncImageView.configuration.contentMode = .center + asyncImageView.image = image } func setPlaceholder(_ image: UIImage?) { - asyncImageView.imageView.image = image + asyncImageView.image = image } func setImage(with imageURL: URL, size: CGSize? = nil) {