TXFullVideoView.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. //
  2. // TXFullVideoView.m
  3. // TeacherDaya
  4. //
  5. // Created by 王智 on 2023/4/14.
  6. // Copyright © 2023 DayaMusic. All rights reserved.
  7. //
  8. #import "TXFullVideoView.h"
  9. #import "ClassroomService.h"
  10. #import "TXFullVideoCell.h"
  11. @interface TXFullVideoView ()<UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
  12. @property (nonatomic, strong) UICollectionView *videoView;
  13. @property (nonatomic, strong) NSMutableArray *videoDataSource;
  14. @property (nonatomic, strong) dispatch_queue_t videoListQueue;
  15. @property (nonatomic, assign) CGRect viewFrame;
  16. @property (nonatomic, assign) CGSize cellSize;
  17. @end
  18. @implementation TXFullVideoView
  19. - (instancetype)initWithFrame:(CGRect)frame {
  20. self = [super initWithFrame:frame];
  21. if (self) {
  22. _viewFrame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
  23. [self addSubview:self.videoView];
  24. [self addCancleButton];
  25. }
  26. return self;
  27. }
  28. - (void)addCancleButton {
  29. UIButton *cancleButton = [[UIButton alloc] initWithFrame:CGRectMake(KLandscapeWidth - 50, 10, 40, 40)];
  30. [cancleButton setImage:[UIImage imageNamed:@"videoMask_delete"] forState:UIControlStateNormal];
  31. [cancleButton addTarget:self action:@selector(cancleButtonAction:) forControlEvents:UIControlEventTouchUpInside];
  32. [self addSubview:cancleButton];
  33. [self bringSubviewToFront:cancleButton];
  34. }
  35. - (void)cancleButtonAction:(UIButton *)sender {
  36. if (self.delegate && [self.delegate respondsToSelector:@selector(cancleFullVideoList)]) {
  37. [self.delegate cancleFullVideoList];
  38. }
  39. }
  40. - (void)showInView:(UIView *)view {
  41. [view addSubview:self];
  42. if ([ClassroomService sharedService].currentRoom.isPlayBeat || [ClassroomService sharedService].currentRoom.isPlaySong) {
  43. // 记录当前播放的学生音频
  44. self.currentPlayUserId = [ClassroomService sharedService].currentRoom.currentPlayUserId;
  45. }
  46. }
  47. - (void)showVideoList {
  48. dispatch_async(self.videoListQueue, ^{
  49. NSArray *tempArray = [ClassroomService sharedService].currentRoom.memberList;
  50. // NSMutableArray *array = [NSMutableArray arrayWithArray:[ClassroomService sharedService].currentRoom.memberList];
  51. // [array addObjectsFromArray:tempArray];
  52. // [array addObjectsFromArray:tempArray];
  53. // [array addObjectsFromArray:tempArray];
  54. //// [array addObjectsFromArray:tempArray];
  55. // tempArray = [NSArray arrayWithArray:array];
  56. if (tempArray.count <= 0) {
  57. return;
  58. }
  59. NSSortDescriptor * des = [[NSSortDescriptor alloc] initWithKey:@"joinTime" ascending:YES];
  60. NSMutableArray *sortArray = [[tempArray sortedArrayUsingDescriptors:@[des]] mutableCopy];
  61. RoomMember *currentMember = [ClassroomService sharedService].currentRoom.currentMember;
  62. RoomMember *teacher = [ClassroomService sharedService].currentRoom.teacher;
  63. __block NSInteger teacherIdx = -1;
  64. __block NSInteger meIdx = -1;
  65. NSMutableIndexSet *set = [[NSMutableIndexSet alloc]init];
  66. for (int i = 0; i < [sortArray count]; i++ ) {
  67. RoomMember *member = (RoomMember *)[sortArray objectAtIndex:i];
  68. if ([member.userId isEqualToString:currentMember.userId]) {
  69. meIdx = i;
  70. }else {
  71. if (member.role == RoleTeacher) {
  72. teacherIdx = i;
  73. }
  74. if (member.role == RoleAudience) {
  75. [set addIndex:i];//旁观者不能被任何他人看见,如果自己是旁观者自己可以看见自己
  76. }
  77. }
  78. }
  79. NSMutableArray *lastArray = [[NSMutableArray alloc] init];
  80. if (teacherIdx >= 0) {
  81. [lastArray addObject:teacher];
  82. [set addIndex:teacherIdx];
  83. }
  84. if (meIdx >= 0) {
  85. [lastArray addObject:currentMember];
  86. [set addIndex:meIdx];
  87. }
  88. if (set.count > 0) {
  89. [sortArray removeObjectsAtIndexes:set];
  90. }
  91. [lastArray addObjectsFromArray:sortArray];
  92. dispatch_async(dispatch_get_main_queue(), ^{
  93. self.videoDataSource = [lastArray mutableCopy];
  94. [self.videoView reloadData];
  95. });
  96. });
  97. }
  98. - (void)updateUserVideo:(NSString *)userId {
  99. dispatch_async(self.videoListQueue, ^{
  100. for(int i=0;i < self.videoDataSource.count; i++) {
  101. RoomMember *member = self.videoDataSource[i];
  102. if([member.userId isEqualToString:userId]) {
  103. NSIndexPath *index = [NSIndexPath indexPathForItem:i inSection:0];
  104. dispatch_async(dispatch_get_main_queue(), ^{
  105. TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
  106. if (cell) {
  107. [self.videoView reloadItemsAtIndexPaths:@[index]];
  108. }
  109. });
  110. }
  111. }
  112. });
  113. }
  114. - (void)updateUserQuality:(NSString *)userId netWorkingStatus:(TXNetWorkingStatus)quality {
  115. dispatch_async(self.videoListQueue, ^{
  116. for(int i = 0;i < self.videoDataSource.count; i++) {
  117. RoomMember *member = self.videoDataSource[i];
  118. if([member.userId isEqualToString:userId]) {
  119. NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
  120. dispatch_async(dispatch_get_main_queue(), ^{
  121. TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
  122. if (cell) {
  123. [cell updateQuality:quality];
  124. }
  125. });
  126. }
  127. }
  128. });
  129. }
  130. - (void)updateMicStatus:(NSString *)userId volume:(NSInteger)volume {
  131. dispatch_async(self.videoListQueue, ^{
  132. for(int i = 0;i < self.videoDataSource.count; i++) {
  133. RoomMember *member = self.videoDataSource[i];
  134. if([member.userId isEqualToString:userId]) {
  135. RoomMember *currentMember = [[ClassroomService sharedService].currentRoom getMember:userId];
  136. NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
  137. dispatch_async(dispatch_get_main_queue(), ^{
  138. TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
  139. if (cell) {
  140. [cell updateUserVolume:volume isCloseMic:!currentMember.microphoneEnable];
  141. }
  142. });
  143. }
  144. }
  145. });
  146. }
  147. #pragma mark ----- collection view data source
  148. - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
  149. return 1;
  150. }
  151. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  152. return self.videoDataSource.count;
  153. }
  154. - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  155. TXFullVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TXFullVideoCell" forIndexPath:indexPath];
  156. cell.cellSize = self.cellSize;
  157. [cell setModel:[self.videoDataSource objectAtIndex:indexPath.row] displayUserId:self.displayUserId];
  158. return cell;
  159. }
  160. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  161. // 显示大屏
  162. RoomMember *mem = [self.videoDataSource objectAtIndex:indexPath.row];
  163. if (self.delegate && [self.delegate respondsToSelector:@selector(fullVideoListView:didTap:)]) {
  164. self.displayUserId = mem.userId;
  165. [self.delegate fullVideoListView:self didTap:mem];
  166. }
  167. }
  168. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
  169. switch (self.videoDataSource.count) {
  170. case 1:
  171. {
  172. self.cellSize = CGSizeMake((self.viewFrame.size.width - 30) / 2.0f, self.viewFrame.size.height - 20);
  173. return self.cellSize;
  174. }
  175. break;
  176. case 2:
  177. {
  178. self.cellSize = CGSizeMake((_viewFrame.size.width - 30) / 2.0f, _viewFrame.size.height - 20);
  179. return self.cellSize;
  180. }
  181. break;
  182. case 3:
  183. case 4:
  184. {
  185. self.cellSize = CGSizeMake((_viewFrame.size.width - 30) / 2.0f, (_viewFrame.size.height - 30) / 2.0f);
  186. return self.cellSize;
  187. }
  188. break;
  189. case 5:
  190. case 6:
  191. {
  192. self.cellSize = CGSizeMake((_viewFrame.size.width - 40) / 3.0f, (_viewFrame.size.height - 30) / 2.0f);
  193. return self.cellSize;
  194. }
  195. break;
  196. default:
  197. self.cellSize = CGSizeMake((_viewFrame.size.width - 40) / 3.0f, (_viewFrame.size.height - 40) / 3.0f);
  198. return self.cellSize;
  199. }
  200. }
  201. #pragma mark ---- lazying
  202. - (UICollectionView *)videoView {
  203. if (!_videoView) {
  204. UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
  205. layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
  206. _videoView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight) collectionViewLayout:layout];
  207. _videoView.backgroundColor = HexRGB(0xffffff);
  208. _videoView.delegate = self;
  209. _videoView.dataSource = self;
  210. _videoView.bounces = NO;
  211. _videoView.showsVerticalScrollIndicator = NO;
  212. _videoView.showsHorizontalScrollIndicator = NO;
  213. [_videoView registerNib:[UINib nibWithNibName:@"TXFullVideoCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"TXFullVideoCell"];
  214. }
  215. return _videoView;
  216. }
  217. - (NSMutableArray *)videoDataSource {
  218. if (!_videoDataSource) {
  219. _videoDataSource = [NSMutableArray array];
  220. }
  221. return _videoDataSource;
  222. }
  223. - (dispatch_queue_t)videoListQueue {
  224. if (!_videoListQueue) {
  225. _videoListQueue = dispatch_queue_create("cn.daya.fullVideo.videolist", DISPATCH_QUEUE_SERIAL);
  226. }
  227. return _videoListQueue;
  228. }
  229. /*
  230. // Only override drawRect: if you perform custom drawing.
  231. // An empty implementation adversely affects performance during animation.
  232. - (void)drawRect:(CGRect)rect {
  233. // Drawing code
  234. }
  235. */
  236. @end