// // LNSkillFieldPhotoEditView.swift // Gami // // Created by OneeChan on 2026/1/21. // import Foundation import UIKit import SnapKit class LNSkillFieldPhotoEditView: LNSkillFieldBaseEditView { private var maxCount = -1 private let stackView = UIStackView() private let addImageButton = UIButton() override init(frame: CGRect) { super.init(frame: frame) setupViews() } override func update(_ field: LNSkillEditField) { super.update(field) if let limit = field.validate.arraySize { maxCount = limit.max } if let urls = field.value as? [String] { for url in urls { let imageView = buildImageView() imageView.loadImage(url: url) stackView.addArrangedSubview(imageView) imageView.snp.makeConstraints { make in make.height.equalToSuperview() make.width.equalTo(imageView.snp.height) } } updateImageCount() } } required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension LNSkillFieldPhotoEditView: LNImageUploadViewDelegate { func onImageUploadView(view: LNImageUploadView, didUploadImage url: String) { guard let field else { return } let imageViews = stackView.arrangedSubviews.filter { $0 is LNImageUploadView } as! [LNImageUploadView] field.value = imageViews.compactMap({ $0.imageUrl }) delegate?.onSkillFieldBaseEditViewInputChanged(view: self) needReview = true } func onImageUploadViewDidClickDelete(view: LNImageUploadView) { stackView.removeArrangedSubview(view) view.removeFromSuperview() guard let field else { return } let imageViews = stackView.arrangedSubviews.filter { $0 is LNImageUploadView } as! [LNImageUploadView] field.value = imageViews.compactMap({ $0.imageUrl }) delegate?.onSkillFieldBaseEditViewInputChanged(view: self) updateImageCount() needReview = true } } extension LNSkillFieldPhotoEditView { private func updateImageCount() { guard maxCount > 0 else { return } let imageViews = stackView.arrangedSubviews.filter { $0 is LNImageUploadView } addImageButton.isHidden = imageViews.count >= maxCount } private func setupViews() { let scrollView = UIScrollView() scrollView.showsVerticalScrollIndicator = false scrollView.showsHorizontalScrollIndicator = false scrollView.clipsToBounds = false container.addSubview(scrollView) scrollView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.verticalEdges.equalToSuperview().inset(2) make.height.equalTo(90) } stackView.axis = .horizontal stackView.spacing = 6 scrollView.addSubview(stackView) stackView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.verticalEdges.equalToSuperview() make.height.equalToSuperview() } let config = UIImage.SymbolConfiguration(pointSize: 17, weight: .semibold) addImageButton.backgroundColor = .fill_2 addImageButton.layer.cornerRadius = 9 addImageButton.setImage(.init(systemName: "plus", withConfiguration: config), for: .normal) addImageButton.tintColor = .text_3 addImageButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } LNBottomSheetMenu.showImageSelectMenu(view: self) { [weak self] image, _ in guard let self else { return } guard let image = image?.compress(type: .photoWall) else { return } let imageView = buildImageView() imageView.uploadImage(image: image) stackView.insertArrangedSubview(imageView, at: 1) imageView.snp.makeConstraints { make in make.height.equalToSuperview() make.width.equalTo(imageView.snp.height) } updateImageCount() } }), for: .touchUpInside) stackView.addArrangedSubview(addImageButton) addImageButton.snp.makeConstraints { make in make.height.equalToSuperview() make.width.equalTo(addImageButton.snp.height) } } private func buildImageView() -> LNImageUploadView { let imageView = LNImageUploadView() imageView.uploadType = .other imageView.layer.cornerRadius = 9 imageView.clipsToBounds = true imageView.showClearButton = true imageView.delegate = self return imageView } }