XYChatRoomManager.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. //
  2. // XYChatRoomManager.m
  3. // Starbuds
  4. //
  5. // Created by 翟玉磊 on 2020/6/29.
  6. // Copyright © 2020 翟玉磊. All rights reserved.
  7. //
  8. #import "XYChatRoomManager.h"
  9. #import "XYFloatingDragView.h"
  10. #import "XYChatRoomShowAnimationView.h"
  11. #import "XYPeiPlayCommendAlertView.h"
  12. #import "XYCrossRoomPkManager.h"
  13. #import "XYBankIdentityCardVerIfyViewController.h"
  14. @interface XYChatRoomManager ()<XYFloatingDragViewDelegate>
  15. /// 语音悬浮窗
  16. @property (nonatomic, strong) XYFloatingDragView *floatingDragView;
  17. @property (nonatomic, strong) XYChatRoomShowAnimationView *showAnimationView;
  18. @property (nonatomic, copy) NSString *roomId;
  19. @end
  20. @implementation XYChatRoomManager
  21. #pragma mark — 单例
  22. static XYChatRoomManager *_singleInstance = nil;
  23. + (instancetype)sharedInstance {
  24. static dispatch_once_t onceToken;
  25. dispatch_once(&onceToken, ^{
  26. if (_singleInstance == nil) {
  27. _singleInstance = [[self alloc]init];
  28. }
  29. });
  30. return _singleInstance;
  31. }
  32. + (instancetype)allocWithZone:(struct _NSZone *)zone {
  33. static dispatch_once_t onceToken;
  34. dispatch_once(&onceToken, ^{
  35. _singleInstance = [super allocWithZone:zone];
  36. });
  37. return _singleInstance;
  38. }
  39. - (id)copyWithZone:(NSZone *)zone {
  40. return _singleInstance;
  41. }
  42. - (id)mutableCopyWithZone:(NSZone *)zone {
  43. return _singleInstance;
  44. }
  45. #pragma mark — Public
  46. - (void)showChatRoomWithRoomId:(NSString *)roomId roomCoverUrl:(NSString *)roomCoverUrl completion:(void (^ __nullable)(void))completion {
  47. if (![XYUserInfoManager nowUser]) {
  48. [ApplicationDelegate createQulickLoginPageVC];
  49. return;
  50. }
  51. if (StringIsEmpty(roomId)) {
  52. !completion?:completion();
  53. return;
  54. }
  55. if (!ApplicationDelegate.tabbarVC) {
  56. return;
  57. }
  58. // 所有进入语音房的次数,加载房间信息的时候统计
  59. [StatisticsManager event:@"voiceroom_load"];
  60. // 从外部点击进入语音房时上报,区分不同来源
  61. [StatisticsManager event:@"goto_voiceroom"];
  62. // 获取房间信息 判断是否需要密码
  63. if (StringIsNotEmpty(self.roomId)) {
  64. if (![self.roomId isEqualToString:roomId]) {
  65. // 先销毁悬浮窗
  66. [self closeChatRoomBlock:^{
  67. [self.showAnimationView showChatRoomAnimationWithRoomCoverUrl:roomCoverUrl completion:^{
  68. [self jainRoomWithRoomId:roomId pass:@"" completion:completion];
  69. }];
  70. }];
  71. }else {
  72. // 因为id一直且存在直播间 说明是打开的同一个房间 则先打开直播间界面再关闭悬浮窗
  73. [self openFloatingDragWindow];
  74. }
  75. }else {
  76. // 记录进入房间的时间戳
  77. [[XYPeiPlayCommendAlertView shareInstance] joinRoom];
  78. // 显示进场动画
  79. [self.showAnimationView showChatRoomAnimationWithRoomCoverUrl:roomCoverUrl completion:^{
  80. [self jainRoomWithRoomId:roomId pass:@"" completion:completion];
  81. }];
  82. }
  83. }
  84. - (void)jainRoomWithRoomId:(NSString *)roomId pass:(NSString *)pass completion:(void (^ __nullable)(void))completion {
  85. // 不相等则需要请求房间信息,确定是否需要密码
  86. [[XYVoiceRoomAPIManager new] getRoomInfoWithRoomId:roomId pass:pass successHandler:^(ZYLResponseModel *responseModel) {
  87. self.liveRoomVCInfo = [[XYLiveRoomVCInfo alloc] init];
  88. [self.liveRoomVCInfo create:responseModel.data];
  89. [XYChatRoomManager sharedInstance].liveRoomVCInfo = self.liveRoomVCInfo;
  90. BOOL needPass = [responseModel.data[@"needPass"] boolValue];
  91. if (needPass) {
  92. // 关闭进场动画
  93. [self.showAnimationView dismissCompletion:nil];
  94. self.showAnimationView = nil;
  95. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"该房间已上锁" message:nil preferredStyle:UIAlertControllerStyleAlert];
  96. [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
  97. [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  98. UITextField *userNameTextField = alertController.textFields.firstObject;
  99. NSLog(@"房间密码:%@",userNameTextField.text);
  100. [self jainRoomWithRoomId:roomId pass:userNameTextField.text completion:completion];
  101. }]];
  102. [alertController addTextFieldWithConfigurationHandler:^(UITextField*_Nonnull textField) {
  103. textField.placeholder = @"请输入房间密码";
  104. textField.secureTextEntry = YES;
  105. }];
  106. [ApplicationDelegate.tabbarVC presentViewController:alertController animated:YES completion:nil];
  107. }else {
  108. if (self.chatRoomController==nil) {
  109. // 初始化控制器
  110. self.chatRoomController = XYChatRoomViewController.new;
  111. XYChatRoomInfoManager *infoManager = XYChatRoomInfoManager.new;
  112. infoManager.delegate = self.chatRoomController;
  113. self.chatRoomController.infoManager = infoManager;
  114. [self.chatRoomController roomRTCManager];
  115. }
  116. self.roomId = [roomId copy];
  117. // 设置直播间信息
  118. XYChatRoomInfoModel *model = XYChatRoomInfoModel.new;
  119. [model yy_modelSetWithDictionary:responseModel.data];
  120. [model yy_modelSetWithDictionary:responseModel.data[@"room"]];
  121. self.chatRoomController.infoManager.roomInfoModel = model;
  122. // 麦位信息
  123. self.chatRoomController.infoManager.seatsArray = [NSMutableArray array];
  124. NSMutableArray *seats = [NSMutableArray array];
  125. if (self.chatRoomController.infoManager.roomInfoModel.roomType == XYVoiceRoomTypeVoiceLive) {
  126. NSArray *tempSeats = responseModel.data[@"seats"];
  127. if (tempSeats.count > 5) {
  128. [seats addObjectsFromArray:[tempSeats subarrayWithRange:NSMakeRange(0, 5)]];
  129. }else {
  130. [seats addObjectsFromArray:responseModel.data[@"seats"]];
  131. }
  132. }else {
  133. [seats addObjectsFromArray:responseModel.data[@"seats"]];
  134. }
  135. // 先重置用户的上麦状态
  136. self.chatRoomController.infoManager.isCurrentOnMicrophone = NO;
  137. self.chatRoomController.infoManager.isCurrentHost = NO;
  138. for (NSDictionary *dict in seats) {
  139. XYChatRoomSeatsModel *seatModel = XYChatRoomSeatsModel.new;
  140. [seatModel yy_modelSetWithDictionary:dict];
  141. seatModel.isShowScore = self.chatRoomController.infoManager.roomInfoModel.roomScoreEnabled;
  142. [self.chatRoomController.infoManager.seatsArray addObject:seatModel];
  143. if (seatModel.user) {
  144. // 麦位用户
  145. [self.chatRoomController.infoManager.seatUserArray addObject:seatModel.user];
  146. // 获取当前用户的上麦的状态
  147. if ([seatModel.user.userId isEqualToString:[XYUserInfoManager nowUser].userId]) {
  148. self.chatRoomController.infoManager.isCurrentOnMicrophone = YES;
  149. if (seatModel.seatNo == 0) {
  150. self.chatRoomController.infoManager.isCurrentHost = YES;
  151. }
  152. }
  153. }
  154. }
  155. self.chatRoomController.infoManager.role = [responseModel.data[@"role"] integerValue];
  156. self.chatRoomController.infoManager.stage = [responseModel.data[@"stage"] integerValue];
  157. self.chatRoomController.infoManager.isFav = [responseModel.data[@"isFav"] boolValue];
  158. NSDictionary *profile = responseModel.data[@"profile"];
  159. if (profile) {
  160. NSMutableDictionary *profileDict = [[NSMutableDictionary alloc] init];
  161. [profileDict setDictionary:profile];
  162. [profileDict setObject:[XYUserInfoManager nowUser].headWearAnimationId forKey:@"headWearAnimationId"];
  163. self.chatRoomController.infoManager.profile = profileDict;
  164. }
  165. self.chatRoomController.infoManager.timestamp = responseModel.data[@"timestamp"];
  166. // 获取rtc的认证信息
  167. XYChatRoomRTCAuthInfoModel *rtcModel = XYChatRoomRTCAuthInfoModel.new;
  168. [rtcModel yy_modelSetWithDictionary:responseModel.data[@"authInfo"]];
  169. self.chatRoomController.infoManager.rtcAuthInfo = rtcModel;
  170. // pk相关
  171. self.chatRoomController.infoManager.battleEnabled = self.chatRoomController.infoManager.KFBattleEnabled = [responseModel.data[@"battleEnabled"] boolValue];
  172. NSDictionary *battleRoomIn = responseModel.data[@"battleRoomIn"];
  173. if (battleRoomIn) {
  174. XYChatRoomBattleRoomInModel *battleRoomInModel = XYChatRoomBattleRoomInModel.new;
  175. [battleRoomInModel yy_modelSetWithDictionary:battleRoomIn];
  176. self.chatRoomController.infoManager.battleRoomIn = battleRoomInModel;
  177. if (battleRoomInModel.battleStatus == 201) {
  178. self.chatRoomController.infoManager.pkState = YES;
  179. }else {
  180. self.chatRoomController.infoManager.pkState = NO;
  181. }
  182. }
  183. // 跨房PK
  184. NSDictionary *battleRoomCross = responseModel.data[@"battleRoomCross"];
  185. if (battleRoomCross) {
  186. NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] init];
  187. NSMutableDictionary *msgDict = [[NSMutableDictionary alloc] initWithDictionary:battleRoomCross];
  188. [msgDict setObject:RTC_BATTLE_ROOM_CROSS_STATUS forKey:@"type"];
  189. [dataDict setObject:msgDict forKey:@"msg"];
  190. [XYCrossRoomPkManager sharedInstance].battleRoomCrossDict = dataDict;
  191. XYChatRoomKFBattleRoomInModel *battleRoomInModel = XYChatRoomKFBattleRoomInModel.new;
  192. [battleRoomInModel yy_modelSetWithDictionary:battleRoomCross];
  193. self.chatRoomController.infoManager.battleRoomCross = battleRoomInModel;
  194. if (battleRoomInModel.battleStatus == 201) {
  195. self.chatRoomController.infoManager.KFPkState = YES;
  196. }else {
  197. self.chatRoomController.infoManager.KFPkState = NO;
  198. }
  199. }
  200. // 跨房PK
  201. NSDictionary *auction = responseModel.data[@"auction"];
  202. if (auction) {
  203. XYChatRoomAuctionInfoModel *auctionModel = XYChatRoomAuctionInfoModel.new;
  204. [auctionModel yy_modelSetWithDictionary:auction];
  205. self.chatRoomController.infoManager.auctionInfoModel = auctionModel;
  206. self.chatRoomController.infoManager.isAuctioning = YES;
  207. }
  208. // 小时榜开关
  209. self.chatRoomController.infoManager.hourRankEnabled = [responseModel.data[@"hourRankEnabled"] boolValue];
  210. // 审核中不显示规则
  211. if (ApplicationDelegate.isVersionStatus) {
  212. self.chatRoomController.infoManager.roomInfoModel.roomRule = @"";
  213. }
  214. // 个播相关
  215. if (self.chatRoomController.infoManager.roomInfoModel.roomType == XYVoiceRoomTypeVoiceLive) {
  216. self.chatRoomController.infoManager.singleRtcHisId = [BaseMethod toString:responseModel.data[@"singleRtcHisId"]];
  217. // 主播是否暂离
  218. self.chatRoomController.infoManager.isSingleRtcAnchorOnline = [responseModel.data[@"isSingleRtcAnchorOnline"] boolValue];
  219. }
  220. // 是否开播
  221. self.chatRoomController.infoManager.isLive = [responseModel.data[@"isLive"] boolValue];
  222. // 房间类型统计
  223. if (self.chatRoomController.infoManager.roomInfoModel.roomType == XYVoiceRoomTypeLove) {
  224. // 进入[相亲房]的次数,在进入语音房时上报
  225. [StatisticsManager event:@"goto_dateroom"];
  226. }else if (self.chatRoomController.infoManager.roomInfoModel.roomType == XYVoiceRoomTypeOrder) {
  227. // 进入[派单房]的次数,在进入语音房时上报
  228. [StatisticsManager event:@"goto_dispatchroom"];
  229. }else if (self.chatRoomController.infoManager.roomInfoModel.roomType == XYVoiceRoomTypeAuction) {
  230. // 进入[拍卖房]的次数,在进入语音房时上报
  231. [StatisticsManager event:@"goto_auctionroom"];
  232. }else if (self.chatRoomController.infoManager.roomInfoModel.roomType == XYVoiceRoomTypeVoiceLive) {
  233. // 进入[个播房]的次数,在进入语音房时上报
  234. [StatisticsManager event:@"goto_personalliveroom"];
  235. }
  236. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  237. // 更新进入房间
  238. [self.chatRoomController enterRoom];
  239. });
  240. // 显示动画
  241. [self showAnimationCompletion:completion];
  242. }
  243. } failureHandler:^(ZYLNetworkError *error) {
  244. // 关闭进场动画
  245. [self.showAnimationView dismissCompletion:^{
  246. [SVProgressHUD showInfoWithStatus:error.domain];
  247. self.showAnimationView = nil;
  248. }];
  249. NSDictionary *data1 = error.responseObject;
  250. if ([data1[@"data"][@"goAuth"] isEqualToString:@"1"]) {//需要认证
  251. CustomActionAlertController *al = [[CustomActionAlertController alloc] initWithTitle:nil message:kLocalizedString(@"根据《网络游戏管理暂行办法》要求,未实名认证部分功能的使用将受到限制") sure:kLocalizedString(@"去认证") cancel:kLocalizedString(@"取消") selctedBlock:^(NSInteger index, NSString * _Nonnull title) {
  252. if ([title isEqualToString:kLocalizedString(@"去认证")]) {
  253. XYBankIdentityCardVerIfyViewController *controller = XYBankIdentityCardVerIfyViewController.new;
  254. controller.targetAction = 2;
  255. [[AppDelegate sharedDelegate].getCurrentController.navigationController pushViewController:controller animated:YES];
  256. }
  257. }];
  258. [al show];
  259. }
  260. }];
  261. }
  262. - (void)showAnimationCompletion:(void (^ __nullable)(void))completion {
  263. UINavigationController *currentNav = [ApplicationDelegate getCurrentController].navigationController;
  264. if ([currentNav.topViewController isKindOfClass:XYChatRoomViewController.class]) {
  265. !completion?:completion();
  266. return;
  267. }
  268. [currentNav pushViewController:self.chatRoomController animated:YES];
  269. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  270. // 阻止设备锁屏
  271. [self.showAnimationView dismissCompletion:^{
  272. self.showAnimationView = nil;
  273. [UIApplication sharedApplication].idleTimerDisabled = YES;
  274. !completion?:completion();
  275. }];
  276. });
  277. }
  278. /// 转变成悬浮按钮 showFloatingDrag YES显示小窗口
  279. - (void)dismissChatRoomWithShowFloatingDrag:(BOOL)showFloatingDrag completion:(void (^ __nullable)(void))completion {
  280. if (!self.isChatRooming) {
  281. !completion?:completion();
  282. return;
  283. }
  284. if (showFloatingDrag) {
  285. [self.chatRoomController.navigationController popViewControllerAnimated:YES];
  286. [self showVoiceFloatingDrag];
  287. // 开启设备锁屏
  288. [UIApplication sharedApplication].idleTimerDisabled = NO;
  289. !completion?:completion();
  290. }else {
  291. // 1.设置关闭状态
  292. self.chatRoomController.infoManager.enterClosedState = YES;
  293. // 2.显示loading
  294. [SVProgressHUD showWithStatus:kLocalizedString(@"关闭中")];
  295. // 3.关闭rtc、rtm、下麦
  296. [self.chatRoomController requestCloseRoomBlock:^{
  297. // 4.回收栈位
  298. UINavigationController *currentNavigation = self.chatRoomController.navigationController;
  299. NSMutableArray *marr = [[NSMutableArray alloc]initWithArray:currentNavigation.viewControllers];
  300. if ([[currentNavigation.viewControllers lastObject] isKindOfClass:XYChatRoomViewController.class]) {
  301. [self.chatRoomController.navigationController popViewControllerAnimated:YES];
  302. }else {
  303. for (NSInteger i = 0; i < marr.count; i++) {
  304. UIViewController *vc = marr[i];
  305. //防止删掉当前控制器
  306. if (i != (marr.count-1)) {
  307. if ([vc isKindOfClass:XYChatRoomViewController.class]) {
  308. [marr removeObject:vc];
  309. break;
  310. }
  311. }
  312. }
  313. currentNavigation.viewControllers = marr;
  314. if (currentNavigation.viewControllers.count == marr.count) {
  315. // 没删除则使用系统回收
  316. [self.chatRoomController.navigationController popViewControllerAnimated:YES];
  317. }
  318. }
  319. // 5.销毁语聊房
  320. [self clearChatRoom];
  321. !completion?:completion();
  322. }];
  323. }
  324. }
  325. - (BOOL)isChatRooming {
  326. if (_chatRoomController) {
  327. return YES;
  328. }
  329. return NO;
  330. }
  331. - (BOOL)isShrink {
  332. // 是否在聊天室
  333. if (self.isChatRooming) {
  334. if (_floatingDragView) {
  335. return YES;
  336. }
  337. }
  338. return NO;
  339. }
  340. - (void)showVoiceFloatingDrag {
  341. if (_floatingDragView == nil) {
  342. _floatingDragView = [XYFloatingDragView floatingDragViewWithFloatingDragType:XYFloatingDragTypeVoiceChatRoom];
  343. _floatingDragView.delegate = self;
  344. [_floatingDragView setupViewDataWithModel:self.chatRoomController.infoManager.roomInfoModel];
  345. }
  346. [_floatingDragView showAnimation:YES];
  347. }
  348. #pragma mark — XYFloatingDragViewDelegate 悬浮窗回调协议
  349. /// 展开聊天室
  350. - (void)openFloatingDragWindow {
  351. // 显示聊天室
  352. if (self.isShrink) {
  353. [self showAnimationCompletion:^{
  354. }];
  355. }
  356. // 销毁悬浮窗
  357. [self clearFloatingDragWindow];
  358. }
  359. /// 关闭聊天室
  360. - (void)closeFloatingDragWindow {
  361. [self closeChatRoomBlock:nil];
  362. }
  363. /// 销毁悬浮窗
  364. - (void)clearFloatingDragWindow {
  365. if (_floatingDragView) {
  366. [_floatingDragView clear];
  367. [_floatingDragView removeFromSuperview];
  368. _floatingDragView = nil;
  369. }
  370. }
  371. #pragma mark — 关闭房间
  372. - (void)closeChatRoomBlock:(void(^ __nullable)(void))block {
  373. [self dismissChatRoomWithShowFloatingDrag:NO completion:block];
  374. }
  375. - (void)clearChatRoom {
  376. // 销毁悬浮窗
  377. [self clearFloatingDragWindow];
  378. // 销毁控制器
  379. if (_chatRoomController) {
  380. [_chatRoomController clear];
  381. [_chatRoomController.view removeFromSuperview];
  382. _chatRoomController = nil;
  383. }
  384. // 开启设备锁屏
  385. [UIApplication sharedApplication].idleTimerDisabled = NO;
  386. [self reset];
  387. [SVProgressHUD dismiss];
  388. }
  389. //保存玩法已自动显示
  390. - (void)savePlayMethodShowState:(NSString *)roomId{
  391. [[NSUserDefaults standardUserDefaults] setObject:@"roomId" forKey:roomId];
  392. }
  393. //获取玩法是否已自动显示
  394. - (BOOL )getPlayMethodShowState:(NSString *)roomId{
  395. NSString *haveRoomId = [[NSUserDefaults standardUserDefaults] objectForKey:roomId];
  396. if (haveRoomId.length) {
  397. return YES;
  398. }
  399. return NO;
  400. }
  401. #pragma mark — 重置状态
  402. - (void)reset {
  403. _roomId = nil;
  404. }
  405. #pragma mark — Getter
  406. - (XYChatRoomShowAnimationView *)showAnimationView {
  407. if (!_showAnimationView) {
  408. _showAnimationView = [[XYChatRoomShowAnimationView alloc] initWithFrame:[UIScreen mainScreen].bounds];
  409. }
  410. return _showAnimationView;
  411. }
  412. @end