mastodon-ios/Mastodon/Protocol/AvatarConfigurableView.swift

147 lines
5.7 KiB
Swift

//
// AvatarConfigurableView.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-2-4.
//
import UIKit
import AlamofireImage
import Kingfisher
protocol AvatarConfigurableView {
static var configurableAvatarImageViewSize: CGSize { get }
static var configurableAvatarImageViewBadgeAppearanceStyle: AvatarConfigurableViewConfiguration.BadgeAppearanceStyle { get }
var configurableAvatarImageView: UIImageView? { get }
var configurableAvatarButton: UIButton? { get }
var configurableVerifiedBadgeImageView: UIImageView? { get }
func configure(withConfigurationInput input: AvatarConfigurableViewConfiguration.Input)
func avatarConfigurableView(_ avatarConfigurableView: AvatarConfigurableView, didFinishConfiguration configuration: AvatarConfigurableViewConfiguration)
}
extension AvatarConfigurableView {
static var configurableAvatarImageViewBadgeAppearanceStyle: AvatarConfigurableViewConfiguration.BadgeAppearanceStyle { return .mini }
public func configure(withConfigurationInput input: AvatarConfigurableViewConfiguration.Input) {
// TODO: set badge
configurableVerifiedBadgeImageView?.isHidden = true
let cornerRadius = Self.configurableAvatarImageViewSize.width * 0.5
// let scale = (configurableAvatarImageView ?? configurableAvatarButton)?.window?.screen.scale ?? UIScreen.main.scale
let placeholderImage: UIImage = {
let placeholderImage = input.placeholderImage ?? UIImage.placeholder(size: Self.configurableAvatarImageViewSize, color: .systemFill)
return placeholderImage.af.imageRoundedIntoCircle()
}()
// cancel previous task
configurableAvatarImageView?.af.cancelImageRequest()
configurableAvatarImageView?.kf.cancelDownloadTask()
configurableAvatarButton?.af.cancelImageRequest(for: .normal)
configurableAvatarButton?.kf.cancelImageDownloadTask()
// reset layer attributes
configurableAvatarImageView?.layer.masksToBounds = false
configurableAvatarImageView?.layer.cornerRadius = 0
configurableAvatarImageView?.layer.cornerCurve = .circular
configurableAvatarButton?.layer.masksToBounds = false
configurableAvatarButton?.layer.cornerRadius = 0
configurableAvatarButton?.layer.cornerCurve = .circular
defer {
let configuration = AvatarConfigurableViewConfiguration(input: input)
avatarConfigurableView(self, didFinishConfiguration: configuration)
}
// set placeholder if no asset
guard let avatarImageURL = input.avatarImageURL else {
configurableAvatarImageView?.image = placeholderImage
configurableAvatarButton?.setImage(placeholderImage, for: .normal)
return
}
if let avatarImageView = configurableAvatarImageView {
// set avatar (GIF using Kingfisher)
switch avatarImageURL.pathExtension {
case "gif":
avatarImageView.kf.setImage(
with: avatarImageURL,
placeholder: placeholderImage,
options: [
.transition(.fade(0.2))
]
)
avatarImageView.layer.masksToBounds = true
avatarImageView.layer.cornerRadius = cornerRadius
avatarImageView.layer.cornerCurve = .circular
default:
let filter = ScaledToSizeCircleFilter(size: Self.configurableAvatarImageViewSize)
avatarImageView.af.setImage(
withURL: avatarImageURL,
placeholderImage: placeholderImage,
filter: filter,
imageTransition: .crossDissolve(0.3),
runImageTransitionIfCached: false,
completion: nil
)
}
}
if let avatarButton = configurableAvatarButton {
switch avatarImageURL.pathExtension {
case "gif":
avatarButton.kf.setImage(
with: avatarImageURL,
for: .normal,
placeholder: placeholderImage,
options: [
.transition(.fade(0.2))
]
)
avatarButton.layer.masksToBounds = true
avatarButton.layer.cornerRadius = cornerRadius
avatarButton.layer.cornerCurve = .circular
default:
let filter = ScaledToSizeCircleFilter(size: Self.configurableAvatarImageViewSize)
avatarButton.af.setImage(
for: .normal,
url: avatarImageURL,
placeholderImage: placeholderImage,
filter: filter,
completion: nil
)
}
}
}
func avatarConfigurableView(_ avatarConfigurableView: AvatarConfigurableView, didFinishConfiguration configuration: AvatarConfigurableViewConfiguration) { }
}
struct AvatarConfigurableViewConfiguration {
enum BadgeAppearanceStyle {
case mini
case normal
}
struct Input {
let avatarImageURL: URL?
let placeholderImage: UIImage?
let blocked: Bool
let verified: Bool
init(avatarImageURL: URL?, placeholderImage: UIImage? = nil, blocked: Bool = false, verified: Bool = false) {
self.avatarImageURL = avatarImageURL
self.placeholderImage = placeholderImage
self.blocked = blocked
self.verified = verified
}
}
let input: Input
}