Skip to content

Commit

Permalink
Refine AsyncImageView API
Browse files Browse the repository at this point in the history
  • Loading branch information
kean committed Dec 16, 2024
1 parent 619ec55 commit 14dcd0b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 22 deletions.
68 changes: 51 additions & 17 deletions WordPress/Classes/Utility/Media/AsyncImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}

Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -130,4 +156,12 @@ extension GIFImageView {
self.image = image
}
}

private func prepareForReuse() {
if isAnimatingGIF {
prepareForReuse()
} else {
image = nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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) {
Expand Down

0 comments on commit 14dcd0b

Please sign in to comment.