Visual_Novel_iOS/crush/Crush/Src/Components/UI/BaseView/UploadImageView.swift

266 lines
9.1 KiB
Swift

//
// UploadImageView.swift
// Crush
//
// Created by Leon on 2025/7/20.
//
import UIKit
import SnapKit
enum UploadImageState: UInt {
case `default`
case uploading
case success
case failed
case oversize
case yellow
}
class UploadImageView: UIView {
// MARK: - Properties
let imageView: CLImageView
let errorLabel: UILabel
let deleteButton: EPIconTertiaryDarkButton
let indicatorView: UIActivityIndicatorView
var state: UploadImageState = .default {
didSet {
dealUploadState(state)
}
}
var notShowDeleteButton: Bool = false {
didSet {
deleteButton.alpha = notShowDeleteButton ? 0 : 1
}
}
var bgTapBlock: (() -> Void)?
var deleteTapBlock: (() -> Void)?
var retryTapBlock: (() -> Void)?
private var bottomBottom: UIButton
private var bgButton: EPHighlightBorderButton
private var loadingView: UIView
private var indicatorLabel: UILabel
private var errorView: UIView
private var retryButton: UIButton
private var videoMode: Bool = false
// MARK: - Initialization
override init(frame: CGRect) {
imageView = CLImageView(frame: .zero)
errorLabel = UILabel()
deleteButton = EPIconTertiaryDarkButton(radius: .round, iconSize: .small, iconCode: .delete)
indicatorView = UIActivityIndicatorView()
bottomBottom = UIButton(type: .custom)
bgButton = EPHighlightBorderButton(type: .custom)
loadingView = UIView()
indicatorLabel = UILabel()
errorView = UIView()
retryButton = UIButton()
super.init(frame: frame)
setupUI()
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Setup
private func setupUI() {
backgroundColor = .c.csen//EPSystemToken.color(.surfaceElementNormal)
layer.cornerRadius = 8
clipsToBounds = true
// Bottom button
bottomBottom.backgroundColor = .clear
bottomBottom.addTarget(self, action: #selector(bgButtonTapAction), for: .touchUpInside)
addSubview(bottomBottom)
bottomBottom.snp.makeConstraints { make in
make.edges.equalTo(self)
}
// Background button
bgButton.layer.cornerRadius = layer.cornerRadius
bgButton.clipsToBounds = true
bgButton.addTarget(self, action: #selector(bgButtonTapAction), for: .touchUpInside)
let bgButtonImageColor: UIColor = .c.cttn
let image = MWIconFont.image(fromIcon: .iconUploadimg, size: CGSize(width: 48, height: 48), color: bgButtonImageColor)
//MWIconFont.image(fromIconInt: .iconUploadimg, size: CGSize(width: 48, height: 48), color: bgButtonImageColor, edgeInsets: .zero)
bgButton.setImage(image, for: .normal)
bgButton.setTitle("Click to generate images", for: .normal)
bgButton.setTitleColor(.c.cttn, for: .normal)
bgButton.titleLabel?.font = .t.tbm
//EPSystemToken.typography(.txtBodyM).font
addSubview(bgButton)
bgButton.snp.makeConstraints { make in
make.edges.equalTo(self)
}
// Image view
imageView.layer.cornerRadius = 8
imageView.clipsToBounds = true
imageView.layer.borderColor = UIColor.c.civn.cgColor
imageView.isHidden = true
imageView.contentMode = .scaleAspectFill
addSubview(imageView)
imageView.snp.makeConstraints { make in
make.edges.equalTo(self)
}
// Loading view
loadingView.isHidden = true
loadingView.backgroundColor = UIColor.black.withAlphaComponent(0.7) // Replaced hex_120E1B_bg
addSubview(loadingView)
loadingView.snp.makeConstraints { make in
make.edges.equalTo(self)
}
// Indicator view
indicatorView.color = .white // Replaced hex_FFFFFF
loadingView.addSubview(indicatorView)
indicatorView.snp.makeConstraints { make in
make.centerX.equalTo(loadingView)
make.centerY.equalTo(loadingView).offset(-10)
}
// Indicator label
indicatorLabel.font = .t.tbm//EPSystemToken.typography(.txtBodyM).font
indicatorLabel.textColor = .c.ctpsn//EPSystemToken.color(.txtPrimarySpecialmapNormal)
indicatorLabel.text = NSLocalizedString("uploading", comment: "")
loadingView.addSubview(indicatorLabel)
indicatorLabel.snp.makeConstraints { make in
make.centerX.equalTo(loadingView)
make.top.equalTo(indicatorView.snp.bottom).offset(12)
}
// Error view
errorView.isHidden = true
errorView.backgroundColor = .red //EPSystemToken.color(.importantOnpicNormal)
addSubview(errorView)
errorView.snp.makeConstraints { make in
make.leading.trailing.bottom.equalTo(self)
}
// Error label
errorLabel.isHidden = false
errorLabel.font = .t.tbs//EPSystemToken.typography(.txtBodyS).font
errorLabel.textColor = .c.ctpsn//EPSystemToken.color(.txtPrimarySpecialmapNormal)
errorLabel.numberOfLines = 5
errorLabel.textAlignment = .left
errorView.addSubview(errorLabel)
errorLabel.snp.makeConstraints { make in
make.leading.equalTo(errorView).offset(16)
make.trailing.equalTo(errorView).offset(-16)
make.top.equalTo(errorView).offset(8)
make.bottom.equalTo(errorView).offset(-8)
}
// Delete button
let deleteButtonSize = deleteButton.bgImageSize()
deleteButton.addTarget(self, action: #selector(deleteAction), for: .touchUpInside)
addSubview(deleteButton)
deleteButton.snp.makeConstraints { make in
make.trailing.equalTo(self).offset(-16)
make.top.equalTo(self).offset(16)
make.size.equalTo(deleteButtonSize)
}
// Retry button
retryButton.isHidden = true
let retryImage = MWIconFont.image(fromIcon: .iconReload, size: CGSize(width: 48, height: 48), color: UIColor.c.ctpsn)
retryButton.setImage(retryImage, for: .normal)
retryButton.addTarget(self, action: #selector(retryAction), for: .touchUpInside)
addSubview(retryButton)
retryButton.snp.makeConstraints { make in
make.center.equalTo(self)
make.size.equalTo(CGSize(width: 48, height: 48))
}
state = .default
}
// MARK: - Public Methods
func setupVideoMode() {
videoMode = true
}
// MARK: - Actions
@objc private func bgButtonTapAction() {
bgTapBlock?()
}
@objc private func deleteAction() {
deleteTapBlock?()
}
@objc private func retryAction() {
retryTapBlock?()
}
// MARK: - State Handling
private func dealUploadState(_ state: UploadImageState) {
indicatorView.stopAnimating()
imageView.isHidden = false
imageView.layer.borderWidth = 0
errorLabel.text = ""
bgButton.isHidden = true
switch state {
case .default:
bgButton.isHidden = false
bgButton.isEnabled = true
imageView.isHidden = true
deleteButton.isHidden = true
retryButton.isHidden = true
loadingView.isHidden = true
errorView.isHidden = true
case .uploading:
bottomBottom.isEnabled = false
deleteButton.isHidden = false
retryButton.isHidden = true
loadingView.isHidden = false
errorView.isHidden = true
indicatorView.startAnimating()
case .failed:
bottomBottom.isEnabled = false
deleteButton.isHidden = false
retryButton.isHidden = false
loadingView.isHidden = true
errorView.isHidden = false
imageView.layer.borderWidth = CLSystemToken.border(token: .bs)//EPSystemToken.border(.borderS)
case .oversize:
bottomBottom.isEnabled = false
deleteButton.isHidden = false
retryButton.isHidden = true
loadingView.isHidden = true
errorView.isHidden = false
imageView.layer.borderWidth = CLSystemToken.border(token: .bs)//EPSystemToken.border(.borderS)
case .yellow:
bottomBottom.isEnabled = false
deleteButton.isHidden = false
retryButton.isHidden = true
loadingView.isHidden = true
errorView.isHidden = false
imageView.layer.borderWidth = CLSystemToken.border(token: .bs)
case .success:
bottomBottom.isEnabled = true
deleteButton.isHidden = false
retryButton.isHidden = true
loadingView.isHidden = true
errorView.isHidden = true
}
}
// MARK: - Overrides
override func layoutSubviews() {
super.layoutSubviews()
bgButton.setUp(.top, padding: 12)
}
}