| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- //
- // LNJoinUsSkillFieldsEditView.swift
- // Gami
- //
- // Created by OneeChan on 2026/1/19.
- //
- import Foundation
- import UIKit
- import SnapKit
- import Combine
- class LNJoinUsSkillFieldsEditView: UIView {
- private let titleLabel = UILabel()
-
- private let stackView = UIStackView()
-
- private let applyButton = UIButton()
-
- private var fieldViews: [LNSkillFieldBaseEditView] = []
- private var field: LNCreateSkillInputFieldsVO?
-
- override var isHidden: Bool {
- didSet {
- if isHidden {
- LNVoicePlayer.shared.stop()
- LNVoiceRecorder.shared.stopRecord()
- }
- }
- }
-
- deinit {
- LNVoicePlayer.shared.stop()
- LNVoiceRecorder.shared.stopRecord()
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- setupViews()
- }
-
- func update(_ skill: LNGameCategoryItemVO, info: LNCreateSkillInputFieldsVO) {
- stackView.arrangedSubviews.forEach {
- stackView.removeArrangedSubview($0)
- $0.removeFromSuperview()
- }
-
- titleLabel.text = skill.name
- if info.bizCategoryCode?.isEmpty != false {
- info.bizCategoryCode = skill.code
- }
-
- for field in info.fields {
- let view: LNSkillFieldBaseEditView? = switch field.type {
- case .singleLineText, .number:
- LNSkillFieldSingleLineEditView()
- case .multiLineText:
- LNSkillFieldMultiLineEditView()
- case .singleSelection, .multiSelection:
- LNSkillFieldSelectionEditView()
- case .voice:
- LNSkillFieldVoiceEditView()
- case .photo:
- LNSkillFieldPhotoEditView()
- default:
- nil
- }
- if let view {
- stackView.addArrangedSubview(view)
- fieldViews.append(view)
- view.delegate = self
- view.update(field)
- }
- }
-
- field = info
-
- checkSubmitButton()
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNJoinUsSkillFieldsEditView {
- private func commit() {
- guard let field else { return }
-
- if fieldViews.first(where: { $0.checkAvailable() == false }) != nil {
- return
- }
- showLoading()
- DispatchQueue.global().async { [weak self] in
- let voices = field.fields.filter({ $0.type == .voice })
- let group = DispatchGroup()
- var uploadDone = true
- for voice in voices {
- if let path = voice.value as? String,
- !path.starts(with: "http") {
- group.enter()
- LNFileUploader.shared.startUpload(type: .voice, fileURL: URL(fileURLWithPath: path), progressHandler: nil)
- { url, err in
- if let err {
- showToast(err)
- uploadDone = false
- } else if let url {
- voice.value = url
- } else {
- uploadDone = false
- }
- group.leave()
- }
- }
- }
- group.wait()
-
- if !uploadDone {
- dismissLoading()
- return
- }
- guard let self else { return }
- let info = LNCreateSkillFieldsInfo()
- info.bizCategoryCode = field.bizCategoryCode!
- for item in field.fields {
- let config = LNCreateSkillFieldInfo()
- config.fieldCode = item.fieldCode
- config.value = item.value
- if item.type == .voice {
- config.duration = item.duration
- }
- info.fields.append(config)
- }
- LNGameMateManager.shared.createSkill(info: info) { [weak self] success in
- dismissLoading()
- guard let self else { return }
- guard success else { return }
- pushToJoinUsReview()
- }
- }
- }
- }
- extension LNJoinUsSkillFieldsEditView: LNSkillFieldBaseEditViewDelegate {
- func onSkillFieldBaseEditViewInputChanged(view: LNSkillFieldBaseEditView) {
- checkSubmitButton()
- }
- }
- extension LNJoinUsSkillFieldsEditView {
- private func checkSubmitButton() {
- let allInput = fieldViews.first { !$0.hasInput() } == nil
-
- if allInput != applyButton.isEnabled {
- applyButton.isEnabled = allInput
- applyButton.setBackgroundImage(allInput ? .primary_8 : nil, for: .normal)
- }
- }
-
- private func setupViews() {
- onTap { [weak self] in
- guard let self else { return }
- endEditing(true)
- }
-
- let header = buildTitle()
- addSubview(header)
- header.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview()
- }
-
- let scrollView = UIScrollView()
- scrollView.showsVerticalScrollIndicator = false
- scrollView.showsHorizontalScrollIndicator = false
- scrollView.contentInsetAdjustmentBehavior = .never
- scrollView.contentInset = .init(top: 0, left: 0, bottom: -commonBottomInset + 62, right: 0)
- scrollView.adjustKeyoard()
- addSubview(scrollView)
- scrollView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(16)
- make.top.equalTo(header.snp.bottom)
- make.bottom.equalToSuperview()
- }
-
- stackView.axis = .vertical
- stackView.spacing = 24
- scrollView.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- make.width.equalToSuperview()
- }
-
- let bottomMenu = UIView()
- addSubview(bottomMenu)
- bottomMenu.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.bottom.equalToSuperview()
- }
-
- let bottomGradient = CAGradientLayer()
- bottomGradient.colors = [
- UIColor.white.withAlphaComponent(0).cgColor,
- UIColor.white.cgColor,
- UIColor.white.cgColor
- ]
- bottomGradient.locations = [0, 0.5, 1]
- bottomGradient.startPoint = .init(x: 0, y: 0)
- bottomGradient.endPoint = .init(x: 0, y: 1)
- bottomMenu.layer.addSublayer(bottomGradient)
- bottomMenu.publisher(for: \.bounds).removeDuplicates().sink { [weak bottomGradient] newValue in
- guard let bottomGradient else { return }
- bottomGradient.frame = newValue
- }.store(in: &cancellables)
-
- applyButton.setTitle(.init(key: "A00240"), for: .normal)
- applyButton.setTitleColor(.text_1, for: .normal)
- applyButton.titleLabel?.font = .heading_h3
- applyButton.layer.cornerRadius = 23.5
- applyButton.backgroundColor = .fill_4
- applyButton.clipsToBounds = true
- applyButton.isEnabled = false
- applyButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- commit()
- }), for: .touchUpInside)
- bottomMenu.addSubview(applyButton)
- applyButton.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(16)
- make.bottom.equalToSuperview().offset(commonBottomInset)
- make.top.equalToSuperview()
- make.height.equalTo(47)
- }
- }
-
- private func buildTitle() -> UIView {
- let container = UIView()
-
- titleLabel.font = .heading_h2
- titleLabel.textColor = .text_5
- container.addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(20)
- make.verticalEdges.equalToSuperview().inset(20)
- }
-
- return container
- }
- }
|