RQVideoModule.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //
  2. // RQVideoModule.m
  3. // JSJP
  4. //
  5. // Created by 张嵘 on 2021/10/25.
  6. //
  7. #import "RQVideoModule.h"
  8. #import "UIView+ZFFrame.h"
  9. #import <ZFPlayer/ZFAVPlayerManager.h>
  10. /// 播放视频
  11. NSString * const RQPlayVideoUrlNotification = @"RQPlayVideoUrlNotification";
  12. /// 播放视频Model
  13. NSString * const RQPlayVideoItemKey = @"RQPlayVideoItemKey";
  14. /// 播放视频ModelArr
  15. NSString * const RQPlayVideoItemArrKey = @"RQPlayVideoItemArrKey";
  16. /// 视频Index
  17. NSString * const RQVideoItemIndexKey = @"RQVideoItemIndexKey";
  18. /// 视频IndexPath
  19. NSString * const RQVideoItemIndexPathKey = @"RQVideoItemIndexPathKey";
  20. @implementation RQVideoPermissionStateModel
  21. @end
  22. @interface RQVideoModule ()
  23. @property (nonatomic, readwrite, strong) ZFPlayerControlView *controlView;
  24. @property (nonatomic, readwrite, assign) RQADDoType adDoType;
  25. @property (nonatomic, readwrite, assign) ZFPlayerPlaybackState playState;
  26. @property (nonatomic, readwrite, strong) RQVipPlaceHolderView *vipPlaceHolderView;
  27. @property (nonatomic, readwrite, strong) UIView *playView;
  28. @property (nonatomic, readwrite, strong) UIScrollView *scrollView;
  29. @end
  30. @implementation RQVideoModule
  31. static id rq_VideoModule = nil;
  32. #pragma mark - init
  33. + (instancetype)sharedInstance {
  34. static dispatch_once_t onceToken;
  35. dispatch_once(&onceToken, ^{
  36. rq_VideoModule = [[self alloc] init];
  37. });
  38. return rq_VideoModule;
  39. }
  40. - (instancetype)init {
  41. if (self = [super init]) {
  42. self.playerController.controlView = self.controlView;
  43. }
  44. return self;
  45. }
  46. - (BOOL)isCanWatchWithVideosItem:(VideosItem *)videosItem {
  47. if (RQ_USER_MANAGER.isLogin) {
  48. // if (!RQ_COMMON_MANAGER.APP_SWITCH) {
  49. if (videosItem.videoType == RQVideoType_KaoChang) {
  50. if (videosItem.permission == 2) {
  51. if (videosItem.placeVideoListModel.placeListModel.isCheckVip) {
  52. return YES;
  53. } else {
  54. [QMUITips showInfo:@"请购买该考场VIP会员"];
  55. return NO;
  56. }
  57. } else {
  58. return YES;
  59. }
  60. } else {
  61. if (videosItem.subject == 1) {
  62. if (RQ_VIP_Module.isSubject2Vip) {
  63. return YES;
  64. } else {
  65. if (videosItem.permission == 2) {
  66. [RQ_VIP_Module gotoBuyVipWithVipPageType:RQVIPPageType_Full];
  67. return NO;
  68. } else {
  69. return YES;
  70. }
  71. }
  72. } else if (videosItem.subject == 2) {
  73. if (RQ_VIP_Module.isSubject3Vip) {
  74. return YES;
  75. } else {
  76. if (videosItem.permission == 2) {
  77. [RQ_VIP_Module gotoBuyVipWithVipPageType:RQVIPPageType_Full];
  78. return NO;
  79. } else {
  80. return YES;
  81. }
  82. }
  83. } else if (videosItem.subject == 5) {
  84. if (RQ_VIP_Module.isSpSubject1Vip) {
  85. return YES;
  86. } else {
  87. if (videosItem.permission == 2) {
  88. [RQ_VIP_Module gotoBuyVipWithVipPageType:RQVIPPageType_Full];
  89. return NO;
  90. } else {
  91. return YES;
  92. }
  93. }
  94. } else if (videosItem.subject == 6) {
  95. if (RQ_VIP_Module.isSpSubject4Vip) {
  96. return YES;
  97. } else {
  98. if (videosItem.permission == 2) {
  99. [RQ_VIP_Module gotoBuyVipWithVipPageType:RQVIPPageType_Full];
  100. return NO;
  101. } else {
  102. return YES;
  103. }
  104. }
  105. } else {
  106. return YES;
  107. }
  108. }
  109. // } else {
  110. // return YES;
  111. // }
  112. } else {
  113. if (videosItem.permission == 0) {
  114. return YES;
  115. } else {
  116. RQ_USER_MANAGER.isShouldLogin;
  117. return NO;
  118. }
  119. }
  120. }
  121. - (void)playVideoWithVideosItem:(VideosItem *)videosItem videosItemArr:(NSArray *)videosItemArr playView:(UIView *)playView scrollView:(UIScrollView *)scrollView {
  122. if (self.playerController && self.playerController.isPlaying) {
  123. [self.playerController stop];
  124. }
  125. self.playView = playView;
  126. self.scrollView = scrollView;
  127. [self.playerController updateNoramlPlayerWithContainerView:playView];
  128. [self requestDataWithVideosItem:videosItem videosItemArr:videosItemArr];
  129. }
  130. - (void)requestDataWithVideosItem:(VideosItem *)videoItem videosItemArr:(NSArray *)videosItemArr {
  131. WeakSelf(weakSelf)
  132. if (RQ_Video_Module.currentpPlayVideosItem.isPlaying) {
  133. RQ_Video_Module.currentpPlayVideosItem.isPlaying = NO;
  134. }
  135. self.playerController.playableArray = videosItemArr;
  136. [self.controlView showTitle:videoItem.title coverURLString:videoItem.coverFileUrl placeholderImage:RQWebVideoImagePlaceholder() fullScreenMode:ZFFullScreenModeAutomatic];
  137. [self.playerController playWithPlayable:videoItem];
  138. if ((videoItem.subject == 1 && RQ_VIP_Module.isSubject2Vip) ||
  139. (videoItem.subject == 2 && RQ_VIP_Module.isSubject3Vip) ||
  140. (videoItem.subject == 5 && RQ_VIP_Module.isSpSubject1Vip) ||
  141. (videoItem.subject == 6 && RQ_VIP_Module.isSpSubject4Vip)) {
  142. } else {
  143. [self.playerController.currentPlayerManager pause];
  144. if (_payState>0) return;
  145. NSLog(@"AD-广告");
  146. [RQ_AD_MANAGER loadAdWithAdType:RQADType_native customView:self.playView];
  147. _payState = 1;
  148. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  149. _payState = 0;
  150. });
  151. //广告关闭监听-时间监听 2025-2-19 ning
  152. [RQ_AD_MANAGER initCloseBlock:^(RQADDoType adDoType) {
  153. dispatch_async(dispatch_get_main_queue(), ^{
  154. // @strongify(self)
  155. weakSelf.adDoType = adDoType;
  156. ZFPlayerPlaybackState playState = weakSelf.playerController.currentPlayerManager.playState;
  157. if (adDoType == RQADDoType_Miss) {
  158. }
  159. switch (adDoType) {
  160. case RQADDoType_Success:
  161. case RQADDoType_Click:{
  162. if (playState == ZFPlayerPlayStatePlaying) {
  163. [weakSelf.playerController.currentPlayerManager pause];
  164. }
  165. break;
  166. }
  167. case RQADDoType_Faild:
  168. case RQADDoType_Close:{
  169. if (playState == ZFPlayerPlayStatePaused) {
  170. // if(RQ_AD_MANAGER.adType==RQADType_fullScreen||RQ_AD_MANAGER.adType==RQADType_native){
  171. // break;
  172. // }
  173. if (!weakSelf.playerController.player.isFullScreen) {
  174. //延时
  175. if ([NSStringFromClass([RQControllerHelper.currentViewController class]) isEqualToString:@"ZFLandscapeViewController"]||
  176. [NSStringFromClass([RQControllerHelper.currentViewController class]) isEqualToString:@"NYLIVideoDetailViewController"]) {
  177. [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  178. [subscriber sendNext:@"延时.2f秒"];
  179. return nil;
  180. }] delay:.2f] deliverOnMainThread] subscribeNext:^(id x) {
  181. // @strongify(self)
  182. [weakSelf.playerController.currentPlayerManager play];
  183. weakSelf.adDoType = RQADDoType_Miss;
  184. }];
  185. }
  186. } else {
  187. if ([NSStringFromClass([RQControllerHelper.currentViewController class]) isEqualToString:@"ZFLandscapeViewController"]||
  188. [NSStringFromClass([RQControllerHelper.currentViewController class]) isEqualToString:@"NYLIVideoDetailViewController"]) {
  189. [weakSelf.playerController.currentPlayerManager play];
  190. weakSelf.adDoType = RQADDoType_Miss;
  191. }
  192. }
  193. }
  194. break;
  195. }
  196. default:
  197. break;
  198. }
  199. });
  200. }];
  201. }
  202. __block BOOL isBuy = videoItem.placeVideoListModel.placeListModel.isCheckVip;
  203. [[[[RACObserve(RQ_COMMON_MANAGER, vipListArr) deliverOnMainThread] takeUntil:self.rac_willDeallocSignal] skip:1] subscribeNext:^(id _Nullable x) {
  204. isBuy = [RQ_COMMON_MANAGER.vipListArr containsObject:videoItem.placeVideoListModel.examName];
  205. }];
  206. // if (!RQ_COMMON_MANAGER.APP_SWITCH) { //播放时间监听 2025-2-19 ning
  207. self.playerController.player.playerPlayTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval currentTime, NSTimeInterval duration) {
  208. // @strongify(self)
  209. if (videoItem.permission == 1) {
  210. if (videoItem.videoType == RQVideoType_KaoChang) {
  211. if (!isBuy) {
  212. NSInteger tryLookSecond = RQStringIsEmpty(videoItem.placeVideoListModel.tryLookSecond)? 0 : videoItem.placeVideoListModel.tryLookSecond.integerValue;
  213. if (tryLookSecond > 0) {
  214. if (weakSelf.playerController.player.currentTime >= tryLookSecond) {
  215. [weakSelf.playerController.currentPlayerManager pause];
  216. weakSelf.vipPlaceHolderView.myTitleLabel.text = @"试看结束,开通考场会员观看完整视频";
  217. [weakSelf.playerController.containerView addSubview:weakSelf.vipPlaceHolderView];
  218. [weakSelf.vipPlaceHolderView.reLookBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  219. [weakSelf.vipPlaceHolderView removeFromSuperview];
  220. weakSelf.controlView = nil;
  221. weakSelf.playerController.controlView = weakSelf.controlView;
  222. [weakSelf.controlView showTitle:videoItem.title coverURLString:videoItem.coverFileUrl placeholderImage:RQWebVideoImagePlaceholder() fullScreenMode:ZFFullScreenModeAutomatic];
  223. [weakSelf.playerController playWithPlayable:videoItem];
  224. }];
  225. [weakSelf.vipPlaceHolderView.openBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  226. [RQ_APPDELEGATE.services popViewModelAnimated:YES];
  227. }];
  228. }
  229. }
  230. }
  231. } else {
  232. if ((videoItem.subject == 0 && RQ_VIP_Module.isSubject1Vip) ||
  233. (videoItem.subject == 1 && RQ_VIP_Module.isSubject2Vip) ||
  234. (videoItem.subject == 2 && RQ_VIP_Module.isSubject3Vip) ||
  235. (videoItem.subject == 5 && RQ_VIP_Module.isSpSubject1Vip) ||
  236. (videoItem.subject == 6 && RQ_VIP_Module.isSpSubject4Vip)) {
  237. } else {
  238. NSInteger tryLookSecond = RQStringIsEmpty(videoItem.tryLookSecond)? 15 : videoItem.tryLookSecond.integerValue;
  239. if (weakSelf.playerController.player.currentTime >= tryLookSecond) {
  240. [weakSelf.playerController.currentPlayerManager pause];
  241. switch (videoItem.subject) {
  242. case 0:
  243. weakSelf.vipPlaceHolderView.myTitleLabel.text = @"试看结束,开通科一会员观看完整视频";
  244. break;
  245. case 1:
  246. weakSelf.vipPlaceHolderView.myTitleLabel.text = @"试看结束,开通科二会员观看完整视频";
  247. break;
  248. case 2:
  249. weakSelf.vipPlaceHolderView.myTitleLabel.text = @"试看结束,开通科三会员观看完整视频";
  250. break;
  251. case 3:
  252. weakSelf.vipPlaceHolderView.myTitleLabel.text = @"试看结束,开通科四会员观看完整视频";
  253. break;
  254. default:
  255. weakSelf.vipPlaceHolderView.myTitleLabel.text = @"试看结束,开通会员观看完整视频";
  256. break;
  257. }
  258. [weakSelf.playerController.containerView addSubview:weakSelf.vipPlaceHolderView];
  259. [weakSelf.vipPlaceHolderView.reLookBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  260. [weakSelf.vipPlaceHolderView removeFromSuperview];
  261. weakSelf.controlView = nil;
  262. weakSelf.playerController.controlView = weakSelf.controlView;
  263. [weakSelf.controlView showTitle:videoItem.title coverURLString:videoItem.coverFileUrl placeholderImage:RQWebVideoImagePlaceholder() fullScreenMode:ZFFullScreenModeAutomatic];
  264. [weakSelf.playerController playWithPlayable:videoItem];
  265. }];
  266. [weakSelf.vipPlaceHolderView.openBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  267. [RQ_VIP_Module gotoBuyVipWithVipPageType:RQVIPPageType_Full];
  268. }];
  269. }
  270. }
  271. }
  272. }
  273. };
  274. // }
  275. //播放结束监听 2025-2-19 ning
  276. self.playerController.currentPlayerManager.playerDidToEnd = ^(id<ZFPlayerMediaPlayback> _Nonnull asset) {
  277. // @strongify(self)
  278. if (!weakSelf.playerController.player.isFullScreen) {
  279. NSInteger currentIndex = [videosItemArr indexOfObject:videoItem];
  280. NSInteger nextIndex = (currentIndex + 1 >= weakSelf.playerController.playableArray.count)? 0 : currentIndex + 1;
  281. VideosItem *nextVideoItem = (VideosItem *)videosItemArr[nextIndex];
  282. if ([weakSelf isCanWatchWithVideosItem:nextVideoItem]) {
  283. videoItem.isPlaying = NO;
  284. nextVideoItem.isPlaying = YES;
  285. [weakSelf requestDataWithVideosItem:nextVideoItem videosItemArr:videosItemArr];
  286. }
  287. } else {
  288. NSInteger currentIndex = [videosItemArr indexOfObject:RQ_Video_Module.currentpPlayVideosItem];
  289. NSInteger nextIndex = (currentIndex + 1 >= weakSelf.playerController.playableArray.count)? 0 : currentIndex + 1;
  290. VideosItem *nextVideoItem = (VideosItem *)videosItemArr[nextIndex];
  291. if ([weakSelf isCanWatchWithVideosItem:nextVideoItem]) {
  292. if ((videoItem.subject == 1 && RQ_VIP_Module.isSubject2Vip) ||
  293. (videoItem.subject == 2 && RQ_VIP_Module.isSubject3Vip) ||
  294. (videoItem.subject == 5 && RQ_VIP_Module.isSpSubject1Vip) ||
  295. (videoItem.subject == 6 && RQ_VIP_Module.isSpSubject4Vip)) {
  296. } else {
  297. [RQ_AD_MANAGER loadAdWithAdType:RQADType_fullScreen customView:nil];
  298. }
  299. __block BOOL isSure;
  300. SCLAlertView *alert = [[SCLAlertView alloc] initWithNewWindow];
  301. alert.backgroundViewColor = RQ_BACKGROUNDCOLOR_1;
  302. alert.customViewColor = RQ_MAIN_COLOR;
  303. [alert addButton:@"立即播放 " actionBlock:^(void) {
  304. isSure = YES;
  305. RQ_Video_Module.currentpPlayVideosItem.isPlaying = NO;
  306. [weakSelf.playerController playWithPlayable:nextVideoItem];
  307. nextVideoItem.isPlaying = YES;
  308. [weakSelf.playerController.currentPlayerManager pause];
  309. [weakSelf.controlView updateTitle:nextVideoItem.title coverURLString:nextVideoItem.coverFileUrl placeholderImage:RQWebVideoImagePlaceholder() fullScreenMode:ZFFullScreenModeAutomatic];
  310. RQ_Video_Module.currentpPlayVideosItem = nextVideoItem;
  311. }];
  312. [alert addTimerToButtonIndex:0 reverse:YES];
  313. [alert showNotice:@"温馨提示" subTitle:@"即将播放下一个视频" closeButtonTitle:@"取消" duration:5.0f];
  314. [alert alertIsDismissed:^{
  315. if (isSure) {
  316. if ((videoItem.subject == 1 && RQ_VIP_Module.isSubject2Vip) ||
  317. (videoItem.subject == 2 && RQ_VIP_Module.isSubject3Vip) ||
  318. (videoItem.subject == 5 && RQ_VIP_Module.isSpSubject1Vip) ||
  319. (videoItem.subject == 6 && RQ_VIP_Module.isSpSubject4Vip)) {
  320. } else {
  321. [RQ_AD_MANAGER showAdWithAdType:RQADType_fullScreen];
  322. }
  323. }
  324. }];
  325. }
  326. }
  327. };
  328. //延时
  329. [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  330. [subscriber sendNext:@"延时.5f秒"];
  331. return nil;
  332. }] delay:.5f] deliverOnMainThread] subscribeNext:^(id x) {
  333. NSInteger index = [videosItemArr indexOfObject:videoItem];
  334. [self.scrollView zf_scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:ZFPlayerScrollViewScrollPositionCenteredVertically animated:YES completionHandler:nil];
  335. }];
  336. videoItem.isPlaying = YES;
  337. RQ_Video_Module.currentpPlayVideosItem = videoItem;
  338. }
  339. //延迟播放
  340. - (void)delayPlaydo:(NSInteger)subject {
  341. WeakSelf(weakSelf)
  342. if ((subject == 1 && RQ_VIP_Module.isSubject2Vip) ||
  343. (subject == 2 && RQ_VIP_Module.isSubject3Vip) ||
  344. (subject == 5 && RQ_VIP_Module.isSpSubject1Vip) ||
  345. (subject == 6 && RQ_VIP_Module.isSpSubject4Vip)) {
  346. [weakSelf.vipPlaceHolderView removeFromSuperview];
  347. weakSelf.controlView = nil;
  348. weakSelf.playerController.controlView = weakSelf.controlView;
  349. //延时
  350. if ([NSStringFromClass([RQControllerHelper.currentViewController class]) isEqualToString:@"ZFLandscapeViewController"]||
  351. [NSStringFromClass([RQControllerHelper.currentViewController class]) isEqualToString:@"NYLIVideoDetailViewController"]) {
  352. [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  353. [subscriber sendNext:@"延时.2f秒"];
  354. return nil;
  355. }] delay:.2f] deliverOnMainThread] subscribeNext:^(id x) {
  356. // @strongify(self)
  357. [weakSelf.playerController.currentPlayerManager play];
  358. weakSelf.adDoType = RQADDoType_Miss;
  359. }];
  360. }
  361. }
  362. }
  363. - (void)backBtnClickActiondo{
  364. [self.controlView backBtnClickActiondo];
  365. }
  366. #pragma mark - LazyLoad
  367. - (ZFPlayerControlView *)controlView {
  368. if (!_controlView) {
  369. _controlView = [[ZFPlayerControlView alloc] init];
  370. // @weakify(self)
  371. WeakSelf(weakSelf)
  372. [_controlView.portraitControlView.backBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  373. if(weakSelf.livideoDetailViewController.tagTyp>0&&weakSelf.failSpecialDetailViewController==NULL&&weakSelf.videoDetailViewController==NULL){//tbar 中的视频不用关闭
  374. return;
  375. }
  376. [RQNotificationCenter removeObserver:weakSelf.videoDetailViewController name:RQPlayVideoUrlNotification object:nil];
  377. [RQNotificationCenter removeObserver:weakSelf.failSpecialDetailViewController name:RQPlayVideoUrlNotification object:nil];
  378. [RQNotificationCenter removeObserver:weakSelf.livideoDetailViewController name:RQPlayVideoUrlNotification object:nil];
  379. [weakSelf.playerController stop];
  380. [RQ_APPDELEGATE.services popViewModelAnimated:YES];
  381. }];
  382. _controlView.portraitControlView.topToolView.alpha = 1;
  383. _controlView.portraitControlView.topToolView.zf_y = 0;
  384. [[[[RACObserve(_controlView, portraitControlView.topToolView.alpha) deliverOnMainThread] distinctUntilChanged] takeUntil:weakSelf.rac_willDeallocSignal] subscribeNext:^(id _Nullable x) {
  385. // @strongify(_controlView)
  386. if (_controlView.portraitControlView.topToolView.alpha < 1) {
  387. _controlView.portraitControlView.topToolView.alpha = 1;
  388. }
  389. }];
  390. [[[[RACObserve(_controlView, portraitControlView.topToolView.zf_y) deliverOnMainThread] distinctUntilChanged] takeUntil:weakSelf.rac_willDeallocSignal] subscribeNext:^(id _Nullable x) {
  391. // @strongify(_controlView)
  392. if (_controlView.portraitControlView.topToolView.zf_y < 0) {
  393. _controlView.portraitControlView.topToolView.zf_y = 0;
  394. }
  395. }];
  396. }
  397. return _controlView;
  398. }
  399. - (RQVipPlaceHolderView *)vipPlaceHolderView {
  400. if (!_vipPlaceHolderView) {
  401. _vipPlaceHolderView = [RQVipPlaceHolderView vipPlaceHolderView];
  402. _vipPlaceHolderView.size = self.playerController.containerView.size;
  403. }
  404. return _vipPlaceHolderView;
  405. }
  406. - (MPPlayerController *)playerController {
  407. if (!_playerController) {
  408. _playerController = [MPPlayerController playrWithContainerView:UIView.new];
  409. [_playerController.player setExitFullScreenWhenStop:NO];
  410. }
  411. return _playerController;
  412. }
  413. - (ZFPlayerController *)zfPlayerController {
  414. if (!_zfPlayerController) {
  415. ZFAVPlayerManager *playerManager = [[ZFAVPlayerManager alloc] init];
  416. playerManager.shouldAutoPlay = YES;
  417. _zfPlayerController = [ZFPlayerController playerWithPlayerManager:playerManager containerView:UIView.new];
  418. [_zfPlayerController setExitFullScreenWhenStop:YES];
  419. }
  420. return _zfPlayerController;
  421. }
  422. @end