LNAutoReplyEditViewController.swift 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //
  2. // LNAutoReplyEditViewController.swift
  3. // Gami
  4. //
  5. // Created by OneeChan on 2026/3/10.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. extension UIView {
  11. func pushToAutoRelyEdit(num: Int, item: LNAutoReplyVO) {
  12. let vc = LNAutoReplyEditViewController()
  13. vc.update(num: num, item: item)
  14. navigationController?.pushViewController(vc, animated: true)
  15. }
  16. }
  17. class LNAutoReplyEditViewController: LNViewController {
  18. private let editView = UIView()
  19. private let titleLabel = UILabel()
  20. private let textEdit = LNCommonTextView()
  21. private let voiceEdit = LNVoiceEditView()
  22. private let rejectView = UIView()
  23. private let rejectLabel = UILabel()
  24. private let commitButton = UIButton()
  25. private var curItem: LNAutoReplyVO?
  26. override func viewDidLoad() {
  27. super.viewDidLoad()
  28. setupViews()
  29. }
  30. func update(num: Int, item: LNAutoReplyVO) {
  31. textEdit.isHidden = true
  32. voiceEdit.isHidden = true
  33. rejectView.isHidden = true
  34. titleLabel.text = .init(key: "B00114", num + 1)
  35. switch item.type {
  36. case .text:
  37. textEdit.isHidden = false
  38. textEdit.textView.text = item.textContent
  39. case .voice:
  40. voiceEdit.isHidden = false
  41. voiceEdit.update(item.voiceUrl, duration: item.voiceDuration)
  42. }
  43. commitButton.isEnabled = false
  44. commitButton.setBackgroundImage(nil, for: .normal)
  45. switch item.status {
  46. case .pass:
  47. commitButton.setTitle(.init(key: "A00240"), for: .normal)
  48. case .reject:
  49. commitButton.setTitle(.init(key: "B00121"), for: .normal)
  50. rejectLabel.text = item.reviewReason
  51. rejectView.isHidden = false
  52. case .reviewing:
  53. break
  54. }
  55. curItem = item
  56. }
  57. }
  58. extension LNAutoReplyEditViewController {
  59. private func commitItem(_ item: LNAutoReplyVO) {
  60. if item.id.isEmpty {
  61. LNGameMateManager.shared.createAutoReplay(item: item) { [weak self] success in
  62. guard let self else { return }
  63. guard success else { return }
  64. view.pushToSkillReview(cls: LNAutoReplyEditViewController.self)
  65. }
  66. } else {
  67. LNGameMateManager.shared.updateAutoReplay(item: item) { [weak self] success in
  68. guard let self else { return }
  69. guard success else { return }
  70. navigationController?.popViewController(animated: true)
  71. }
  72. }
  73. }
  74. }
  75. extension LNAutoReplyEditViewController: UITextViewDelegate, LNVoiceEditViewDelegate {
  76. func onVoiceChanged() {
  77. checkSubmit()
  78. }
  79. func textViewDidChange(_ textView: UITextView) {
  80. checkSubmit()
  81. }
  82. }
  83. extension LNAutoReplyEditViewController {
  84. private func checkSubmit() {
  85. let enable = switch curItem?.type {
  86. case .text:
  87. textEdit.text.isEmpty == false && textEdit.text != curItem?.textContent
  88. case .voice:
  89. voiceEdit.voiceInfo.0 != nil && voiceEdit.voiceInfo.1 > 0 && voiceEdit.voiceInfo.0 != curItem?.voiceUrl
  90. case nil:
  91. false
  92. }
  93. if commitButton.isEnabled != enable {
  94. commitButton.isEnabled = enable
  95. if enable {
  96. commitButton.setBackgroundImage(.primary_8, for: .normal)
  97. } else {
  98. commitButton.setBackgroundImage(nil, for: .normal)
  99. }
  100. }
  101. }
  102. private func setupViews() {
  103. title = .init(key: "B00112")
  104. view.backgroundColor = .primary_1
  105. view.onTap { [weak self] in
  106. guard let self else { return }
  107. view.endEditing(true)
  108. }
  109. if curItem?.id.isEmpty == false {
  110. let delete = UIButton()
  111. delete.setImage(.icDelete.withTintColor(.text_5, renderingMode: .alwaysOriginal), for: .normal)
  112. delete.addAction(UIAction(handler: { [weak self] _ in
  113. guard let self else { return }
  114. LNCommonAlertView.showCommonDeleteAlert { [weak self] in
  115. guard let self else { return }
  116. guard let curItem else { return }
  117. LNGameMateManager.shared.deleteAutoReplay(id: curItem.id) { [weak self] success in
  118. guard let self else { return }
  119. guard success else { return }
  120. navigationController?.popViewController(animated: true)
  121. }
  122. }
  123. }), for: .touchUpInside)
  124. setRightButton(delete)
  125. }
  126. let stackView = UIStackView()
  127. stackView.axis = .vertical
  128. stackView.spacing = 10
  129. view.addSubview(stackView)
  130. stackView.snp.makeConstraints { make in
  131. make.horizontalEdges.equalToSuperview().inset(16)
  132. make.top.equalToSuperview().offset(12)
  133. }
  134. stackView.addArrangedSubview(buildWelcomeDetailView())
  135. stackView.addArrangedSubview(buildReject())
  136. commitButton.layer.cornerRadius = 23.5
  137. commitButton.clipsToBounds = true
  138. commitButton.backgroundColor = .fill_4
  139. commitButton.setTitleColor(.text_1, for: .normal)
  140. commitButton.titleLabel?.font = .heading_h3
  141. commitButton.addAction(UIAction(handler: { [weak self] _ in
  142. guard let self else { return }
  143. guard let curItem else { return }
  144. switch curItem.type {
  145. case .text:
  146. curItem.textContent = textEdit.text
  147. commitItem(curItem)
  148. case .voice:
  149. let (url, duration) = voiceEdit.voiceInfo
  150. guard let url else { return }
  151. showLoading()
  152. LNFileUploader.shared.startUpload(type: .voice, fileURL: URL(fileURLWithPath: url), progressHandler: nil)
  153. { [weak self] url, err in
  154. dismissLoading()
  155. guard let self else { return }
  156. if let url, err == nil {
  157. curItem.voiceUrl = url
  158. curItem.voiceDuration = duration
  159. commitItem(curItem)
  160. } else {
  161. showToast(err)
  162. }
  163. }
  164. }
  165. }), for: .touchUpInside)
  166. view.addSubview(commitButton)
  167. commitButton.snp.makeConstraints { make in
  168. make.horizontalEdges.equalToSuperview().inset(16)
  169. make.bottom.equalToSuperview().offset(view.commonBottomInset)
  170. make.height.equalTo(47)
  171. }
  172. }
  173. private func buildWelcomeDetailView() -> UIView {
  174. editView.layer.cornerRadius = 12
  175. editView.backgroundColor = .fill
  176. titleLabel.font = .heading_h4
  177. titleLabel.textColor = .text_5
  178. editView.addSubview(titleLabel)
  179. titleLabel.snp.makeConstraints { make in
  180. make.horizontalEdges.equalToSuperview().inset(16)
  181. make.top.equalToSuperview().offset(16)
  182. }
  183. let stackView = UIStackView()
  184. stackView.axis = .vertical
  185. stackView.spacing = 10
  186. editView.addSubview(stackView)
  187. stackView.snp.makeConstraints { make in
  188. make.horizontalEdges.equalToSuperview().inset(16)
  189. make.top.equalTo(titleLabel.snp.bottom).offset(8)
  190. make.bottom.equalToSuperview().offset(-16)
  191. }
  192. textEdit.delegate = self
  193. textEdit.maxInput = LNGameMateManager.AutoReplayMaxInput
  194. textEdit.placeholderLabel.text = .init(key: "B00126")
  195. textEdit.snp.makeConstraints { make in
  196. make.height.equalTo(150)
  197. }
  198. stackView.addArrangedSubview(textEdit)
  199. voiceEdit.delegate = self
  200. stackView.addArrangedSubview(voiceEdit)
  201. return editView
  202. }
  203. private func buildReject() -> UIView {
  204. rejectView.layer.cornerRadius = 12
  205. rejectView.backgroundColor = .fill
  206. let titleLabel = UILabel()
  207. titleLabel.text = .init(key: "B00127")
  208. titleLabel.font = .heading_h4
  209. titleLabel.textColor = .text_5
  210. rejectView.addSubview(titleLabel)
  211. titleLabel.snp.makeConstraints { make in
  212. make.horizontalEdges.equalToSuperview().inset(16)
  213. make.top.equalToSuperview().offset(16)
  214. }
  215. rejectLabel.font = .body_s
  216. rejectLabel.textColor = .text_4
  217. rejectView.addSubview(rejectLabel)
  218. rejectLabel.snp.makeConstraints { make in
  219. make.horizontalEdges.equalToSuperview().inset(16)
  220. make.top.equalTo(titleLabel.snp.bottom).offset(8)
  221. make.bottom.equalToSuperview().offset(-16)
  222. }
  223. return rejectView
  224. }
  225. }
  226. #if DEBUG
  227. import SwiftUI
  228. struct LNAutoReplyEditViewControllerPreview: UIViewControllerRepresentable {
  229. func makeUIViewController(context: Context) -> some UIViewController {
  230. LNAutoReplyEditViewController()
  231. }
  232. func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
  233. }
  234. }
  235. #Preview(body: {
  236. LNAutoReplyEditViewControllerPreview()
  237. })
  238. #endif