TSAIChatHistoryVC.swift 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //
  2. // TSAIChatHistoryVC.swift
  3. // AIEmoji
  4. //
  5. // Created by 100Years on 2025/2/12.
  6. //
  7. import SwipeCellKit
  8. class TSAIChatHistoryVC: TSBaseVC {
  9. lazy var viewModel : TSAIChatHistoryVM = {
  10. let viewModel = TSAIChatHistoryVM()
  11. return viewModel
  12. }()
  13. lazy var layout: UICollectionViewFlowLayout = {
  14. let layout = UICollectionViewFlowLayout()
  15. layout.scrollDirection = .vertical
  16. layout.itemSize = CGSize(width: k_ScreenWidth-32, height: 74)
  17. layout.minimumInteritemSpacing = 10.0
  18. layout.minimumLineSpacing = 18.0
  19. layout.headerReferenceSize = CGSizeMake(k_ScreenWidth, 48)
  20. return layout
  21. }()
  22. lazy var collectionView: UICollectionView = {
  23. let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
  24. collectionView.delegate = self
  25. collectionView.dataSource = self
  26. collectionView.showsVerticalScrollIndicator = false
  27. collectionView.showsHorizontalScrollIndicator = false
  28. collectionView.backgroundColor = .clear
  29. collectionView.register(TSAIChatHistoryCell.self, forCellWithReuseIdentifier: TSAIChatHistoryCell.cellID)
  30. collectionView.register(TSAIChatHistorySectionHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: TSAIChatHistorySectionHeaderView.reuseIdentifier)
  31. if #available(iOS 11.0, *) {
  32. collectionView.contentInsetAdjustmentBehavior = .never
  33. }
  34. return collectionView
  35. }()
  36. lazy var pageNullView: TSPageNullView = {
  37. let pageNullView = TSPageNullView()
  38. pageNullView.isHidden = true
  39. return pageNullView
  40. }()
  41. var deleteAllBtn:UIButton = UIButton()
  42. override func createView() {
  43. addNormalNavBarView()
  44. setPageTitle("History".localized)
  45. deleteAllBtn = setNavigationItem("", imageName: "delete_white", direction: .right, action: #selector(deleteAll))
  46. contentView.addSubview(pageNullView)
  47. contentView.addSubview(collectionView)
  48. collectionView.snp.makeConstraints { make in
  49. make.edges.equalToSuperview()
  50. }
  51. }
  52. override func dealThings() {
  53. updateListView()
  54. }
  55. func updateListView(){
  56. pageNullView.isHidden = viewModel.historyModelChatList.count > 0 ? true : false
  57. deleteAllBtn.isHidden = !pageNullView.isHidden
  58. collectionView.reloadData()
  59. }
  60. @objc func deleteAll(){
  61. showCustomAlert(message: "Are you sure to delete".localized, deleteHandler: { [weak self] in
  62. guard let self = self else { return }
  63. viewModel.deleteAll()
  64. self.viewModel.historyModelChatList.removeAll()
  65. self.updateListView()
  66. })
  67. }
  68. }
  69. extension TSAIChatHistoryVC: UICollectionViewDataSource ,UICollectionViewDelegate {
  70. public func numberOfSections(in collectionView: UICollectionView) -> Int {
  71. return viewModel.historyModelChatList.count
  72. }
  73. public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  74. if let sectionModel = viewModel.historyModelChatList.safeObj(At: section) {
  75. return sectionModel.chatList.count
  76. }
  77. return 0
  78. }
  79. public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  80. let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TSAIChatHistoryCell.cellID, for: indexPath)
  81. if let sectionModel = viewModel.historyModelChatList.safeObj(At: indexPath.section),
  82. let itemModel = sectionModel.chatList.safeObj(At: indexPath.item),
  83. let cell = cell as? TSAIChatHistoryCell
  84. {
  85. cell.delegate = self
  86. cell.model = itemModel
  87. }
  88. return cell
  89. }
  90. public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  91. if let sectionModel = viewModel.historyModelChatList.safeObj(At: indexPath.section),
  92. let itemModel = sectionModel.chatList.safeObj(At: indexPath.item)
  93. {
  94. let chatVC = TSChatViewController()
  95. chatVC.viewModel.uiStyle = .history
  96. chatVC.viewModel.dbAIChatList = itemModel
  97. chatVC.deleteBlock = { [weak self] in
  98. guard let self = self else { return }
  99. //删除 UI 层的 cell
  100. sectionModel.chatList.remove(at: indexPath.item)
  101. if sectionModel.chatList.count == 0 {
  102. self.viewModel.historyModelChatList.remove(at: indexPath.section)
  103. }
  104. updateListView()
  105. }
  106. self.navigationController?.pushViewController(chatVC, animated: true)
  107. }
  108. }
  109. public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
  110. if let sectionModel = viewModel.historyModelChatList.safeObj(At: indexPath.section) {
  111. if kind == UICollectionView.elementKindSectionHeader {
  112. if let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TSAIChatHistorySectionHeaderView.reuseIdentifier, for: indexPath) as? TSAIChatHistorySectionHeaderView {
  113. header.titleLabel.text = sectionModel.title
  114. return header
  115. }
  116. }
  117. }
  118. return TSAIChatHistorySectionHeaderView()
  119. }
  120. }
  121. extension TSAIChatHistoryVC: SwipeCollectionViewCellDelegate {
  122. func collectionView(_ collectionView: UICollectionView, editActionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
  123. guard orientation == .right else { return nil }
  124. // 删除操作
  125. let deleteAction = SwipeAction(style: .destructive, title: nil) {[weak self] action, indexPath in
  126. guard let self = self else { return }
  127. showCustomAlert(message: "Are you sure to delete".localized, deleteHandler: {
  128. if let sectionModel = self.viewModel.historyModelChatList.safeObj(At: indexPath.section),
  129. let itemModel = sectionModel.chatList.safeObj(At: indexPath.item){
  130. sectionModel.chatList.remove(at: indexPath.item)
  131. itemModel.delete()
  132. if sectionModel.chatList.count == 0 {
  133. self.viewModel.historyModelChatList.remove(at: indexPath.section)
  134. }
  135. self.updateListView()
  136. }
  137. })
  138. }
  139. deleteAction.backgroundColor = "#E83E3E".uiColor
  140. deleteAction.image = UIImage(named: "delete_white")
  141. return [deleteAction]
  142. }
  143. func collectionView(_ collectionView: UICollectionView, editActionsOptionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
  144. var options = SwipeOptions()
  145. // options.expansionStyle = .destructive(automaticallyDelete: false) // 完全滑动时是否自动触发操作
  146. options.transitionStyle = .border // 滑动动画样式
  147. return options
  148. }
  149. }
  150. class TSAIChatHistoryCell: SwipeCollectionViewCell {
  151. override init(frame: CGRect) {
  152. super.init(frame: frame)
  153. creatUI()
  154. }
  155. required public init?(coder: NSCoder) {
  156. fatalError("init(coder:) has not been implemented")
  157. }
  158. static let cellID = "TSAIChatHistoryCell"
  159. lazy var titleLabel: UILabel = {
  160. let titleLabel = UILabel.createLabel( font:.font(size: 16.0),textColor: .white)
  161. return titleLabel
  162. }()
  163. lazy var infoLabel: UILabel = {
  164. let titleLabel = UILabel.createLabel( font:.font(size: 14.0),textColor: .white.withAlphaComponent(0.4))
  165. return titleLabel
  166. }()
  167. var model:TSDBAIChatList?{
  168. didSet{
  169. if let dbMessage = model?.messages.last {
  170. titleLabel.text = dbMessage.kindValue
  171. infoLabel.text = dbMessage.sentDate.dateTimeString
  172. }
  173. }
  174. }
  175. func creatUI() {
  176. backgroundColor = "#333333".uiColor
  177. cornerRadius = 16.0
  178. contentView.addSubview(titleLabel)
  179. titleLabel.snp.makeConstraints { make in
  180. make.top.leading.equalTo(16)
  181. make.trailing.equalTo(-16)
  182. make.height.equalTo(16)
  183. }
  184. contentView.addSubview(infoLabel)
  185. infoLabel.snp.makeConstraints { make in
  186. make.top.equalTo(44)
  187. make.leading.equalTo(16)
  188. make.trailing.equalTo(-16)
  189. make.height.equalTo(14)
  190. }
  191. }
  192. }
  193. class TSAIChatHistorySectionHeaderView: UICollectionReusableView {
  194. static let reuseIdentifier = "TSAIChatHistorySectionHeaderView"
  195. let titleLabel: UILabel = {
  196. let label = UILabel.createLabel(text: "",font: .font(size: 16),textColor: .white)
  197. return label
  198. }()
  199. override init(frame: CGRect) {
  200. super.init(frame: frame)
  201. addSubview(titleLabel)
  202. titleLabel.snp.makeConstraints { make in
  203. make.leading.equalTo(16)
  204. make.trailing.equalTo(-16)
  205. make.centerY.equalToSuperview()
  206. }
  207. }
  208. required init?(coder: NSCoder) {
  209. fatalError("init(coder:) has not been implemented")
  210. }
  211. }