LNProfileFeedProvider.swift 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //
  2. // LNProfileFeedProvider.swift
  3. // Gami
  4. //
  5. // Created by OneeChan on 2026/3/2.
  6. //
  7. import Foundation
  8. import UIKit
  9. import MJRefresh
  10. class LNProfileFeedProvider: NSObject, LNProfileBaseProvider {
  11. private(set) var title: String = .init(key: "A00303")
  12. private weak var tableView: UITableView?
  13. private var curDetail: LNUserProfileVO?
  14. private var loading = false
  15. private var feedList: [LNFeedItemVO] = []
  16. private var nextTag: String?
  17. var numberOfCell: Int {
  18. feedList.count
  19. }
  20. override init() {
  21. super.init()
  22. LNEventDeliver.addObserver(self)
  23. }
  24. func registerCell(tableView: UITableView) {
  25. tableView.register(LNProfileFeedItemCell.self, forCellReuseIdentifier: LNProfileFeedItemCell.className)
  26. self.tableView = tableView
  27. let footer = MJRefreshAutoNormalFooter { [weak self] in
  28. guard let self else { return }
  29. self.loadList()
  30. }
  31. footer.setTitle("", for: .noMoreData)
  32. footer.setTitle(.init(key: "A00046"), for: .idle)
  33. footer.endRefreshingCompletionBlock = { [weak self] in
  34. guard let self else { return }
  35. loadList()
  36. }
  37. tableView.mj_footer = footer
  38. }
  39. func buildCell(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
  40. let cell = tableView.dequeueReusableCell(withIdentifier: LNProfileFeedItemCell.className, for: indexPath) as! LNProfileFeedItemCell
  41. let data = feedList[indexPath.row]
  42. cell.update(data)
  43. return cell
  44. }
  45. func onAppear() {
  46. autoPlayVideo()
  47. }
  48. func update(_ detail: LNUserProfileVO) {
  49. curDetail = detail
  50. loadList()
  51. }
  52. }
  53. extension LNProfileFeedProvider: LNFeedManagerNotify {
  54. func onPostFeedSuccess() {
  55. guard let curDetail else { return }
  56. LNFeedManager.shared.getFeedList(uid: curDetail.userNo, next: nil) { [weak self] res in
  57. guard let self else { return }
  58. guard let res else { return }
  59. let curFirst = feedList.first?.id ?? ""
  60. if let index = res.list.firstIndex(where: { $0.id == curFirst }) {
  61. let newItems = res.list[..<index]
  62. feedList.insert(contentsOf: newItems, at: 0)
  63. } else {
  64. feedList.insert(contentsOf: res.list, at: 0)
  65. }
  66. tableView?.reloadData()
  67. }
  68. }
  69. func onFeedDelete(id: String) {
  70. feedList.removeAll { $0.id == id }
  71. tableView?.reloadData()
  72. }
  73. }
  74. extension LNProfileFeedProvider: UITableViewDelegate {
  75. func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
  76. guard let view = cell as? LNProfileFeedItemCell, view.isVideo else {
  77. return
  78. }
  79. view.stopPlayVideoIfNeed()
  80. }
  81. func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
  82. autoPlayVideo()
  83. }
  84. func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
  85. autoPlayVideo()
  86. }
  87. func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
  88. if !decelerate {
  89. autoPlayVideo()
  90. }
  91. }
  92. }
  93. extension LNProfileFeedProvider {
  94. private func autoPlayVideo() {
  95. guard let tableView else { return }
  96. let visibleRows = tableView.visibleCells.compactMap { $0 as? LNProfileFeedItemCell }
  97. let videoCells = visibleRows.compactMap {
  98. if $0.isVideo {
  99. $0
  100. } else {
  101. nil
  102. }
  103. }
  104. if videoCells.isEmpty { return }
  105. else {
  106. let first = videoCells.first {
  107. tableView.contentOffset.y - $0.frame.minY < 100
  108. && tableView.contentOffset.y + tableView.bounds.height - $0.frame.minY > 300
  109. }
  110. videoCells.forEach {
  111. if $0 != first {
  112. $0.stopPlayVideoIfNeed()
  113. } else {
  114. $0.autoPlayVideoIfNeed()
  115. }
  116. }
  117. }
  118. }
  119. }
  120. extension LNProfileFeedProvider {
  121. private func loadList() {
  122. guard let curDetail, !loading else { return }
  123. loading = true
  124. let curNext = nextTag ?? ""
  125. LNFeedManager.shared.getFeedList(uid: curDetail.userNo, next: curNext) { [weak self] res in
  126. guard let self else { return }
  127. loading = false
  128. if let res {
  129. if curNext.isEmpty {
  130. feedList.removeAll()
  131. }
  132. feedList.append(contentsOf: res.list)
  133. self.nextTag = nextTag
  134. tableView?.reloadData()
  135. }
  136. if nextTag?.isEmpty != false {
  137. tableView?.mj_footer?.endRefreshingWithNoMoreData()
  138. } else {
  139. tableView?.mj_footer?.endRefreshing()
  140. }
  141. }
  142. }
  143. }