TSChatInputBarVC.swift 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //
  2. // TSChatInputBarVC.swift
  3. // AIEmoji
  4. //
  5. // Created by 100Years on 2025/2/14.
  6. //
  7. import UIKit
  8. class TSChatInputBarVC: TSBaseVC, UITextViewDelegate {
  9. var sendComplete:(([Any])->Void)?
  10. //AI是否正在回答问题
  11. var isAIAnswering:Bool = false{
  12. didSet{
  13. sendEnabled(enabled: !isAIAnswering)
  14. setBtnHidden()
  15. }
  16. }
  17. lazy var InputBarView:UIView = {
  18. let InputBarView = UIView()
  19. InputBarView.backgroundColor = "#222222".uiColor
  20. InputBarView.cornerRadius = 28.0
  21. return InputBarView
  22. }()
  23. lazy var sendBtn: UIButton = {
  24. let sendBtn = UIButton.createButton(image: UIImage(named: "chat_send")) { [weak self] in
  25. guard let self = self else { return }
  26. sendMsg()
  27. }
  28. sendBtn.isEnabled = false
  29. return sendBtn
  30. }()
  31. lazy var stopBtn: UIButton = {
  32. let stopBtn = UIButton.createButton(image: UIImage(named: "chat_stop")) { [weak self] in
  33. guard let self = self else { return }
  34. NotificationCenter.default.post(name: .kAIStopRespondNotification, object: nil, userInfo: nil)
  35. }
  36. return stopBtn
  37. }()
  38. lazy var magnifyBtn: UIButton = {
  39. let magnifyBtn = UIButton.createButton(image: UIImage(named: "chat_send_magnify")) { [weak self] in
  40. guard let self = self else { return }
  41. let vc = TSChatInputFullScreenVC()
  42. vc.text = textView.text
  43. vc.sendComplete = { [weak self] date in
  44. guard let self = self else { return }
  45. if let text = date.first as? String {
  46. textView.text = text
  47. textView.resignFirstResponder()
  48. textDidChange()
  49. scrollTextViewToBottom()
  50. sendComplete?(date)
  51. }
  52. }
  53. vc.closeComplete = { [weak self] text in
  54. guard let self = self else { return }
  55. textView.text = text
  56. textView.resignFirstResponder()
  57. textDidChange()
  58. scrollTextViewToBottom()
  59. }
  60. kPresentModalVC(target: self, modelVC: vc)
  61. }
  62. magnifyBtn.isHidden = true
  63. return magnifyBtn
  64. }()
  65. private let minHeight: CGFloat = 56//24
  66. private let maxHeight: CGFloat = 154
  67. lazy var textView: TSCustomTextView = {
  68. let textView = TSCustomTextView()
  69. textView.backgroundColor = .clear
  70. textView.textColor = .white
  71. textView.delegate = self
  72. textView.font = .font(size: 16)
  73. textView.clipsToBounds = true
  74. textView.isScrollEnabled = false
  75. textView.tintColor = .themeColor
  76. textView.returnKeyType = .send
  77. textView.placeholder = "Message chat".localized
  78. textView.placeholderColor = .white.withAlphaComponent(0.4)
  79. textView.placeholderLabel.font = .font(size: 16.0)
  80. textView.textInsets = UIEdgeInsets(top: 18, left: 16, bottom: 14, right: 0)
  81. return textView
  82. }()
  83. override func createView() {
  84. setNavBarViewHidden(true)
  85. view.backgroundColor = .clear
  86. contentView.addSubview(InputBarView)
  87. InputBarView.addSubview(textView)
  88. InputBarView.addSubview(magnifyBtn)
  89. InputBarView.addSubview(stopBtn)
  90. InputBarView.addSubview(sendBtn)
  91. InputBarView.snp.makeConstraints { make in
  92. make.leading.equalTo(16)
  93. make.trailing.equalTo(-16)
  94. make.top.equalTo(12)
  95. make.bottom.equalTo(-12)
  96. }
  97. textView.snp.makeConstraints { make in
  98. make.leading.equalTo(0)
  99. make.trailing.equalTo(-60)
  100. make.top.equalTo(0)
  101. make.bottom.equalTo(0)
  102. make.height.equalTo(minHeight)
  103. }
  104. stopBtn.snp.makeConstraints { make in
  105. make.trailing.equalTo(-16)
  106. make.bottom.equalTo(-16)
  107. make.width.equalTo(24)
  108. make.height.equalTo(24)
  109. }
  110. sendBtn.snp.makeConstraints { make in
  111. make.trailing.equalTo(-16)
  112. make.bottom.equalTo(-16)
  113. make.width.equalTo(24)
  114. make.height.equalTo(24)
  115. }
  116. magnifyBtn.snp.makeConstraints { make in
  117. make.trailing.equalTo(-16)
  118. make.top.equalTo(16)
  119. make.width.equalTo(24)
  120. make.height.equalTo(24)
  121. }
  122. }
  123. override func dealThings() {
  124. // 监听文本变化事件
  125. NotificationCenter.default.addObserver(self, selector: #selector(textDidChange), name: UITextView.textDidChangeNotification, object: textView)
  126. NotificationCenter.default.addObserver(self, selector: #selector(handleAIAnsweringNotification(_:)), name: .kAIAnsweringNotification, object: nil)
  127. }
  128. func sendMsg(){
  129. if sendBtn.isEnabled == false {
  130. return
  131. }
  132. // if textView.text.replacingOccurrences(of: " ", with: "").count <= 0 {
  133. // return
  134. // }
  135. if let string = textView.text {
  136. sendComplete?([string])
  137. textView.resignFirstResponder()
  138. }
  139. }
  140. func sendEnabled(enabled:Bool){
  141. if enabled == true,
  142. isAIAnswering == false,
  143. textView.text.replacingOccurrences(of: " ", with: "").count > 0 {
  144. sendBtn.isEnabled = true
  145. }else{
  146. sendBtn.isEnabled = false
  147. }
  148. }
  149. func emptyInput() {
  150. textView.text = ""
  151. textDidChange()
  152. magnifyBtn.isHidden = true
  153. }
  154. @objc func handleAIAnsweringNotification(_ notification: Notification) {
  155. if let userInfo = notification.userInfo, let boolValue = userInfo[kIsAIAnswering] as? Bool {
  156. isAIAnswering = boolValue
  157. }
  158. }
  159. func setBtnHidden() {
  160. if isAIAnswering {
  161. sendBtn.isHidden = true
  162. stopBtn.isHidden = false
  163. }else{
  164. sendBtn.isHidden = false
  165. stopBtn.isHidden = true
  166. }
  167. }
  168. deinit {
  169. // 移除通知监听
  170. NotificationCenter.default.removeObserver(self, name: UITextView.textDidChangeNotification, object: textView)
  171. }
  172. }
  173. extension TSChatInputBarVC {
  174. @objc private func textDidChange() {
  175. // 计算输入框的内容高度
  176. let sizeToFit = CGSize(width: textView.bounds.width, height: .greatestFiniteMagnitude)
  177. let estimatedSize = textView.sizeThatFits(sizeToFit)
  178. // 根据内容高度调整输入框的高度
  179. var newHeight = estimatedSize.height
  180. if newHeight <= minHeight {
  181. newHeight = minHeight
  182. textView.isScrollEnabled = false
  183. magnifyBtn.isHidden = true
  184. } else if newHeight > maxHeight {
  185. newHeight = maxHeight
  186. textView.isScrollEnabled = true
  187. magnifyBtn.isHidden = false
  188. } else {
  189. textView.isScrollEnabled = false
  190. magnifyBtn.isHidden = true
  191. }
  192. sendEnabled(enabled: textView.text.count > 0)
  193. // 更新输入框的高度
  194. textView.snp.updateConstraints { make in
  195. make.height.equalTo(newHeight)
  196. }
  197. }
  198. private func scrollTextViewToBottom() {
  199. let bottomOffset = CGPoint(x: 0, y: textView.contentSize.height - textView.bounds.size.height)
  200. textView.setContentOffset(bottomOffset, animated: true)
  201. }
  202. }
  203. extension TSChatInputBarVC {
  204. // 实现 UITextViewDelegate 协议方法,控制 return 键行为
  205. func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
  206. if text == "\n" {
  207. // 当输入为换行符(即按下 return 键)时,执行相应操作
  208. sendMsg()
  209. return false
  210. }
  211. return true
  212. }
  213. }