LNSkillEditViewController.swift 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // LNSkillEditViewController.swift
  3. // Gami
  4. //
  5. // Created by OneeChan on 2026/1/25.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. import Combine
  11. extension UIView {
  12. func pushToSkillEdit(_ info: LNSkillEditFieldsResponse) {
  13. showLoading()
  14. LNGameMateManager.shared.getJoinGameMateInfo { [weak self] res in
  15. dismissLoading()
  16. guard let self else { return }
  17. if res?.underReview == true {
  18. let vc = LNSkillReviewViewController()
  19. navigationController?.pushViewController(vc, animated: true)
  20. return
  21. }
  22. let vc = LNSkillEditViewController(info: info)
  23. navigationController?.pushViewController(vc, animated: true)
  24. }
  25. }
  26. }
  27. class LNSkillEditViewController: LNViewController {
  28. private let scrollView = UIScrollView()
  29. private let info: LNSkillEditFieldsResponse
  30. private let editPanel = LNSkillFieldsEditView()
  31. private let confirmButton = UIButton()
  32. init(info: LNSkillEditFieldsResponse) {
  33. self.info = info
  34. super.init(nibName: nil, bundle: nil)
  35. }
  36. required init?(coder: NSCoder) {
  37. fatalError("init(coder:) has not been implemented")
  38. }
  39. override func viewDidLoad() {
  40. super.viewDidLoad()
  41. setupViews()
  42. checkConfirmButton()
  43. }
  44. }
  45. extension LNSkillEditViewController {
  46. private func commit() {
  47. guard editPanel.checkAvailable else {
  48. return
  49. }
  50. showLoading()
  51. DispatchQueue.global().async { [weak self] in
  52. guard let self else {
  53. dismissLoading()
  54. return
  55. }
  56. let voices = info.fields.filter({ $0.type == .voice })
  57. let group = DispatchGroup()
  58. var uploadDone = true
  59. for voice in voices {
  60. if let path = voice.value as? String,
  61. !path.starts(with: "http") {
  62. group.enter()
  63. LNFileUploader.shared.startUpload(type: .voice, fileURL: URL(fileURLWithPath: path), progressHandler: nil)
  64. { url, err in
  65. if let err {
  66. showToast(err)
  67. uploadDone = false
  68. } else if let url {
  69. voice.value = url
  70. } else {
  71. uploadDone = false
  72. }
  73. group.leave()
  74. }
  75. }
  76. }
  77. group.wait()
  78. if !uploadDone {
  79. dismissLoading()
  80. return
  81. }
  82. let input = LNEditSkillFieldsInfo()
  83. input.skillId = info.skillId
  84. input.apply = editPanel.needReview
  85. for item in info.fields {
  86. let config = LNCreateSkillFieldInfo()
  87. config.fieldCode = item.fieldCode
  88. config.value = item.value
  89. if item.type == .voice {
  90. config.duration = item.duration
  91. }
  92. input.fields.append(config)
  93. }
  94. LNGameMateManager.shared.commitSkillEdit(info: input) { [weak self] success in
  95. dismissLoading()
  96. guard let self else { return }
  97. guard success else { return }
  98. if input.apply {
  99. view.pushToSkillReview(cls: LNSkillCreateViewController.self)
  100. } else {
  101. navigationController?.popViewController(animated: true)
  102. }
  103. }
  104. }
  105. }
  106. }
  107. extension LNSkillEditViewController: LNSkillFieldBaseEditViewDelegate {
  108. func onSkillFieldBaseEditViewInputChanged(view: LNSkillFieldBaseEditView) {
  109. checkConfirmButton()
  110. }
  111. }
  112. extension LNSkillEditViewController {
  113. private func checkConfirmButton() {
  114. let allInput = editPanel.hasAllInput
  115. if allInput != confirmButton.isEnabled {
  116. confirmButton.isEnabled = allInput
  117. confirmButton.setBackgroundImage(allInput ? .primary_8 : nil, for: .normal)
  118. }
  119. }
  120. private func setupViews() {
  121. title = .init(key: "B00093")
  122. view.backgroundColor = .primary_1
  123. view.onTap { [weak self] in
  124. guard let self else { return }
  125. view.endEditing(true)
  126. }
  127. scrollView.showsHorizontalScrollIndicator = false
  128. scrollView.showsVerticalScrollIndicator = false
  129. scrollView.contentInset = .init(top: 12, left: 0, bottom: -view.commonBottomInset + 32, right: 0)
  130. scrollView.adjustKeyoard()
  131. view.addSubview(scrollView)
  132. scrollView.snp.makeConstraints { make in
  133. make.horizontalEdges.equalToSuperview().inset(16)
  134. make.top.equalToSuperview()
  135. make.bottom.equalToSuperview()
  136. }
  137. scrollView.addSubview(editPanel)
  138. editPanel.snp.makeConstraints { make in
  139. make.edges.equalToSuperview()
  140. make.width.equalToSuperview()
  141. }
  142. editPanel.delegate = self
  143. editPanel.update(info.bizCategoryName, fields: info.fields)
  144. let bottomMenu = UIView()
  145. view.addSubview(bottomMenu)
  146. bottomMenu.snp.makeConstraints { make in
  147. make.horizontalEdges.equalToSuperview()
  148. make.bottom.equalToSuperview()
  149. }
  150. let bottomGradient = CAGradientLayer()
  151. bottomGradient.colors = [
  152. UIColor.white.withAlphaComponent(0).cgColor,
  153. UIColor.white.cgColor,
  154. UIColor.white.cgColor
  155. ]
  156. bottomGradient.locations = [0, 0.5, 1]
  157. bottomGradient.startPoint = .init(x: 0, y: 0)
  158. bottomGradient.endPoint = .init(x: 0, y: 1)
  159. bottomMenu.layer.addSublayer(bottomGradient)
  160. bottomMenu.publisher(for: \.bounds).removeDuplicates().sink { [weak bottomGradient] newValue in
  161. guard let bottomGradient else { return }
  162. bottomGradient.frame = newValue
  163. }.store(in: &cancellables)
  164. confirmButton.setTitle(.init(key: "A00002"), for: .normal)
  165. confirmButton.setTitleColor(.text_1, for: .normal)
  166. confirmButton.titleLabel?.font = .heading_h3
  167. confirmButton.layer.cornerRadius = 23.5
  168. confirmButton.backgroundColor = .fill_4
  169. confirmButton.clipsToBounds = true
  170. confirmButton.isEnabled = false
  171. confirmButton.addAction(UIAction(handler: { [weak self] _ in
  172. guard let self else { return }
  173. commit()
  174. }), for: .touchUpInside)
  175. bottomMenu.addSubview(confirmButton)
  176. confirmButton.snp.makeConstraints { make in
  177. make.horizontalEdges.equalToSuperview().inset(16)
  178. make.bottom.equalToSuperview().offset(view.commonBottomInset)
  179. make.top.equalToSuperview()
  180. make.height.equalTo(47)
  181. }
  182. }
  183. }