mastodon-app-ufficiale-ipho.../Mastodon/Protocol/AvatarConfigurableView.swift

152 lines
5.6 KiB
Swift

//
// AvatarConfigurableView.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-2-4.
//
import UIKit
import AlamofireImage
import FLAnimatedImage
import Nuke
protocol AvatarConfigurableView {
static var configurableAvatarImageSize: CGSize { get }
static var configurableAvatarImageCornerRadius: CGFloat { get }
var configurableAvatarImageView: UIImageView? { get }
var configurableAvatarButton: UIButton? { get }
func configure(with configuration: AvatarConfigurableViewConfiguration)
func avatarConfigurableView(_ avatarConfigurableView: AvatarConfigurableView, didFinishConfiguration configuration: AvatarConfigurableViewConfiguration)
}
extension AvatarConfigurableView {
public func configure(with configuration: AvatarConfigurableViewConfiguration) {
let placeholderImage: UIImage = {
guard let placeholderImage = configuration.placeholderImage else {
#if APP_EXTENSION
let placeholderImage = configuration.placeholderImage ?? UIImage.placeholder(size: Self.configurableAvatarImageSize, color: .systemFill)
if Self.configurableAvatarImageCornerRadius < Self.configurableAvatarImageSize.width * 0.5 {
return placeholderImage
.af.imageAspectScaled(toFill: Self.configurableAvatarImageSize)
.af.imageRounded(withCornerRadius: Self.configurableAvatarImageCornerRadius, divideRadiusByImageScale: false)
} else {
return placeholderImage.af.imageRoundedIntoCircle()
}
#else
return AppContext.shared.placeholderImageCacheService.image(
color: .systemFill,
size: Self.configurableAvatarImageSize,
cornerRadius: Self.configurableAvatarImageCornerRadius
)
#endif
}
return placeholderImage
}()
// 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
// accessibility
configurableAvatarImageView?.accessibilityIgnoresInvertColors = true
configurableAvatarButton?.accessibilityIgnoresInvertColors = true
defer {
avatarConfigurableView(self, didFinishConfiguration: configuration)
}
guard let imageDisplayingView: ImageDisplayingView = configurableAvatarImageView ?? configurableAvatarButton?.imageView else {
return
}
// set corner radius (due to GIF won't crop)
imageDisplayingView.layer.masksToBounds = true
imageDisplayingView.layer.cornerRadius = Self.configurableAvatarImageCornerRadius
imageDisplayingView.layer.cornerCurve = Self.configurableAvatarImageCornerRadius < Self.configurableAvatarImageSize.width * 0.5 ? .continuous :.circular
// set border
configureLayerBorder(view: imageDisplayingView, configuration: configuration)
// set image
let url = configuration.avatarImageURL
let processors: [ImageProcessing] = [
ImageProcessors.Resize(
size: Self.configurableAvatarImageSize,
unit: .points,
contentMode: .aspectFill,
crop: false
),
ImageProcessors.RoundedCorners(
radius: Self.configurableAvatarImageCornerRadius
)
]
let request = ImageRequest(url: url, processors: processors)
let options = ImageLoadingOptions(
placeholder: placeholderImage,
transition: .fadeIn(duration: 0.2)
)
Nuke.loadImage(
with: request,
options: options,
into: imageDisplayingView
) { result in
switch result {
case .failure:
break
case .success:
break
}
}
}
func configureLayerBorder(view: UIView, configuration: AvatarConfigurableViewConfiguration) {
guard let borderWidth = configuration.borderWidth, borderWidth > 0,
let borderColor = configuration.borderColor else {
return
}
view.layer.masksToBounds = true
view.layer.cornerRadius = Self.configurableAvatarImageCornerRadius
view.layer.cornerCurve = .continuous
view.layer.borderColor = borderColor.cgColor
view.layer.borderWidth = borderWidth
}
func avatarConfigurableView(_ avatarConfigurableView: AvatarConfigurableView, didFinishConfiguration configuration: AvatarConfigurableViewConfiguration) { }
}
struct AvatarConfigurableViewConfiguration {
let avatarImageURL: URL?
let placeholderImage: UIImage?
let borderColor: UIColor?
let borderWidth: CGFloat?
let keepImageCorner: Bool
init(
avatarImageURL: URL?,
placeholderImage: UIImage? = nil,
borderColor: UIColor? = nil,
borderWidth: CGFloat? = nil,
keepImageCorner: Bool = false // default clip corner on image
) {
self.avatarImageURL = avatarImageURL
self.placeholderImage = placeholderImage
self.borderColor = borderColor
self.borderWidth = borderWidth
self.keepImageCorner = keepImageCorner
}
}