MVPlayViewController.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. //
  2. // MVPlayViewController.swift
  3. // MusicVideoPlus
  4. //
  5. // Created by SanW on 2021/6/22.
  6. //
  7. import BFFramework
  8. import UIKit
  9. import BFUIKit
  10. import WechatOpenSDK
  11. class MVPlayViewController: BFBaseViewController {
  12. var itemsList: [PQVideoListModel] = Array<PQVideoListModel>.init()
  13. var pageNum: Int = 1
  14. var currentIndex: IndexPath?
  15. var currentActionBtn: UIButton? // 记录上次点击按钮
  16. var currentVideoData: PQVideoListModel? // 记录上次点击数据
  17. var isRequesting: Bool = false // 是否正在请求数据
  18. var isPlayEnd: Bool = false // 是否播放结束
  19. lazy var leftBtn: UIButton = {
  20. let leftBtn = UIButton(type: .custom)
  21. leftBtn.frame = CGRect(x: 0, y: cDevice_iPhoneStatusBarHei, width: cDefaultMargin * 4, height: cDefaultMargin * 4)
  22. leftBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -5, right: 0)
  23. leftBtn.tintColor = UIColor.white
  24. leftBtn.setImage((imageInUIKit(by: "icon_detail_back") ?? UIImage()).withRenderingMode(.alwaysTemplate), for: .normal)
  25. leftBtn.addTarget(self, action: #selector(backBtnClick), for: .touchUpInside)
  26. return leftBtn
  27. }()
  28. lazy var collectionView: UICollectionView = {
  29. let layout = UICollectionViewFlowLayout()
  30. layout.minimumLineSpacing = 0
  31. layout.sectionInset = UIEdgeInsets.zero
  32. layout.minimumInteritemSpacing = 0
  33. layout.itemSize = view.frame.size
  34. let collectionView = UICollectionView(frame: view.frame, collectionViewLayout: layout)
  35. collectionView.scrollsToTop = false
  36. collectionView.isPagingEnabled = true
  37. collectionView.showsVerticalScrollIndicator = false
  38. collectionView.register(MVPlayControlViewCell.self, forCellWithReuseIdentifier: String(describing: MVPlayControlViewCell.self))
  39. collectionView.delegate = self
  40. collectionView.dataSource = self
  41. if #available(iOS 11.0, *) {
  42. collectionView.contentInsetAdjustmentBehavior = .never
  43. } else {
  44. automaticallyAdjustsScrollViewInsets = false
  45. }
  46. collectionView.addRefreshView(type: .REFRESH_TYPE_HEADER) { [weak self] _ in
  47. self?.loadRequestData(isRefresh: true)
  48. }
  49. // MJRefreshAutoNormalFooter,MJRefreshAutoFooter,MJRefreshBackFooter
  50. // MJRefreshFooter 无法显示noMoreData文字
  51. let footer = MJRefreshAutoStateFooter.init { [weak self] in
  52. self?.loadRequestData(isRefresh: false)
  53. }
  54. footer.setTitle("暂时没有更多了", for: .noMoreData)
  55. footer.setTitle("精彩内容正在加载中...", for: .refreshing)
  56. collectionView.mj_footer = footer
  57. return collectionView
  58. }()
  59. override func viewDidLoad() {
  60. super.viewDidLoad()
  61. PQSingletoVideoPlayer.shared.stopPlayer()
  62. view.addSubview(collectionView)
  63. view.addSubview(leftBtn)
  64. if itemsList.count <= 0 {
  65. loadRequestData()
  66. }
  67. if currentIndex != nil, itemsList.count > (currentIndex?.item ?? 0) {
  68. collectionView.contentOffset = CGPoint(x: 0, y: CGFloat(currentIndex?.item ?? 0) * view.frame.size.height)
  69. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) { [weak self] in
  70. self?.scrollViewDidEndDecelerating(self!.collectionView)
  71. }
  72. }
  73. PQSingletoVideoPlayer.shared.playStatusBloc = { [weak self] status in
  74. switch status {
  75. case .PQVIDEO_PLAY_STATUS_BEGIN:
  76. self?.isPlayEnd = false
  77. case .PQVIDEO_PLAY_STATUS_END:
  78. self?.isPlayEnd = true
  79. if ((self?.currentIndex?.item ?? 0) + 1) < (self?.itemsList.count ?? 0) {
  80. self?.collectionView.contentOffset = CGPoint(x: 0, y: CGFloat((self?.currentIndex?.item ?? 0) + 1) * (self!.collectionView.frame.height))
  81. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) { [weak self] in
  82. self?.scrollViewDidEndDecelerating(self!.collectionView)
  83. }
  84. } else {
  85. (self?.collectionView.visibleCell() as? MVPlayControlViewCell)?.tagClick()
  86. self?.loadRequestData(isRefresh: false)
  87. }
  88. if (self?.currentIndex?.item ?? 0) >= ((self?.itemsList.count ?? 0) - 2) {
  89. self?.loadRequestData(isRefresh: false)
  90. }
  91. case .PQVIDEO_PLAY_STATUS_RECONNECT:
  92. cShowHUB(superView: self?.view, msg: "当前网络不佳,尝试重新连接")
  93. case .PQVIDEO_PLAY_STATUS_DISCONNECT:
  94. cShowHUB(superView: self?.view, msg: "重新连接失败,请点击重试")
  95. (self?.collectionView.visibleCell() as? MVPlayControlViewCell)?.pauseClick(isHidden: false, isSelected: true)
  96. default:
  97. break
  98. }
  99. }
  100. PQSingletoVideoPlayer.shared.progressBloc = { [weak self] _, playProgress, duration in
  101. (self?.collectionView.visibleCell() as? MVPlayControlViewCell)?.updateProgress(progress: playProgress / duration)
  102. }
  103. PQNotification.addObserver(self, selector: #selector(didBecomeActiveNotification), name: UIApplication.didBecomeActiveNotification, object: nil)
  104. PQNotification.addObserver(self, selector: #selector(enterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
  105. PQNotification.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
  106. }
  107. override func viewDidAppear(_ animated: Bool) {
  108. super.viewDidAppear(animated)
  109. PQSingletoVideoPlayer.shared.resumePlayer()
  110. }
  111. override func viewDidDisappear(_ animated: Bool) {
  112. super.viewDidDisappear(animated)
  113. PQSingletoVideoPlayer.shared.pausePlayer()
  114. }
  115. /// 请求网络数据
  116. /// - Parameter isRefresh: <#isRefresh description#>
  117. /// - Returns: <#description#>
  118. func loadRequestData(isRefresh: Bool = true, isAutoPlay _: Bool = false) {
  119. if !isNetConnected() {
  120. cShowHUB(superView: view, msg: "没有网络连接")
  121. collectionView.mj_footer?.endRefreshing(completionBlock: { [weak self] in
  122. self?.collectionView.setContentOffset(CGPoint(x: 0, y: (self?.collectionView.contentSize.height ?? 0) - (self?.collectionView.frame.height ?? 0)), animated: false)
  123. })
  124. return
  125. }
  126. if isRequesting {
  127. return
  128. }
  129. isRequesting = true
  130. if isRefresh {
  131. pageNum = 1
  132. } else {
  133. pageNum = pageNum + 1
  134. }
  135. MVMineViewModel.userVideoListData(pageNum: pageNum) { [weak self] videoList, _ in
  136. self?.isRequesting = false
  137. if videoList != nil, (videoList?.count ?? 0) > 0 {
  138. if isRefresh {
  139. self?.itemsList = videoList!
  140. } else {
  141. self?.itemsList = self!.itemsList + videoList!
  142. }
  143. self?.collectionView.reloadData()
  144. if self?.currentIndex == nil {
  145. self?.scrollViewDidEndDecelerating(self!.collectionView)
  146. } else if self?.isPlayEnd ?? false, ((self?.currentIndex?.item ?? 0) + 1) < (self?.itemsList.count ?? 0) {
  147. self?.collectionView.contentOffset = CGPoint(x: 0, y: CGFloat((self?.currentIndex?.item ?? 0) + 1) * (self!.collectionView.frame.height))
  148. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) { [weak self] in
  149. self?.scrollViewDidEndDecelerating(self!.collectionView)
  150. }
  151. }
  152. } else {
  153. self?.pageNum = (self?.pageNum ?? 1) - 1
  154. }
  155. if isRefresh {
  156. self?.collectionView.mj_header?.endRefreshing()
  157. self?.collectionView.mj_footer?.resetNoMoreData()
  158. } else {
  159. self?.collectionView.mj_footer?.endRefreshing()
  160. }
  161. if (videoList?.count ?? 0) < 20, videoList != nil {
  162. self?.collectionView.mj_footer?.endRefreshingWithNoMoreData()
  163. }
  164. }
  165. }
  166. deinit {
  167. PQNotification.removeObserver(self)
  168. PQSingletoVideoPlayer.shared.progressBloc = nil
  169. PQSingletoVideoPlayer.shared.playStatusBloc = nil
  170. PQSingletoVideoPlayer.shared.stopPlayer()
  171. }
  172. }
  173. extension MVPlayViewController: UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
  174. func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int {
  175. return itemsList.count
  176. }
  177. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  178. let itemData = itemsList[indexPath.item]
  179. let cell = MVPlayControlViewCell.playControlCell(collectionView: collectionView, indexPath: indexPath)
  180. cell.videoData = itemData
  181. cell.btnClickHandle = { [weak self] sender, videoData in
  182. self?.btnClickHandle(sender: sender, videoData: videoData)
  183. }
  184. return cell
  185. }
  186. func collectionView(_: UICollectionView, didSelectItemAt _: IndexPath) {}
  187. func scrollViewDidEndDecelerating(_: UIScrollView) {
  188. if itemsList.count <= 0 {
  189. PQSingletoVideoPlayer.shared.stopPlayer()
  190. return
  191. }
  192. let cell: MVPlayControlViewCell? = collectionView.visibleCell() as? MVPlayControlViewCell
  193. cell?.pauseClick()
  194. if cell == nil {
  195. return
  196. }
  197. let indexPath = collectionView.indexPath(for: cell!)
  198. let itemData = itemsList[indexPath?.item ?? 0]
  199. if currentIndex != nil, currentIndex?.item == indexPath?.item, PQSingletoVideoPlayer.shared.playControllerView != nil {
  200. PQSingletoVideoPlayer.shared.configPlyer(videoData: itemData, controllerView: cell!.coverImageView, renderMode: itemData.height <= itemData.width ? .RENDER_MODE_FILL_EDGE : .RENDER_MODE_FILL_SCREEN)
  201. PQSingletoVideoPlayer.shared.resetPlayer()
  202. return
  203. }
  204. currentIndex = indexPath
  205. itemData.playProgress = 0
  206. PQSingletoVideoPlayer.shared.configPlyer(videoData: itemData, controllerView: cell!.coverImageView, renderMode: itemData.height <= itemData.width ? .RENDER_MODE_FILL_EDGE : .RENDER_MODE_FILL_SCREEN)
  207. PQSingletoVideoPlayer.shared.resetPlayer()
  208. if (indexPath?.item ?? 0) >= itemsList.count - 2 {
  209. loadRequestData(isRefresh: false)
  210. }
  211. }
  212. /// 按钮点击处理
  213. /// - Parameters:
  214. /// - sender: <#sender description#>
  215. /// - videoData: <#videoData description#>
  216. /// - Returns: <#description#>
  217. func btnClickHandle(sender: UIButton, videoData: PQVideoListModel?) {
  218. switch sender.tag {
  219. case 1: // 暂停/播放
  220. if sender.isHidden {
  221. PQSingletoVideoPlayer.shared.startPlayr()
  222. } else {
  223. PQSingletoVideoPlayer.shared.pausePlayer()
  224. }
  225. case 2: // 昵称
  226. break
  227. case 3: // 做同款
  228. let navVc: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController) as? UINavigationController
  229. (navVc?.viewControllers.first as? MVHomeController)?.jumpToDetailVc(type: 2, videoData: videoData)
  230. case 4: // 分享好友
  231. if !isNetConnected() {
  232. cShowHUB(superView: view, msg: "没有网络连接")
  233. return
  234. }
  235. if !PQSingletoWXApiUtil.shared.isInstallWX() {
  236. cShowHUB(superView: view, msg: "您还未安装微信客户端!")
  237. return
  238. }
  239. cShowHUB(superView: nil, msg: nil)
  240. let shareId = getUniqueId(desc: "\(videoData?.uniqueId ?? "")shareId")
  241. PQBaseViewModel.wxFriendShareInfo(videoId: (videoData?.uniqueId)!) { [weak self] imagePath, title, shareWeappRawId, msg in
  242. if msg != nil {
  243. cShowHUB(superView: self?.view, msg: "网络不佳哦")
  244. return
  245. }
  246. PQSingletoWXApiUtil.shared.share(type: 3, scene: Int32(WXSceneSession.rawValue), shareWeappRawId: shareWeappRawId, title: title, description: title, imageUrl: imagePath, path: videoData?.videoPath, videoId: (videoData?.uniqueId)!, pageSource: videoData?.pageSource ?? .sp_category, shareId: shareId).wxApiUtilHander = { _, _ in
  247. self?.currentActionBtn = sender
  248. self?.currentVideoData = videoData
  249. }
  250. cHiddenHUB(superView: nil)
  251. }
  252. // 分享好友上报
  253. reportUpload(isFriend: true, openId: "", shareId: shareId, videoData: videoData)
  254. case 5: // 分享朋友圈
  255. if !isNetConnected() {
  256. cShowHUB(superView: view, msg: "没有网络连接")
  257. return
  258. }
  259. if !PQSingletoWXApiUtil.shared.isInstallWX() {
  260. cShowHUB(superView: view, msg: "您还未安装微信客户端!")
  261. return
  262. }
  263. let shareId = getUniqueId(desc: "\(videoData?.uniqueId ?? "")shareId")
  264. PQBaseViewModel.h5ShareLinkInfo(videoId: videoData?.uniqueId ?? "", pageSource: videoData?.pageSource ?? .sp_category) { [weak self] path, _ in
  265. cHiddenHUB(superView: nil)
  266. if path != nil {
  267. //判断shareText是否有效
  268. var shareText = ""
  269. shareText = videoData?.title?.replacingOccurrences(of: "\n", with: "") ?? ""
  270. shareText = shareText.replacingOccurrences(of: " ", with: "")
  271. if(shareText.count == 0){
  272. shareText = "\(BFLoginUserInfo.shared.nickName)made a music video for you"
  273. }
  274. PQSingletoWXApiUtil.shared.share(type: 1, scene: Int32(WXSceneTimeline.rawValue), title:shareText , description: "", imageUrl: videoData?.shareImgPath, path: path, videoId: (videoData?.uniqueId)!, pageSource: videoData?.pageSource ?? .sp_category, shareId: shareId).wxApiUtilHander = { _, _ in
  275. self?.currentActionBtn = sender
  276. self?.currentVideoData = videoData
  277. }
  278. } else {
  279. cShowHUB(superView: self?.view, msg: "没有网络连接")
  280. }
  281. }
  282. // 分享朋友圈上报
  283. reportUpload(isFriend: false, openId: "", shareId: shareId, videoData: videoData)
  284. default:
  285. break
  286. }
  287. }
  288. func reportUpload(isFriend: Bool, openId _: String, shareId: String, videoData: PQVideoListModel?) {
  289. // 分享上报
  290. PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Action, videoData: videoData, pageSource: nil, businessType: isFriend ? .bt_videoShareFriend : .bt_videoShareH5, objectType: nil, extParams: nil, shareId: shareId, videoIds: nil, playId: PQSingletoVideoPlayer.shared.playId)
  291. if isFriend {
  292. PQEventTrackViewModel.shareReportUpload(videoId: videoData?.uniqueId ?? "0", pageSource: videoData!.pageSource, recommendId: videoData?.recommendId, recommendLogVO: videoData?.recommendLogVO, flowPool: nil, abInfoData: videoData?.abInfoData, measureType: videoData?.measureType, measureId: videoData?.measureId, businessType: isFriend ? .bt_videoShareFriend : .bt_videoShareH5, targetUid: videoData?.userInfo?.uid, shareId: shareId)
  293. PQEventTrackViewModel.shareReportUpload(screenType: 3, videoId: videoData?.uniqueId ?? "0", pageSource: videoData!.pageSource, recommendId: videoData?.recommendId, recommendLogVO: videoData?.recommendLogVO, flowPool: nil, abInfoData: videoData?.abInfoData, measureType: videoData?.measureType, measureId: videoData?.measureId, businessType: isFriend ? .bt_videoShareFriend : .bt_videoShareH5, targetUid: videoData?.userInfo?.uid, shareId: shareId)
  294. } else {
  295. PQEventTrackViewModel.shareReportUpload(screenType: 2, videoId: videoData?.uniqueId ?? "0", pageSource: videoData!.pageSource, recommendId: videoData?.recommendId, recommendLogVO: videoData?.recommendLogVO, flowPool: nil, abInfoData: videoData?.abInfoData, measureType: videoData?.measureType, measureId: videoData?.measureId, businessType: isFriend ? .bt_videoShareFriend : .bt_videoShareH5, targetUid: videoData?.userInfo?.uid, shareId: shareId)
  296. }
  297. }
  298. @objc func didBecomeActiveNotification() {
  299. if currentActionBtn != nil {
  300. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
  301. cShowHUB(superView: nil, msg: "分享成功")
  302. }
  303. if currentActionBtn?.tag == 4 {
  304. if currentVideoData?.shareCountFriend != nil, currentVideoData?.shareCountFriend ?? 0 > 0 {
  305. currentVideoData?.shareCountFriend = (currentVideoData?.shareCountFriend ?? 0) + 1
  306. } else {
  307. currentVideoData?.shareCountFriend = 1
  308. }
  309. } else if currentActionBtn?.tag == 5 {
  310. if currentVideoData?.shareCount != nil, currentVideoData?.shareCount ?? 0 > 0 {
  311. currentVideoData?.shareCount = (currentVideoData?.shareCount ?? 0) + 1
  312. } else {
  313. currentVideoData?.shareCount = 1
  314. }
  315. }
  316. currentActionBtn = nil
  317. currentVideoData = nil
  318. (collectionView.visibleCell() as? MVPlayControlViewCell)?.addData()
  319. // collectionView.reloadData()
  320. }
  321. let navVc: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController) as? UINavigationController
  322. if navVc?.visibleViewController is MVPlayViewController {
  323. scrollViewDidEndDecelerating(collectionView)
  324. }
  325. }
  326. @objc func enterBackground() {
  327. BFLog(message: "进入到后台")
  328. let navVc: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController) as? UINavigationController
  329. if navVc?.visibleViewController is MVPlayViewController {
  330. (collectionView.visibleCell() as? MVPlayControlViewCell)?.pauseClick(isHidden: false)
  331. PQSingletoVideoPlayer.shared.stopPlayer(isRemove: false)
  332. }
  333. }
  334. @objc func willEnterForeground() {
  335. BFLog(message: "进入到前台")
  336. }
  337. override open var preferredStatusBarStyle: UIStatusBarStyle {
  338. return .lightContent
  339. }
  340. }