// // YMRoomViewController.m // YUMI // // Created by YUMI on 2021/10/11. // #import "XPRoomViewController.h" ///Third #import #import ///Tool #import "YUMIMacroUitls.h" #import "YUMIConstant.h" #import "AccountInfoStorage.h" #import "RtcManager.h" #import "XPRoomMiniManager.h" #import "TTPopup.h" #import "Api+ArrangeMic.h" #import "Api+Room.h" #import "DESEncrypt.h" #import "NSArray+Safe.h" #import "NSMutableDictionary+Saft.h" #import "XPSkillCardPlayerManager.h" #import "XCCurrentVCStackManager.h" #import "CountDownHelper.h" ///Model #import "RoomInfoModel.h" #import "UserInfoModel.h" #import "AttachmentModel.h" #import "ArrangeMicModel.h" #import "XPReleaseRadioModel.h" #import "GuildSuperAdminInfoModel.h" #import "XPKickUserModel.h" #import "ContentLevelUpgradeModel.h" #import "XPReceiveRedPacketModel.h" #import "XPRedPacketModel.h" #import "XPFreeGiftModel.h" #import "XPUserCardInfoModel.h" ///View #import "BaseNavigationController.h" #import "XPRoomBackContainerView.h" #import "XPRoomMenuContainerView.h" #import "XPRoomQuickMessageContainView.h" #import "MsRoomMessageMainView.h" #import "RoomHeaderView.h" #import "SocialStageView.h" #import "TenMicStageView.h" #import "FifteenMicStageView.h" #import "NineteenMicStageView.h" #import "TwentyMicStageView.h" #import "DatingStageView.h" #import "AnchorStageView.h" #import "AnchorPkStageView.h" //#import "XPRoomAnimationView.h" #import "RoomAnimationView.h" #import "XPRoomFunctionContainerView.h" #import "XPArrangeMicViewController.h" #import "XPRoomSettingInputView.h" #import "AnchorRoomScrollView.h" #import "AnchorRoomSrollTipView.h" #import "XPReceiveRedPacketView.h" #import "XPWebViewController.h" #import "SessionViewController.h" #import "XPFreeGiftsObtainView.h" ///P #import "XPRoomPresenter.h" #import "XPRoomProtocol.h" #import "XPWeakTimer.h" #import "RoomHostDelegate.h" #import "RoomGuestDelegate.h" #import "Api+RoomSetting.h" #import "XNDJTDDLoadingTool.h" #import "ClientConfig.h" #import "LittleGameStageView.h" #import "LittleGameScrollStageView.h" #import "XPRoomLittleGameContainerView.h" #import "StageViewManager.h" #import "PIRoomEnterRedPacketView.h" #import "XPIAPRechargeViewController.h" #import "XPCandyTreeInsufficientBalanceView.h" #import "GiftComboManager.h" #import "LuckyGiftWinningFlagView.h" #import "RoomBoomResultView.h" #import "RoomBoomManager.h" #import "RoomBoomExplosionView.h" #import "RoomBoomResultView.h" #import "XPSendGiftView.h" #import "RoomSideMenu.h" #import "RoomResourceManager.h" #import "LuckyPackageLogicManager.h" //#import "XPMineHallAnchorIncomeStatisViewController.h" UIKIT_EXTERN NSString * const kRoomGiftEffectUpdateNotificationKey; UIKIT_EXTERN NSString * const kRoomMiniNotificationKey; UIKIT_EXTERN NSString * kNewUserRechargeKey; UIKIT_EXTERN NSString * const kMessageFromPublicRoomWithAttachmentNotification; UIKIT_EXTERN NSString * const kFreeGiftCountdownNotification; NSString * const kHadShowAnchorRoomTipKey = @"kHadShowAnchorRoomTipKey";//是否展示过个播房上划用户引导 NSString * const kHadQuitOtherRoomKey = @"kHadQuitOtherRoomKey";//是否退出过非自己房间 @interface XPRoomViewController ()< XPRoomProtocol, RoomHostDelegate, NIMChatroomManagerDelegate, NIMChatManagerDelegate, NIMConversationManagerDelegate, NIMLoginManagerDelegate, XPRoomSettingInputViewDelegate, AnchorRoomScrollViewDelegate, NIMBroadcastManagerDelegate, XPRoomLittleGameContainerViewDelegate, CountDownHelperDelegate, PIRoomEnterRedPacketViewDelegate, XPReceiveRedPacketViewDelegate, XPCandyTreeInsufficientBalanceViewDelegate> ///背景 @property (nonatomic,strong) XPRoomBackContainerView *backContainerView; ///个播上下切换view @property (nonatomic, strong) AnchorRoomScrollView *anchorScrollView; ///房间信息 @property (nonatomic,strong) RoomHeaderView *roomHeaderView; ///坑位信息 @property (nonatomic,strong) StageView *stageView; @property (nonatomic,strong) StageViewManager *stageViewManager; @property (nonatomic,strong) TenMicStageView *tenMicStageView; @property (nonatomic,strong) FifteenMicStageView *fifteenMicStageView; @property (nonatomic,strong) TwentyMicStageView *twentyMicStageView; @property(nonatomic, strong) NineteenMicStageView *nineteenMicStageView; ///公屏 @property (nonatomic,strong) MsRoomMessageMainView *messageContainerView; ///快捷发言 @property (nonatomic, strong) XPRoomQuickMessageContainView *quickMessageContainerView; ///底部操作栏 @property (nonatomic,strong) XPRoomMenuContainerView *menuContainerView; ///活动 @property(nonatomic, strong) RoomSideMenu *sideMenu; ///动画的view @property (nonatomic,strong) RoomAnimationView *animationView; ///功能view的的容器 @property (nonatomic,strong) XPRoomFunctionContainerView *functionView; ///小游戏的容器 @property (nonatomic,strong) XPRoomLittleGameContainerView *littleGameView; ///房间的Uid @property (nonatomic,copy) NSString * roomUid; ///小游戏的id @property (nonatomic,copy) NSString *mgId; ///礼物id @property (nonatomic, copy) NSString *giftId; ///用户信息 @property (nonatomic,strong) UserInfoModel *userInfo; ///房间信息 @property (nonatomic,strong) RoomInfoModel *roomInfo; ///本地是否修改过礼物特效显示 当前房间如果设置过礼物特效是否显示的话 就不再跟随房间礼物特效的更新而更新 @property (nonatomic,assign) BOOL hasAnimationEffect; ///跟随的 @property (nonatomic,copy) NSString *fromNick; @property (nonatomic,assign) UserEnterRoomFromType fromType; @property (nonatomic,copy) NSString *fromUid; ///超管列表 @property (nonatomic,strong) NSArray *superMangerList; ///是否请求过了超管 @property (nonatomic,assign) BOOL isRequestSuperAdmin; ///是否是最小化进房 @property (nonatomic,assign) BOOL isMiniEnter; ///个播上划引导 @property (nonatomic, strong) AnchorRoomSrollTipView *anchorScrollTipView; ///滚动过的个播列表 @property (nonatomic,strong) NSMutableArray *anchorRoomList; ///序号 @property (nonatomic,assign) NSInteger anchorIndex; ///免费礼物数量 @property (nonatomic,strong) XPFreeGiftModel *freeModel; ///免费礼物弹窗 @property (nonatomic,strong) XPFreeGiftsObtainView *freeView; ///全服红包id @property(nonatomic,copy) NSString *redEnvelopeId; ///红包 @property(nonatomic,strong) PIRoomEnterRedPacketView *redPacketView; ///是否正在显示红包弹窗,防止显示多个弹窗 @property(nonatomic,assign) BOOL isShowRedPacket; @property(nonatomic,copy) NSString *releaseCoins; @property(nonatomic,copy) NSString *myCoins; @property(nonatomic,strong) UIButton *exitGameButton; /// 上麦请求弹窗定时器,用于10秒后自动移除弹窗 @property(nonatomic,strong) NSTimer *upMicAskTimer; /// 🔧 修复:保存 block 形式的通知观察者,防止内存泄漏 @property(nonatomic,strong) id exchangeRoomAnimationViewObserver; @end @implementation XPRoomViewController + (BOOL)openRoom:(NSString *)roomUid viewController:(UIViewController *)viewController { return [self openRoom:roomUid fromNick:nil fromType:0 fromUid:nil viewController:viewController]; } + (BOOL)openRoom:(NSString *)roomUid viewController:(UIViewController *)viewController redEnvelopeId:(NSString *)redEnvelopeId{ XPRoomViewController * roomVC = [[self alloc] init]; roomVC.roomUid = roomUid; roomVC.fromUid = nil; roomVC.fromType = 0; roomVC.fromNick = nil; roomVC.redEnvelopeId = redEnvelopeId; BaseNavigationController * baseNav = [[BaseNavigationController alloc] initWithRootViewController:roomVC]; baseNav.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:baseNav animated:YES completion:nil]; return YES; } + (BOOL)openRoom:(NSString*)roomUid fromNick:(NSString * __nullable)fromNick fromType:(UserEnterRoomFromType)fromType fromUid:(NSString * __nullable)fromUid viewController:(UIViewController*)viewController { XPRoomViewController * roomVC = [[self alloc] init]; roomVC.roomUid = roomUid; roomVC.fromUid = fromUid; roomVC.fromType = fromType; roomVC.fromNick = fromNick; BaseNavigationController * baseNav = [[BaseNavigationController alloc] initWithRootViewController:roomVC]; baseNav.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:baseNav animated:YES completion:nil]; return YES; } /**最小化进房 * @params roomUid 房主uid * @params viewController 启动方 */ + (BOOL)openMiniRoom:(NSString*)roomUid viewController:(UIViewController*)viewController { XPRoomViewController * roomVC = [[self alloc] init]; roomVC.roomUid = roomUid; roomVC.isMiniEnter = YES; BaseNavigationController * baseNav = [[BaseNavigationController alloc] initWithRootViewController:roomVC]; baseNav.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:baseNav animated:YES completion:nil]; return roomVC; } /**最小化进房 * @params roomUid 房主uid * @params viewController 启动方 * @params redEnvelopeId 全服红包id */ + (BOOL)openMiniRoom:(NSString*)roomUid viewController:(UIViewController*)viewController redEnvelopeId:(NSString *)redEnvelopeId{ XPRoomViewController * roomVC = [[self alloc] init]; roomVC.roomUid = roomUid; roomVC.isMiniEnter = YES; roomVC.redEnvelopeId = redEnvelopeId; BaseNavigationController * baseNav = [[BaseNavigationController alloc] initWithRootViewController:roomVC]; baseNav.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:baseNav animated:YES completion:nil]; return roomVC; } /** XPRoomViewController 不允许外部 init ,请通过该方法启动房间。 * @params roomUid 房主uid * @params viewController 启动方 * @params mgId 小游戏的id */ + (BOOL)openRoom:(NSString*)roomUid mgId:(NSString *)mgId viewController:(UIViewController*)viewController { XPRoomViewController * roomVC = [[self alloc] init]; roomVC.roomUid = roomUid; roomVC.mgId = mgId; BaseNavigationController * baseNav = [[BaseNavigationController alloc] initWithRootViewController:roomVC]; baseNav.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:baseNav animated:YES completion:nil]; return YES; } /// h5进房并弹出礼物面板 /// @param roomUid 房主Uid /// @param giftId 礼物id /// @param viewController 启动方 + (BOOL)openRoom:(NSString *)roomUid giftId:(NSString *)giftId viewController:(UIViewController *)viewController { XPRoomViewController * roomVC = [[self alloc] init]; roomVC.roomUid = roomUid; roomVC.giftId = giftId; BaseNavigationController * baseNav = [[BaseNavigationController alloc] initWithRootViewController:roomVC]; baseNav.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:baseNav animated:YES completion:nil]; return YES; } - (void)dealloc { NSLog(@"🔄 XPRoomViewController: 开始销毁"); [[RoomBoomManager sharedManager] leaveRoom]; [XPSkillCardPlayerManager shareInstance].photoIdList = nil; [XPSkillCardPlayerManager shareInstance].isInRoomVC = NO; [XPSkillCardPlayerManager shareInstance].isInRoomFirstRecharge = NO; [XPSkillCardPlayerManager shareInstance].isInRoom = NO; [XPSkillCardPlayerManager shareInstance].roomUid = @""; if([[XPRoomMiniManager shareManager] getRoomInfo]==nil){ [XPSkillCardPlayerManager shareInstance].isMineInMic = NO; } [[CountDownHelper shareHelper] stopCountDown]; [CountDownHelper shareHelper].delegate = nil; [[NIMSDK sharedSDK].chatroomManager removeDelegate:self]; [[NIMSDK sharedSDK].chatManager removeDelegate:self]; [[NIMSDK sharedSDK].loginManager removeDelegate:self]; [[NIMSDK sharedSDK].conversationManager removeDelegate:self]; [[NIMSDK sharedSDK].broadcastManager removeDelegate:self]; [[RoomBoomManager sharedManager] removeEventListenerForTarget:self]; // 🔧 修复:移除 block 形式的通知观察者 if (self.exchangeRoomAnimationViewObserver) { [[NSNotificationCenter defaultCenter] removeObserver:self.exchangeRoomAnimationViewObserver]; self.exchangeRoomAnimationViewObserver = nil; } [[NSNotificationCenter defaultCenter] removeObserver:self]; // 🔧 修复:清理 RoomAnimationView if (_animationView) { NSLog(@"🔄 XPRoomViewController: 清理 RoomAnimationView"); [_animationView removeItSelf]; [_animationView removeFromSuperview]; _animationView = nil; } // 清理上麦请求弹窗定时器 if (self.upMicAskTimer) { [self.upMicAskTimer invalidate]; self.upMicAskTimer = nil; } NSLog(@"🔄 XPRoomViewController: 销毁完成"); } - (XPRoomPresenter *)createPresenter { return [[XPRoomPresenter alloc] init]; } - (BOOL)isHiddenNavBar { return YES; } - (void)viewDidLoad { [super viewDidLoad]; [self exitOldRoom]; [self preLoadGifts]; [self initSubViews]; [self initSubViewConstraints]; [self setupNimSDK]; [self loadRoomDataAndUsers]; [self setupNotifications]; [self handleActivityContainerViewEvents]; ///获取房间超管列表 [self.presenter getRoomSuperAdmin:self.roomUid]; [XPSkillCardPlayerManager shareInstance].isInRoom = YES; [CountDownHelper shareHelper].delegate = self; [self setupForBoom]; [self handleGiftComboCallBack]; [self setupStageViewManager]; } //- (void)test { // XPMineHallAnchorIncomeStatisViewController *vc = [[XPMineHallAnchorIncomeStatisViewController alloc] init]; // [self.navigationController pushViewController:vc animated:YES]; //} - (void)handleGiftComboCallBack { @kWeakify(self); [[GiftComboManager sharedManager] setHandleRoomUIChanged:^(BOOL comboViewDisplay) { @kStrongify(self); dispatch_async(dispatch_get_main_queue(), ^{ self.sideMenu.hidden = comboViewDisplay; self.menuContainerView.hidden = comboViewDisplay; // 添加状态验证:如果要隐藏UI,确保连击确实在进行 if (comboViewDisplay && ![[GiftComboManager sharedManager] isActive]) { NSLog(@"⚠️ 检测到UI隐藏请求但连击未进行,执行强制重置"); [self forceBoomStateReset]; } }); }]; } - (void)setupForBoom { @kWeakify(self); [[RoomBoomManager sharedManager] registerBoomExplosion:^(id _Nonnull sth) { @kStrongify(self); [self.presenter getBoomDetail:self.roomUid]; if (![sth isKindOfClass:[NSArray class]]) { return; } dispatch_async(dispatch_get_main_queue(), ^{ [RoomBoomExplosionView display:self.view with:sth complete:^{ }]; }); } target:self]; [[RoomBoomManager sharedManager] registerBoomGiftDisplay:^(id _Nonnull sth) { @kStrongify(self); dispatch_async(dispatch_get_main_queue(), ^{ [RoomBoomResultView display:self.view attachment:sth]; }); } target:self]; [[RoomBoomManager sharedManager] registerBoomEnterRoomExplosion:^(id _Nonnull sth) { @kStrongify(self); if (![sth isKindOfClass:[NSArray class]]) { return; } dispatch_async(dispatch_get_main_queue(), ^{ [RoomBoomExplosionView display:self.view with:sth complete:^{ }]; }); } target:self]; } - (void)requestBoomData { [self.presenter getBoomRocketAnimationInfo:self.roomUid]; [self.presenter getBoomDetail:self.roomUid]; } - (void)loadRoomDataAndUsers { [XNDJTDDLoadingTool showAnchorLoading:self.navigationController.view]; [self.presenter initEnterRoom:self.roomUid user:[AccountInfoStorage instance].getUid]; } - (void)setupNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myGiftEffectUpdate:) name:kRoomGiftEffectUpdateNotificationKey object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(openRedPacketNotification:) name:@"kOpenRedPacketNotification" object:nil]; // 添加公共房间消息转发通知监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePublicRoomMessageForward:) name:@"MessageFromPublicRoomWithAttachmentNotification" object:nil]; // 添加应用生命周期保护 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; @kWeakify(self); // 🔧 修复:保存 block 观察者的返回值,防止内存泄漏 self.exchangeRoomAnimationViewObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"kExchangeRoomAnimationViewAndGameViewIndex" object:nil queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull notification) { @kStrongify(self); if (self.view.subviews.count > 0) { UIView *topView = self.view.subviews.lastObject; UIView *secondView = [self.view.subviews xpSafeObjectAtIndex:self.view.subviews.count-2]; if (secondView && secondView.tag == 913) { NSInteger index1 = [self.view.subviews indexOfObject:topView]; NSInteger index2 = [self.view.subviews indexOfObject:secondView]; [self.view exchangeSubviewAtIndex:index1 withSubviewAtIndex:index2]; } } }]; } - (void)setupNimSDK { //监听云信消息 [[NIMSDK sharedSDK].chatroomManager addDelegate:self]; [[NIMSDK sharedSDK].chatManager addDelegate:self]; [[NIMSDK sharedSDK].loginManager addDelegate:self]; [[NIMSDK sharedSDK].conversationManager addDelegate:self]; [[NIMSDK sharedSDK].broadcastManager addDelegate:self]; } /// 禮物面板緩存-2: 進房後,用當前的 roomUid 加載最新數據,並緩存 - (void)preLoadGifts { [self.presenter getNormalGiftList:self.roomUid]; ///获取免费礼物 [self.presenter getFreeGiftData]; if(![NSString isEmpty:self.redEnvelopeId]){ [self.presenter getRedPacketInft:self.redEnvelopeId]; } } #pragma mark - MSSessionReleaseHeadlinesViewDelegate -(void)releaseHeadlinesWithText:(NSString *)text{ XPCandyTreeInsufficientBalanceView *balanceView = [[XPCandyTreeInsufficientBalanceView alloc]initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; balanceView.delegate = self; [self.view addSubview:balanceView]; } #pragma mark - XPCandyTreeInsufficientBalanceViewDelegate - (void)payBalanceAction{ XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; webVC.type = @"4"; [self.navigationController pushViewController:webVC animated:YES]; } ///打开红包通知 -(void)openRedPacketNotification:(NSNotification *)not{ NSDictionary *redPacketDic = not.userInfo; NSInteger type = [redPacketDic[@"type"] integerValue]; NSInteger userId = [redPacketDic[@"uid"] integerValue]; // NSString *roomUid = redPacketDic[@"roomUId"]; if(type == 2){ [self.messageContainerView showUserCard:userId]; }else if (type == 3){ // [self.roomHeaderView showSharePanel]; }else if (type == 4){ NSString *scrolling = redPacketDic[@"scrolling"]; [self.menuContainerView showInputView:scrolling]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.menuContainerView menuResignFirstResponder]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; [self.menuContainerView recheckMicState]; } -(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; self.freeView.hidden = YES; // 如果连击正在进行,强制重置 if ([[GiftComboManager sharedManager] isActive]) { NSLog(@"📱 房间即将退出,检查连击状态"); [self forceBoomStateReset]; } } - (void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated]; self.navigationController.interactivePopGestureRecognizer.enabled = YES; [XPSkillCardPlayerManager shareInstance].isInRoomVC = NO; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.freeView.hidden = NO; self.navigationController.interactivePopGestureRecognizer.enabled = NO; [XPSkillCardPlayerManager shareInstance].isInRoomVC = YES; } #pragma mark - 连击状态管理 // 强制重置连击状态和恢复UI - (void)forceBoomStateReset { NSLog(@"🔧 XPRoomViewController 强制重置连击状态"); // 1. 直接重置连击管理器(会自动发送通知给所有相关组件) [[GiftComboManager sharedManager] forceBoomStateReset]; // 2. 确保UI恢复(双重保障) dispatch_async(dispatch_get_main_queue(), ^{ self.sideMenu.hidden = NO; self.menuContainerView.hidden = NO; NSLog(@"🔄 强制恢复底部操作栏和侧栏显示"); }); } // 应用生命周期保护 - (void)applicationDidEnterBackground:(NSNotification *)notification { if ([[GiftComboManager sharedManager] isActive]) { NSLog(@"📱 应用进入后台,检查连击状态"); [self forceBoomStateReset]; } } // 内存警告保护 - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; if ([[GiftComboManager sharedManager] isActive]) { NSLog(@"⚠️ 收到内存警告,检查连击状态"); [self forceBoomStateReset]; } } #pragma mark - Private Method - (void)initSubViews { self.view.backgroundColor = [UIColor darkGrayColor]; [self.view addSubview:self.backContainerView]; [self.view addSubview:self.littleGameView]; [self.view addSubview:self.stageView]; [self.view addSubview:self.messageContainerView]; [self.view addSubview:self.quickMessageContainerView]; [self.view addSubview:self.menuContainerView]; [self.view addSubview:self.sideMenu]; [self.view addSubview:self.redPacketView]; [self.view addSubview:self.roomHeaderView]; [self.view addSubview:self.functionView]; [self.view addSubview:self.animationView]; } - (void)__layoutTwentyMicStage { [self.stageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; } - (void)__layoutNineteenMicStage { [self.stageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; } - (void)__layoutFifteenMicStage { [self.stageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; } - (void)__layoutTenMicStage { [self.stageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; } - (void)initSubViewConstraints { [self.backContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }]; [self.littleGameView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }]; [self.roomHeaderView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.top.mas_equalTo(self.view); make.height.mas_equalTo(kNavigationHeight); }]; [self.stageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; [self.messageContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.stageView.mas_bottom); make.bottom.equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.leading.equalTo(self.view); make.trailing.equalTo(self.sideMenu.mas_leading).offset(-10); }]; CGFloat quickMsgHeight = 30; //记录最后关闭时间 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSNumber *closeCount = [defaults objectForKey:kRoomQuickMessageCloseCount]; if (closeCount.intValue > 3) { quickMsgHeight = 0; } else { quickMsgHeight = 30; } [self.quickMessageContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.mas_equalTo(self.view).offset(- 52 - kSafeAreaBottomHeight); make.height.mas_equalTo(0); make.leading.trailing.mas_equalTo(self.view); }]; [self.menuContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); if (iPhoneXSeries) { make.bottom.mas_equalTo(self.view); } else { make.bottom.mas_equalTo(-10); } make.height.mas_equalTo(52 + kSafeAreaBottomHeight); }]; [self.sideMenu mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.messageContainerView); make.trailing.mas_equalTo(self.view); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.width.mas_equalTo(87); }]; [self.redPacketView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.height.mas_equalTo(kGetScaleWidth(58)); make.trailing.mas_equalTo(-kGetScaleWidth(6)); make.bottom.mas_equalTo(-160); }]; [self.animationView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }]; [self.functionView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }]; } - (void)updateViewConstraintsOnAnchorRoom { [self.anchorScrollView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }]; [self.backContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.anchorScrollView.middleImageView); }]; [self.roomHeaderView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.top.mas_equalTo(self.anchorScrollView.middleImageView); make.height.mas_equalTo(kNavigationHeight); }]; [self.stageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.anchorScrollView.middleImageView); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; [self.messageContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.stageView.mas_bottom); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).mas_offset(-5); make.leading.equalTo(self.anchorScrollView.middleImageView); make.trailing.equalTo(self.sideMenu.mas_leading).offset(-10); }]; [self.quickMessageContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(0); make.bottom.mas_equalTo(self.backContainerView).mas_offset(-5-40-8-kSafeAreaBottomHeight); make.leading.equalTo(self.anchorScrollView.middleImageView); make.trailing.equalTo(self.sideMenu.mas_leading).offset(-10); }]; [self.menuContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.anchorScrollView.middleImageView); if (iPhoneXSeries) { make.bottom.mas_equalTo(self.view); } else { make.bottom.mas_equalTo(self.view).offset(-10); } make.height.mas_equalTo(52 + kSafeAreaBottomHeight); }]; [self.sideMenu mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.messageContainerView); make.trailing.mas_equalTo(self.anchorScrollView.middleImageView); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).mas_offset(-5); make.width.mas_equalTo(87); }]; [self.functionView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.anchorScrollView.middleImageView); }]; } - (void)handleActivityContainerViewEvents { @kWeakify(self); self.sideMenu.openRedPacketHandle = ^(XPRedPacketModel * _Nullable redModel,RoomType type,BOOL isChangeRoom) { @kStrongify(self); if(isChangeRoom == YES){ self.redPacketView.type = type; self.redPacketView.redPacketList = self.sideMenu.redPacketList; return; } XPReceiveRedPacketView *view = [[XPReceiveRedPacketView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; view.delegate = self; self.isShowRedPacket = YES; view.receiveModel = redModel; for (UIView *subView in self.view.subviews) { if([subView isKindOfClass:[XPReceiveRedPacketView class]]) { view.alphaView.backgroundColor = [UIColor clearColor]; break; } } [self.view addSubview:view]; [self.view bringSubviewToFront:view]; }; self.sideMenu.showSendGiftView = ^{ @kStrongify(self); NSString * roomUid = [NSString stringWithFormat:@"%ld", [self getRoomInfo].uid]; XPSendGiftView * giftView = [[XPSendGiftView alloc] initWithType:SendGiftType_Room uid:roomUid]; giftView.delegate = self; NSArray * giftUses = [self configGiftUsers:[self getMicroQueue]]; [giftView configGiftUsers:giftUses]; [self.getCurrentNav presentViewController:giftView animated:YES completion:nil]; }; } - (NSArray *)configGiftUsers:(NSMutableDictionary *)queue { NSMutableArray * array = [NSMutableArray array]; for (MicroQueueModel * microModel in queue.allValues) { if (microModel.userInfo && microModel.userInfo.uid >0) { UserInfoModel * userInfo = microModel.userInfo; XPGiftUserInfoModel * userModel = [[XPGiftUserInfoModel alloc] init]; userModel.avatar = userInfo.avatar; userModel.vipMic = userInfo.vipMic; userModel.position = [NSString stringWithFormat:@"%d", microModel.microState.position]; userModel.uid = userInfo.uid; if (self.getRoomInfo.type == RoomType_Anchor && microModel.microState.position == -1) {///个播房一直为离开模式,不需要添加房主位 continue; } [array addObject:userModel]; } } if (self.getRoomInfo.leaveMode) { RoomInfoModel * roomInfo= self.getRoomInfo; XPGiftUserInfoModel * userModel = [[XPGiftUserInfoModel alloc] init]; userModel.avatar = roomInfo.avatar; userModel.position = @"-1"; userModel.uid = roomInfo.uid; [array addObject:userModel]; } else if (self.getRoomInfo.type == RoomType_Anchor) { RoomInfoModel * roomInfo= self.getRoomInfo; BOOL hadContainerOwner = NO; for (UserInfoModel *userModel in array) { if (userModel.uid == roomInfo.uid) { hadContainerOwner = YES; break; } } if (!hadContainerOwner) { XPGiftUserInfoModel * userModel = [[XPGiftUserInfoModel alloc] init]; userModel.avatar = roomInfo.avatar; userModel.position = @"-1"; userModel.uid = roomInfo.uid; [array addObject:userModel]; } } return array; } - (void)exitOldRoom { NSString * roomUid = [NSString stringWithFormat:@"%ld", [XPRoomMiniManager shareManager].getRoomInfo.uid]; if (roomUid.integerValue > 0) { if ([roomUid isEqualToString:self.roomUid]) { self.isMiniEnter = YES; } else { //有最小化房间 并且要进入的房间和最小化的房间不一样的话 就先退掉 最小化的房间 NSString * roomId = [NSString stringWithFormat:@"%ld", [XPRoomMiniManager shareManager].getRoomInfo.roomId]; [self.presenter exitNIMRoom:roomId]; [[RtcManager instance] exitRoom]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [self.presenter reportUserOutRoom:roomUid]; [XPSkillCardPlayerManager shareInstance].micState = MICState_None; } } } -(BOOL)getIsMiniEnter{ return self.isMiniEnter; } - (void)userEnterRoomSuccess { AttachmentModel *attachment = [[AttachmentModel alloc]init]; attachment.first = CustomMessageType_Car_Notify; attachment.second = Custom_Message_Sub_Car_EnterRoom; NSMutableDictionary *att = [NSMutableDictionary dictionary]; if (self.userInfo.userVipInfoVO.enterHide) {///VIP隐身进房,不发座驾消息 return; } if (self.userInfo.platformRole == 1) { return; } if (self.userInfo.viewUrl.length > 0) { [att safeSetObject:self.userInfo.nick forKey:@"nick"]; [att safeSetObject:self.userInfo.viewUrl forKey:@"viewUrl"]; [att safeSetObject:@(self.userInfo.otherViewType) forKey:@"otherViewType"]; } else if (self.userInfo.carEffect.length > 0) { [att safeSetObject:self.userInfo.carEffect forKey:@"effect"]; [att safeSetObject:self.userInfo.nick forKey:@"nick"]; } else { return; } attachment.data = att; NSString *sessionID = [NSString stringWithFormat:@"%ld",self.roomInfo.roomId]; NIMMessage *message = [[NIMMessage alloc]init]; NIMCustomObject *object = [[NIMCustomObject alloc] init]; object.attachment = attachment; message.messageObject = object; //构造会话 NIMSession *session = [NIMSession session:sessionID type:NIMSessionTypeChatroom]; [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil]; } - (BOOL)updateStageView { NSLog(@"🔄 updateStageView: 开始更新 stageView,当前 alpha = %.2f", self.stageView.alpha); // 优先使用 StageViewManager 来管理 stageView if (self.stageViewManager) { NSLog(@"🔧 updateStageView: 使用 StageViewManager"); BOOL success = [self.stageViewManager updateStageViewForRoomType:self.roomInfo.type roomInfo:self.roomInfo container:self.view delegate:self]; if (success) { self.stageView = self.stageViewManager.currentStageView; if (self.stageView) { NSLog(@"🔧 updateStageView: StageViewManager 设置 alpha = 0 (之前 = %.2f)", self.stageView.alpha); self.stageView.alpha = 0; NSLog(@"✅ StageViewManager 成功更新 stageView: %@", NSStringFromClass([self.stageView class])); return YES; } } NSLog(@"⚠️ StageViewManager 更新失败,降级到原有逻辑"); } // 降级处理:原有逻辑 // NSLog(@"🔧 updateStageView: 使用降级逻辑"); // Class stageViewClass = [self stageViewClassForRoomInfo:self.roomInfo]; // if (stageViewClass) { //&& ![self.stageView isKindOfClass:stageViewClass]) { // NSLog(@"🔧 updateStageView: 创建新的 stageView: %@", NSStringFromClass(stageViewClass)); // [self.stageView removeFromSuperview]; // self.stageView = nil; // self.stageView = [[stageViewClass alloc] initWithDelegate:self]; // NSLog(@"🔧 updateStageView: 降级逻辑设置 alpha = 0 (之前 = %.2f)", self.stageView.alpha); // self.stageView.alpha = 0; // NSLog(@"✅ 降级逻辑成功更新 stageView: %@", NSStringFromClass([self.stageView class])); // return YES; // } NSLog(@"❌ 所有 stageView 更新方法都失败了"); return NO; } - (Class)stageViewClassForRoomInfo:(RoomInfoModel *)roomInfo { if (roomInfo.roomModeType == RoomModeType_Open_Blind) { return [DatingStageView class]; } if (roomInfo.datingState == RoomDatingStateChangeType_Close && ![self.stageView isKindOfClass:[SocialStageView class]]) { return [SocialStageView class]; } if (roomInfo.type == RoomType_Anchor) { if (roomInfo.roomModeType == RoomModeType_Open_AcrossRoomPK_mode && ![self.stageView isKindOfClass:[AnchorPKStageView class]]) { return [AnchorPKStageView class]; } else if (roomInfo.roomModeType == RoomModeType_Normal_Mode && ![self.stageView isKindOfClass:[AnchorStageView class]]) { return [AnchorStageView class]; } } else if (roomInfo.type == RoomType_MiniGame) { return [LittleGameScrollStageView class]; } else if (roomInfo.type == RoomType_19Mic) { return [NineteenMicStageView class]; } else if (roomInfo.type == RoomType_20Mic) { return [TwentyMicStageView class]; } else if (roomInfo.type == RoomType_15Mic) { return [FifteenMicStageView class]; } else if (roomInfo.type == RoomType_10Mic) { return [TenMicStageView class]; } else if (roomInfo.hadChangeRoomType && ![self.stageView isKindOfClass:[SocialStageView class]]) { return [SocialStageView class]; } return [SocialStageView class]; } - (void)changeStageViewOnRoomUpdate { NSLog(@"🔄 changeStageViewOnRoomUpdate: 开始更新 stageView"); if (![self updateStageView]) { NSLog(@"❌ changeStageViewOnRoomUpdate: updateStageView 失败"); return; } NSLog(@"✅ changeStageViewOnRoomUpdate: updateStageView 成功,当前 alpha = %.2f", self.stageView.alpha); // 🔧 新增:发送房间类型变化通知 [[NSNotificationCenter defaultCenter] postNotificationName:@"RoomTypeChanged" object:nil userInfo:@{@"roomType": @(self.roomInfo.type)}]; if (!self.stageView.superview) { NSLog(@"🔧 changeStageViewOnRoomUpdate: 添加 stageView 到视图层级"); [self.view insertSubview:self.stageView belowSubview:self.roomHeaderView]; // 防止小屏机麦位挡住按钮 NSInteger index_sideMenu = -1; NSInteger index_stageView = -1; for (UIView *view in self.view.subviews) { if (index_sideMenu == -1 || index_stageView == -1) { if (view == self.sideMenu) { index_sideMenu = [self.view.subviews indexOfObject:view]; } if (view == self.stageView) { index_stageView = [self.view.subviews indexOfObject:view]; } } else { [self.view exchangeSubviewAtIndex:index_sideMenu withSubviewAtIndex:index_stageView]; break; } } } NSLog(@"🔧 changeStageViewOnRoomUpdate: 设置 stageView.alpha = 1 (之前 = %.2f)", self.stageView.alpha); self.stageView.alpha = 1; NSLog(@"✅ changeStageViewOnRoomUpdate: stageView.alpha 已设置为 1"); // 调试:检查最终状态 [self debugStageViewStatus]; [self addExitGameButton]; self.quickMessageContainerView.hidden = YES; [self.quickMessageContainerView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(0); }]; switch (self.roomInfo.type) { case RoomType_MiniGame: { [self.stageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom).offset(26 + 4); make.height.mas_equalTo(self.stageView.hightForStageView); }]; CGFloat height = 80; if (iPhoneXSeries) { height = 100; } [self.messageContainerView mas_remakeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(height); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.leading.mas_equalTo(self.view); make.trailing.mas_equalTo(self.sideMenu.mas_leading).offset(-10); }]; [self.sideMenu displayForMiniGame]; [self.sideMenu mas_remakeConstraints:^(MASConstraintMaker *make) { make.trailing.mas_equalTo(self.view); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.width.mas_equalTo(87); }]; } break; default: { [self.stageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; [self.messageContainerView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.stageView.mas_bottom); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.leading.mas_equalTo(self.view); make.trailing.mas_equalTo(self.sideMenu.mas_leading).offset(-10); }]; if (self.roomInfo.type == RoomType_19Mic || self.roomInfo.type == RoomType_20Mic) { [self.sideMenu mas_remakeConstraints:^(MASConstraintMaker *make) { make.trailing.mas_equalTo(self.view); make.height.mas_equalTo(160); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.width.mas_equalTo(87); }]; } else { [self.sideMenu mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.messageContainerView); make.trailing.mas_equalTo(self.view); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).offset(-5); make.width.mas_equalTo(87); }]; } } break; } } - (void)changeStageViewOnAnchorRoom { if (self.roomInfo.roomModeType == RoomModeType_Open_AcrossRoomPK_mode && ![self.stageView isKindOfClass:[AnchorPKStageView class]]) { [self.stageView removeFromSuperview]; self.stageView = nil; self.stageView = [[AnchorPKStageView alloc] initWithDelegate:self]; } else if(self.roomInfo.roomModeType == RoomModeType_Normal_Mode && ![self.stageView isKindOfClass:[AnchorStageView class]]) { [self.stageView removeFromSuperview]; self.stageView = nil; self.stageView = [[AnchorStageView alloc] initWithDelegate:self]; } if (!self.stageView.superview) { [self.anchorScrollView insertSubview:self.stageView belowSubview:self.roomHeaderView]; } [self.stageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.anchorScrollView.middleImageView); make.top.mas_equalTo(self.roomHeaderView.mas_bottom); make.height.mas_equalTo(self.stageView.hightForStageView); }]; [self.messageContainerView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.stageView.mas_bottom); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).mas_offset(-5); make.leading.mas_equalTo(self.anchorScrollView.middleImageView); make.trailing.mas_equalTo(self.sideMenu.mas_leading).offset(-10); }]; CGFloat quickMsgHeight = 30; //记录最后关闭时间 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSNumber *closeCount = [defaults objectForKey:kRoomQuickMessageCloseCount]; if (closeCount.intValue > 3 || self.roomInfo.speakTemplate.count <=0) { quickMsgHeight = 0; } else { quickMsgHeight = 30; } self.quickMessageContainerView.titleArray = self.roomInfo.speakTemplate; [self.quickMessageContainerView mas_remakeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(0); make.bottom.mas_equalTo(self.backContainerView).mas_offset(-5-40-8-kSafeAreaBottomHeight); make.leading.trailing.mas_equalTo(self.anchorScrollView.middleImageView); }]; [self.sideMenu mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.messageContainerView); make.trailing.mas_equalTo(self.anchorScrollView.middleImageView); make.bottom.mas_equalTo(self.quickMessageContainerView.mas_top).mas_offset(-5); make.width.mas_equalTo(87); }]; } - (void)setRoomInfo:(RoomInfoModel *)roomInfo { if (_roomInfo == roomInfo) { return; } _roomInfo = roomInfo; [[LuckyPackageLogicManager sharedInstance] setRoomUid:@(roomInfo.uid).stringValue]; [[RoomResourceManager sharedManager] updateCurrentSkinID:roomInfo.usedMicSkinId effectID:roomInfo.usedMicEffectId]; [self.sideMenu updateView]; } #pragma mark - Game Switch - (void)addExitGameButton { [self removeExitGameButton]; if (self.roomInfo.type != RoomType_MiniGame) { return; } if (_exitGameButton == nil) { _exitGameButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_exitGameButton setTitle:@"切换" forState:UIControlStateNormal]; [_exitGameButton setImage:[UIImage imageNamed:@"ms_room_game_switch_button"] forState:UIControlStateNormal]; [_exitGameButton addTarget:self action:@selector(didTapExitGameButton) forControlEvents:UIControlEventTouchUpInside]; } [self.view addSubview:self.exitGameButton]; [self.exitGameButton mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.stageView.mas_bottom).offset(10); make.leading.mas_equalTo(self.view).offset(12); make.width.height.equalTo(@21); }]; } - (void)removeExitGameButton { [self.exitGameButton removeFromSuperview]; } - (void)didTapExitGameButton { if ([self.littleGameView isInSudGame]) { [XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"XPRoomFunctionContainerView19")]; } else { @kWeakify(self); [TTPopup alertWithMessage:YMLocalizedString(@"XPRoomFunctionContainerView20") confirmHandler:^{ @kStrongify(self); [XNDJTDDLoadingTool showLoading]; [self exitLittleGame]; } cancelHandler:^{ }]; } } - (void)exitLittleGame { RoomInfoModel * roomInfo = self.getRoomInfo; NSMutableDictionary * params = [NSMutableDictionary dictionary]; NSString * ticket = [AccountInfoStorage instance].getTicket; [params setObject:ticket forKey:@"ticket"]; [params setObject:@(roomInfo.uid).stringValue forKey:@"uid"]; [params setObject:[NSString stringWithFormat:@"%ld", roomInfo.uid] forKey:@"roomUid"]; if (roomInfo.title.length > 0) { [params setObject:roomInfo.title forKey:@"title"]; } if (roomInfo.roomPwd.length > 0) { [params setObject:roomInfo.roomPwd forKey:@"roomPwd"]; } else{ [params setObject:@"" forKey:@"roomPwd"]; } if (roomInfo.tagId > 0) { [params setObject:[NSString stringWithFormat:@"%ld", roomInfo.tagId] forKey:@"tagId"]; } if (self.roomInfo.oldType == 0) { self.roomInfo.oldType = RoomType_Game; } [params setObject:@(self.roomInfo.oldType) forKey:@"type"]; [params setObject:@"0" forKey:@"mgId"]; [params setObject:@(roomInfo.hasAnimationEffect) forKey:@"hasAnimationEffect"]; [Api ownerUpdateRoomInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if (code == 200) { [XNDJTDDLoadingTool hideHUD]; } else { [XNDJTDDLoadingTool showErrorWithMessage:msg]; } } params:params]; [self.littleGameView handleSelfInExitEvent]; [self.littleGameView destroyMG]; } #pragma mark- XPReceiveRedPacketViewDelegate - (void)closeViewAction{ self.isShowRedPacket = NO; } #pragma mark- PIRoomEnterRedPacketViewDelegate - (void)openRedPacketWithModel:(XPRedPacketModel *)redModel{ XPReceiveRedPacketView *view = [[XPReceiveRedPacketView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; view.receiveModel = redModel; view.delegate = self; self.isShowRedPacket = YES; for (UIView *subView in self.view.subviews) { if([subView isKindOfClass:[XPReceiveRedPacketView class]]) { view.alphaView.backgroundColor = [UIColor clearColor]; break; } } [self.view addSubview:view]; [self.view bringSubviewToFront:view]; } #pragma mark - CountDownHelperDelegate - (void)onCountdownFinish { [[NSNotificationCenter defaultCenter]postNotificationName:kFreeGiftCountdownNotification object:nil userInfo:@{@"isCountdownFinish":@(YES)}]; if(self.freeModel.curStage.integerValue < self.freeModel.maxStage.integerValue){ [self.presenter getFreeGiftData]; } if(self.freeModel.curStage.intValue == 0){ self.freeView.freeModel = self.freeModel; if(!self.freeView.superview){ [kWindow addSubview:self.freeView]; } } } - (void)onCountdownOpen:(int)time { NSInteger seconds = time; int hours = (seconds)%(24*3600)/3600; int minutes = (seconds)%3600/60; int second = (seconds)%60; [[NSNotificationCenter defaultCenter] postNotificationName:kFreeGiftCountdownNotification object:nil userInfo:@{@"text": [NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, second], @"isCountdownFinish": @(NO)}]; } - (void)cancelRoomArrangeMic { ///退出排麦 if (self.roomInfo.roomModeType == RoomModeType_Open_Micro_Mode || self.roomInfo.roomModeType == RoomModeType_Open_Blind) { NSString * roomUid = [NSString stringWithFormat:@"%ld", self.roomInfo.uid]; NSString * uid = [AccountInfoStorage instance].getUid; [Api getRoomArrangeMicList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if (code == 200) { ArrangeMicModel * arrangeMicModel= [ArrangeMicModel modelWithJSON:data.data]; if (arrangeMicModel.myPos.intValue > 0) { __block NSString * grouptype = @"0"; if (self.roomInfo.roomModeType == RoomModeType_Open_Blind) { [arrangeMicModel.queue enumerateObjectsUsingBlock:^(ArrangeMicUserModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj.uid.integerValue == [AccountInfoStorage instance].getUid.integerValue) { grouptype = [NSString stringWithFormat:@"%ld", obj.groupType]; *stop = YES; } }]; } [Api cancelArrangeMic:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {} roomUid:roomUid operUid:uid groupType:grouptype]; } } } roomUid:roomUid operUid:uid page:@"1" pageSize:@"50"]; }else if(self.roomInfo.roomModeType == RoomModeType_Open_PK_Mode) { NSString * roomUid = [NSString stringWithFormat:@"%ld", self.roomInfo.uid]; NSString * uid = [AccountInfoStorage instance].getUid; [Api getRoomPKUserList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if (code == 200) { ArrangeMicModel * arrangeMicModel= [ArrangeMicModel modelWithJSON:data.data]; if (arrangeMicModel.myPos.intValue > 0) { __block NSString * grouptype = @"0"; [arrangeMicModel.queue enumerateObjectsUsingBlock:^(ArrangeMicUserModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj.uid.integerValue == [AccountInfoStorage instance].getUid.integerValue) { grouptype = [NSString stringWithFormat:@"%ld", obj.groupType]; *stop = YES; } }]; [Api cancelRoomPKArrangeMic:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { } roomUid:roomUid operUid:uid groupType:grouptype]; } } } roomUid:roomUid operUid:uid page:@"1" pageSize:@"50"]; } } ///超管进入密码房间 - (void)superAdminEnterPwdRoom:(RoomInfoModel *)roomInfo { __block BOOL isSuperAdmin = NO; [self.superMangerList enumerateObjectsUsingBlock:^(GuildSuperAdminInfoModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj.uid isEqualToString:[AccountInfoStorage instance].getUid]) { isSuperAdmin = YES; *stop = YES; } }]; if (!isSuperAdmin) { isSuperAdmin = self.userInfo.platformRole == 1; } if (!isSuperAdmin) { XPRoomSettingInputView * titleView = [[XPRoomSettingInputView alloc] init]; titleView.maxCount = 15; titleView.delegate = self; titleView.type = RoomSettingInputType_Input_Pwd; TTPopupConfig * config = [[TTPopupConfig alloc] init]; config.contentView = titleView; config.maskBackgroundAlpha = 1; config.shouldDismissOnBackgroundTouch = NO; [TTPopup popupWithConfig:config]; } else { self.roomInfo.datingState = roomInfo.roomModeType == RoomModeType_Open_Blind ? RoomDatingStateChangeType_Open : RoomDatingStateChangeType_Normal; [self changeStageViewOnRoomUpdate]; [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; if ([XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) {// 最小化进房 还是原来的房间的话 不需要重新进入云信 因为压根没退 [self.presenter enterNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId] user:self.userInfo]; [self.functionView onRoomEntered]; [self.messageContainerView onRoomEntered]; [self.menuContainerView onRoomEntered]; } else { //虽然没退出房间 但是队列还是要拿的 [self.stageView onRoomMiniEntered]; [self.messageContainerView onRoomMiniEntered]; [self.functionView onRoomMiniEntered]; [self.functionView onRoomEntered]; [self.menuContainerView onRoomMiniEntered]; } [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; } } ///超管进个播有密码房间 - (void)handleSuperManagerEnterAnchorRoom:(RoomInfoModel *)roomInfo { __block BOOL isSuperAdmin = NO; [self.superMangerList enumerateObjectsUsingBlock:^(GuildSuperAdminInfoModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj.uid isEqualToString:[AccountInfoStorage instance].getUid]) { isSuperAdmin = YES; *stop = YES; } }]; if (!isSuperAdmin) { isSuperAdmin = self.userInfo.platformRole == 1; } if (!isSuperAdmin) { XPRoomSettingInputView * titleView = [[XPRoomSettingInputView alloc] init]; titleView.maxCount = 15; titleView.delegate = self; titleView.type = RoomSettingInputType_Input_Pwd; TTPopupConfig * config = [[TTPopupConfig alloc] init]; config.contentView = titleView; config.maskBackgroundAlpha = 1; config.shouldDismissOnBackgroundTouch = NO; [TTPopup popupWithConfig:config]; } else { self.roomInfo.datingState = roomInfo.roomModeType == RoomModeType_Open_Blind ? RoomDatingStateChangeType_Open : RoomDatingStateChangeType_Normal; if (!self.anchorScrollView.superview) { [self.view insertSubview:self.anchorScrollView belowSubview:self.menuContainerView]; } [self.backContainerView removeFromSuperview]; [self.stageView removeFromSuperview]; [self.messageContainerView removeFromSuperview]; [self.quickMessageContainerView removeFromSuperview]; [self.sideMenu removeFromSuperview]; [self.roomHeaderView removeFromSuperview]; [self.functionView removeFromSuperview]; [self.anchorScrollView addSubview:self.backContainerView]; [self.anchorScrollView addSubview:self.stageView]; [self.anchorScrollView addSubview:self.messageContainerView]; [self.anchorScrollView addSubview:self.quickMessageContainerView]; [self.anchorScrollView addSubview:self.sideMenu]; [self.anchorScrollView addSubview:self.roomHeaderView]; if (!self.menuContainerView.superview) { [self.view addSubview:self.menuContainerView]; } [self.anchorScrollView addSubview:self.functionView]; [self.view bringSubviewToFront:self.animationView]; [self updateViewConstraintsOnAnchorRoom]; [self changeStageViewOnAnchorRoom]; [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; if ([XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) {// 最小化进房 还是原来的房间的话 不需要重新进入云信 因为压根没退 [self.presenter enterNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId] user:self.userInfo]; [self.functionView onRoomEntered]; [self.messageContainerView onRoomEntered]; [self.menuContainerView onRoomEntered]; } else { //虽然没退出房间 但是队列还是要拿的 [self.stageView onRoomMiniEntered]; [self.messageContainerView onRoomMiniEntered]; [self.functionView onRoomMiniEntered]; [self.functionView onRoomEntered]; [self.menuContainerView onRoomMiniEntered]; } [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; } } ///展示个播上划引导 - (void)showAnchorScrollTipView { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *anchoScrollTip = [defaults objectForKey:kHadShowAnchorRoomTipKey]; if (!anchoScrollTip) { UIWindow *window = [UIApplication sharedApplication].delegate.window; [window addSubview:self.anchorScrollTipView]; [window bringSubviewToFront:self.anchorScrollTipView]; } } -(void)requesstShieldingAction{ [self.presenter requestShieldingWithType:@"1" objId:[NSString stringWithFormat:@"%ld",self.roomInfo.uid]]; } -(void)requestShieldingSuccess{ [self showErrorToast:YMLocalizedString(@"RoomHeaderView11")]; [self exitRoom]; } #pragma mark - 本地礼物特效更新 - (void)myGiftEffectUpdate:(NSNotification *)notification { NSDictionary * dic = notification.object; self.roomInfo.hasAnimationEffect = ((NSNumber *)dic[@"hasAnimationEffect"]).boolValue; self.hasAnimationEffect = self.roomInfo.hasAnimationEffect; [self.roomHeaderView onRoomUpdate]; } #pragma mark - XPRoomProtocol ///获取已解锁照片id列表 -(void)getUnlockRoomAlbumPhotoListSuccessWithList:(NSArray *)list{} ///获取踢人房间列表 -(void)getKickUserListSuccessWithList:(NSArray *)list{ NSString *uid = [[AccountInfoStorage instance]getUid]; for (id obj in list) { if([obj integerValue] == [uid integerValue]){ [self exitRoom]; [XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"XPRoomViewController0")]; break; } } } - (void)handleRoomWithPasswordAfterInitRoom { if (!self.isRequestSuperAdmin) { @kWeakify(self); [Api getRoomSuperAdminList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); NSArray * array = [GuildSuperAdminInfoModel modelsWithArray:data.data]; self.superMangerList = array; [self superAdminEnterPwdRoom:self.roomInfo]; } roomUid:self.roomUid]; } else { [self superAdminEnterPwdRoom:self.roomInfo]; } } - (void)handleRoomWithoutPasswordAfterInitRoom { NSLog(@"🔄 handleRoomWithoutPasswordAfterInitRoom: 开始处理无密码房间"); self.roomInfo.datingState = (self.roomInfo.roomModeType == RoomModeType_Open_Blind) ? RoomDatingStateChangeType_Open : RoomDatingStateChangeType_Normal; NSLog(@"🔧 handleRoomWithoutPasswordAfterInitRoom: 调用 changeStageViewOnRoomUpdate"); [self changeStageViewOnRoomUpdate]; NSLog(@"✅ handleRoomWithoutPasswordAfterInitRoom: changeStageViewOnRoomUpdate 完成"); [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; self.quickMessageContainerView.titleArray = self.roomInfo.speakTemplate; if ([XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) { [self.functionView onRoomEntered]; [self.messageContainerView onRoomEntered]; [self.menuContainerView onRoomEntered]; // 通知云信重新进房 [self.presenter enterNIMRoom:@(self.roomInfo.roomId).stringValue user:self.userInfo]; } else { //虽然没退出房间 但是队列还是要拿的 [self.stageView onRoomMiniEntered]; [self.functionView onRoomMiniEntered]; [self.sideMenu onRoomMiniEntered]; [self.functionView onRoomEntered]; [self.menuContainerView onRoomMiniEntered]; // PK 状态下,从最小化进房需要模仿初始化房间,丢 2 次 roominfo 进去 functionView if (self.roomInfo.roomModeType == RoomModeType_Open_AcrossRoomPK_mode || self.roomInfo.roomModeType == RoomModeType_Open_PK_Mode) { [self.functionView onRoomEntered]; } [self.messageContainerView onRoomMiniEntered]; } [self cleanMiniRoomStatues]; } - (void)enterMyRoom { if (self.roomInfo.roomId > 0) { // 存在房间信息,直接使用房间信息开房 if (self.roomInfo.type == RoomType_MiniGame && self.roomInfo.mgId > 0) { self.mgId = [NSString stringWithFormat:@"%lld", self.roomInfo.mgId]; } [self.presenter openRoom:self.roomInfo.title type:self.roomInfo.type roomPwd:self.roomInfo.roomPwd roomDesc:self.roomInfo.roomDesc backPic:@"" mgId:self.mgId]; } else { // 不存在房间信息,全新开房 NSString* title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomViewController1"), self.userInfo.nick]; RoomType type = RoomType_Game; if (self.mgId.length > 0) { type = RoomType_MiniGame; } [self.presenter openRoom:title type:type roomPwd:@"" roomDesc:@"" backPic:@"" mgId:self.mgId]; } } - (void)cleanMiniRoomStatues { [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; } - (void)initEnterRoomSuccess:(RoomInfoModel *)roomInfo user:(UserInfoModel *)userInfo { [XNDJTDDLoadingTool hideHUDInView:self.navigationController.view]; [XPSkillCardPlayerManager shareInstance].roomUid = @(roomInfo.uid).stringValue; userInfo.fromUid = self.fromUid; userInfo.fromType = self.fromType; userInfo.fromNick = self.fromNick; self.hasAnimationEffect = roomInfo.hasAnimationEffect; self.roomInfo = roomInfo; self.userInfo = userInfo; [self requestBoomData]; @kWeakify(self); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{ @kStrongify(self); //获取一下红包信息 [self.presenter getRedPacket:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; [self getOnlineCount]; }); switch (roomInfo.type) { case RoomType_Anchor: [self handleInitAnchorRoom]; [self showAnchorScrollTipView]; break; default: { if (roomInfo.valid) { // 房间有效,直接进入房间 if (roomInfo.roomPwd.length > 0 && roomInfo.uid != [AccountInfoStorage instance].getUid.integerValue && [XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) {//进房密码的情况 [self handleRoomWithPasswordAfterInitRoom]; } else { [self handleRoomWithoutPasswordAfterInitRoom]; } } else { // 房间无效,分是否为自己房间进行处理 if ([self.roomUid isEqualToString:[NSString stringWithFormat:@"%ld", userInfo.uid]]) { // 当前用户进入自己房间 [self enterMyRoom]; } else { // 当前用户进入别人房间 [self showSuccessToast:YMLocalizedString(@"XPRoomViewController2")]; [self enterRoomFail:0]; } } } break; } [self.menuContainerView recheckMicState]; } - (void)openRoomSuccess:(RoomInfoModel *)roomInfo { [XNDJTDDLoadingTool hideHUDInView:self.navigationController.view]; self.roomInfo = roomInfo; [XPSkillCardPlayerManager shareInstance].is9Mic = roomInfo.type == RoomType_Game; if (roomInfo.type == RoomType_Anchor) { [self handleInitAnchorRoom]; [self showAnchorScrollTipView]; return; } [self changeStageViewOnRoomUpdate]; [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; [self.functionView onRoomEntered]; [self.messageContainerView onRoomEntered]; self.quickMessageContainerView.titleArray = self.roomInfo.speakTemplate; [self.presenter enterNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId] user:self.userInfo]; } - (void)enterRoomSuccess:(NIMChatroom *)chatRoom { [XNDJTDDLoadingTool hideHUDInView:self.navigationController.view]; [self.stageView onRoomEntered]; [self.functionView onRoomEntered]; //上报进房 if (self.roomInfo != nil) { [self.presenter reportUserInterRoom:[NSString stringWithFormat:@"%zd", self.roomInfo.uid]]; } if (self.giftId.length) { ///有的时候 拉取麦序的话 可能会有点延迟 导致送礼物的人 没有拉取到 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:@"kShowGiftView" object:@{@"giftId": self.giftId}]; }); } } - (void)enterRoomFail:(NSInteger)code { [XNDJTDDLoadingTool hideHUDInView:self.navigationController.view]; [self hideHUD]; if (code == 13003) { [self showErrorToast:YMLocalizedString(@"XPRoomViewController3")]; } [self dismissViewControllerAnimated:YES completion:nil]; } -(void)getOnlineCount{ @kWeakify(self); [Api requestRoomOnlineUserList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); if(code == 200){ NSMutableArray *temp = @[].mutableCopy; NSArray *list = [XPMessageRemoteExtModel modelsWithArray:data.data]; for (XPMessageRemoteExtModel *model in list) { if (model.platformRole != 1) { [temp addObject:model]; } } self.roomInfo.onlineNum = temp.count; [self.functionView updateOnlineCount:[NSString stringWithFormat:@"%ld",temp.count] countList:temp.copy isUpdateCount:NO]; } // 更安全的輪詢 @kWeakify(self); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @kStrongify(self); if (self) { [self getOnlineCount]; } }); } roomUid:self.roomUid]; } ///请求房间超管成功 ///这个接口本来是想和roominfo 和userinfo 一起请求的 但是 进房的同步操作 只有超管进入密码房间才会有同步的问题 - (void)getRoomSuperAdminSuccess:(NSArray *)list { self.isRequestSuperAdmin = YES; self.superMangerList = list; } ///获取推荐滚动的个播房列表(只有第一次进房获取) - (void)getNextAnchorRoomSuccess:(RoomInfoModel *)roomInfo { [self hideHUD]; if (roomInfo) { //获取下一个房间成功 if (![self.anchorRoomList containsObject:self.roomUid]) { [self.anchorRoomList addObject:self.roomUid]; } self.anchorIndex = self.anchorRoomList.count -1; //1、退出房间操作 self.anchorScrollView.isCanScrollTop = YES; self.anchorScrollView.contentOffset = CGPointMake(0, KScreenHeight); self.isRequestSuperAdmin = NO; [self exitOldRoom]; [self.presenter exitNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [[RtcManager instance] exitRoom]; [self.presenter reportUserOutRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; [self.functionView onRoomChange]; //2、移除房间子控件 [self.stageView removeFromSuperview]; [self.messageContainerView removeFromSuperview]; [self.quickMessageContainerView removeFromSuperview]; [self.sideMenu removeFromSuperview]; [self.roomHeaderView removeFromSuperview]; [self.functionView removeFromSuperview]; self.functionView = nil; self.messageContainerView = nil; self.stageView = nil; [self.menuContainerView removeFromSuperview]; self.menuContainerView = nil; //3、重新进入房间 self.roomUid = [NSString stringWithFormat:@"%zd", roomInfo.uid]; [self.presenter initEnterRoom:self.roomUid user:[AccountInfoStorage instance].getUid]; /// 公屏 福袋礼物爆出的礼物 需要依赖 当前房间中的礼物列表 需要提前获取礼物列表 可以拿到礼物 没有想到别的方法去解决这个问题 有需要改的在修改吧 [self.presenter getNormalGiftList:self.roomUid]; ///获取房间超管列表 [self.presenter getRoomSuperAdmin:self.roomUid]; } else { if (self.anchorScrollView.isCanScrollTop) { self.anchorScrollView.contentOffset = CGPointMake(0, KScreenHeight); } else { self.anchorScrollView.contentOffset = CGPointMake(0, 0); } [self showErrorToast:YMLocalizedString(@"XPRoomViewController4")]; } } - (void)getCurrentRoomInfoSuccess:(RoomInfoModel *)roomInfo { [self hideHUD]; self.anchorScrollView.contentOffset = CGPointMake(0, KScreenHeight); if (roomInfo && roomInfo.valid) { //1、退出房间操作 self.isRequestSuperAdmin = NO; [self exitOldRoom]; [self.presenter exitNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [[RtcManager instance] exitRoom]; [self.presenter reportUserOutRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; //2、移除房间子控件 // [self.backContainerView removeFromSuperview]; [self.stageView removeFromSuperview]; [self.messageContainerView removeFromSuperview]; [self.quickMessageContainerView removeFromSuperview]; [self.sideMenu removeFromSuperview]; [self.roomHeaderView removeFromSuperview]; [self.functionView removeFromSuperview]; self.functionView = nil; self.messageContainerView = nil; self.stageView = nil; [self.menuContainerView removeFromSuperview]; self.menuContainerView = nil; //3、重新进入房间 self.roomUid = [NSString stringWithFormat:@"%zd", roomInfo.uid]; [self.presenter initEnterRoom:self.roomUid user:[AccountInfoStorage instance].getUid]; /// 公屏 福袋礼物爆出的礼物 需要依赖 当前房间中的礼物列表 需要提前获取礼物列表 可以拿到礼物 没有想到别的方法去解决这个问题 有需要改的在修改吧 [self.presenter getNormalGiftList:self.roomUid]; ///获取房间超管列表 [self.presenter getRoomSuperAdmin:self.roomUid]; } else { [self showErrorToast:YMLocalizedString(@"XPRoomViewController5")]; } } ///个播房初始化一些操作 - (void)handleInitAnchorRoom { if (self.roomInfo.valid) { // 房间有效,直接进入房间 if (self.roomInfo.roomPwd.length > 0 && self.roomInfo.uid != [AccountInfoStorage instance].getUid.integerValue && [XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) {//进房密码的情况 if (!self.isRequestSuperAdmin) { @kWeakify(self); [Api getRoomSuperAdminList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); NSArray * array = [GuildSuperAdminInfoModel modelsWithArray:data.data]; self.superMangerList = array; [self handleSuperManagerEnterAnchorRoom:self.roomInfo]; } roomUid:self.roomUid]; } else { [self handleSuperManagerEnterAnchorRoom:self.roomInfo]; } } else { self.roomInfo.datingState = self.roomInfo.roomModeType == RoomModeType_Open_Blind ? RoomDatingStateChangeType_Open : RoomDatingStateChangeType_Normal; [self __removeAllViews]; if (!self.anchorScrollView.superview) { [self.view addSubview:self.anchorScrollView]; } [self.anchorScrollView addSubview:self.backContainerView]; [self.anchorScrollView addSubview:self.stageView]; [self.anchorScrollView addSubview:self.messageContainerView]; [self.anchorScrollView addSubview:self.quickMessageContainerView]; [self.anchorScrollView addSubview:self.sideMenu]; [self.anchorScrollView addSubview:self.roomHeaderView]; [self.anchorScrollView addSubview:self.menuContainerView]; [self.anchorScrollView addSubview:self.functionView]; [self.view bringSubviewToFront:self.animationView]; [self updateViewConstraintsOnAnchorRoom]; [self changeStageViewOnAnchorRoom]; [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; if ([XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) {// 最小化进房 还是原来的房间的话 不需要重新进入云信 因为压根没退 [self.presenter enterNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId] user:self.userInfo]; [self.functionView onRoomEntered]; [self.messageContainerView onRoomEntered]; [self.menuContainerView onRoomEntered]; } else { //虽然没退出房间 但是队列还是要拿的 [self.stageView onRoomMiniEntered]; [self.messageContainerView onRoomMiniEntered]; [self.functionView onRoomMiniEntered]; [self.functionView onRoomEntered]; [self.menuContainerView onRoomMiniEntered]; } [self cleanMiniRoomStatues]; } } else { // 房间无效,分是否为自己房间进行处理 if ([self.roomUid isEqualToString:[NSString stringWithFormat:@"%ld", self.userInfo.uid]]) { // 当前用户进入自己房间 if (self.roomInfo.roomId > 0) { // 存在房间信息,直接使用房间信息开房 if (self.roomInfo.type == RoomType_MiniGame && self.roomInfo.mgId > 0) { self.mgId = [NSString stringWithFormat:@"%lld", self.roomInfo.mgId]; } [self.presenter openRoom:self.roomInfo.title type:self.roomInfo.type roomPwd:self.roomInfo.roomPwd roomDesc:self.roomInfo.roomDesc backPic:@"" mgId:self.mgId]; } else { // 不存在房间信息,全新开房 NSString* title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomViewController6"), self.userInfo.nick]; RoomType type = RoomType_Game; if (self.mgId.length > 0) { type = RoomType_MiniGame; } [self.presenter openRoom:title type:type roomPwd:@"" roomDesc:@"" backPic:@"" mgId:self.mgId]; } } else { // 当前用户进入别人房间 // TODO: 房主已经下线。 [self showSuccessToast:YMLocalizedString(@"XPRoomViewController7")]; [self enterRoomFail:0]; } } } - (void)getRedPacketInfoSuccess:(XPRedPacketModel *)redInfo{ XPReceiveRedPacketView *view = [[XPReceiveRedPacketView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; view.delegate = self; self.isShowRedPacket = YES; redInfo.validityType = 0; redInfo.kind = 1; view.receiveModel = redInfo; view.inAllPacketRoom = YES; for (UIView *subView in self.view.subviews) { if([subView isKindOfClass:[XPReceiveRedPacketView class]]) { view.alphaView.backgroundColor = [UIColor clearColor]; break; } } [self.view addSubview:view]; [self.view bringSubviewToFront:view]; } - (void)getRedPacketSuccess:(NSArray *)list { if(list.count > 0){ self.sideMenu.redPacketList = [NSMutableArray arrayWithArray:list]; } } -(void)getFreeGiftDataSuccess:(XPFreeGiftModel *)freeModel{ self.freeModel = freeModel; self.menuContainerView.freeModel = freeModel; if(self.freeModel.curStage.integerValue < self.freeModel.maxStage.integerValue){ [CountDownHelper shareHelper].isCountdownFinish = NO; [[CountDownHelper shareHelper] openCountdownWithTime:freeModel.curStageSecond.intValue]; }else{ if([CountDownHelper shareHelper].isCountdownFinish == NO){ [CountDownHelper shareHelper].isCountdownFinish = YES; } [[NSNotificationCenter defaultCenter]postNotificationName:kFreeGiftCountdownNotification object:nil userInfo:@{@"isHiddenCountdown":@(YES)}]; [[CountDownHelper shareHelper] stopCountDown]; } if(self.freeModel.curStage.intValue > 0 && [[XPRoomMiniManager shareManager].curState isEqualToString:@"0"]){ self.freeView.freeModel = self.freeModel; if(!self.freeView.superview){ [kWindow addSubview:self.freeView]; } [XPRoomMiniManager shareManager].curState = nil; } } #pragma mark - NIMChatroomManagerDelegate - (void)chatroomBeKicked:(NIMChatroomBeKickedResult *)result { if (result.reason == 5) { [self showErrorToast:YMLocalizedString(@"XPRoomViewController9")]; } [self.presenter exitNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [self cancelRoomArrangeMic]; [[RtcManager instance] exitRoom]; [self.presenter reportUserOutRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; [self.littleGameView handleSelfInExitEvent]; [self.littleGameView destroyMG]; [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - NIMChatManagerDelegate - (void)__removeAllViews { [self.anchorScrollView removeFromSuperview]; [self.backContainerView removeFromSuperview]; [self.stageView removeFromSuperview]; [self.messageContainerView removeFromSuperview]; [self.quickMessageContainerView removeFromSuperview]; [self.sideMenu removeFromSuperview]; [self.roomHeaderView removeFromSuperview]; [self.functionView removeFromSuperview]; [self.menuContainerView removeFromSuperview]; } - (void)onRecvMessages:(NSArray *)messages { // 入口排查日志:批次大小、线程和时间戳 for (NIMMessage * message in messages) { ///房间内收到p2p的消息 比如升级消息 if (message.session.sessionType == NIMSessionTypeP2P) { if(message.messageType == NIMMessageTypeCustom) { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) { AttachmentModel * attachment = (AttachmentModel *)obj.attachment; if (attachment.first == CustomMessageType_User_UpGrade) { ContentLevelUpgradeModel * levelInfo = [ContentLevelUpgradeModel modelWithDictionary:attachment.data]; if (attachment.second == Custom_Message_Sub_User_UpGrade_Exper) { self.userInfo.userLevelVo.experLevelSeq = levelInfo.levelSeq; } else if(attachment.second == Custom_Message_Sub_User_UpGrade_Charm) { self.userInfo.userLevelVo.charmLevelSeq = levelInfo.levelSeq; } } } } } // 非房间内消息不处理(记录过滤原因) if (message.session.sessionType != NIMSessionTypeChatroom) { NSLog(@"[Recv] ⛔️ 过滤:非聊天室消息 | type=%ld | sid=%@", (long)message.session.sessionType, message.session.sessionId); continue; } if (![message.session.sessionId isEqualToString:@(self.roomInfo.roomId).stringValue]) { // if (message.messageType == NIMMessageTypeCustom) { // NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; // if ([obj.attachment isKindOfClass:[AttachmentModel class]]) { // AttachmentModel *att = (AttachmentModel *)obj.attachment; // if (!att.isFromPublic) { // NSLog(@"[Recv] ⛔️ 过滤:房间不匹配 | msg.sid=%@ | curRoomId=%@", // message.session.sessionId, @(self.roomInfo.roomId).stringValue); // continue; // } // } // }else { NSLog(@"[Recv] ⛔️ 过滤:房间不匹配 | msg.sid=%@ | curRoomId=%@", message.session.sessionId, @(self.roomInfo.roomId).stringValue); continue; // } } NSLog(@"[Recv] --- Message Raw Attach Content: %@, %@, %ld", @(message.senderClientType), message.rawAttachContent, (long)message.messageType); if ([message.rawAttachContent containsString:@"\"allRoomMsg\":1"]) { NSLog(@"[Recv] --- 拦截旧的全房间消息"); continue; } if (message.messageType == NIMMessageTypeNotification) { [self handleNIMNotificationTypeMessage:message]; } else if (message.messageType == NIMMessageTypeCustom) { // 自定义消息排查日志:first/second/size3 #if DEBUG if ([message.messageObject isKindOfClass:[NIMCustomObject class]]) { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if ([obj.attachment isKindOfClass:[AttachmentModel class]]) { AttachmentModel *att = (AttachmentModel *)obj.attachment; NSData *payloadJSON = nil; @try { payloadJSON = [NSJSONSerialization dataWithJSONObject:att.data ?: @{} options:0 error:nil]; } @catch (__unused NSException *e) {} NSLog(@"[Recv] 🎯 自定义消息 | first=%ld second=%ld | payload=%lub | sid=%@ | ts=%.3f", (long)att.first, (long)att.second, (unsigned long)payloadJSON.length, message.session.sessionId, [[NSDate date] timeIntervalSince1970]); } } #endif [self handleNimCustomTypeMessage:message]; } else if(message.messageType == NIMMessageTypeText) { [self.messageContainerView handleNIMTextMessage:message]; [self.littleGameView handleNIMTextMessage:message]; } else if(message.messageType == NIMMessageTypeTip) { [self.messageContainerView handleNIMTextMessage:message]; }else if(message.messageType == NIMMessageTypeImage){ [self.messageContainerView handleNIMImageMessage:message]; } } } - (void)handleNIMNotificationTypeMessage:(NIMMessage *)message { NIMNotificationObject *notiMsg = (NIMNotificationObject *)message.messageObject; NIMChatroomNotificationContent *content = (NIMChatroomNotificationContent *)notiMsg.content; if (![notiMsg.content isKindOfClass:[NIMChatroomNotificationContent class]]) { // content 可能为其他类型,不处理 return; } NSInteger onLineNumber = self.roomInfo.onlineNum; switch (content.eventType) { case NIMChatroomEventTypeInfoUpdated: // 麦序状态更新 { NSDictionary *data = [content.notifyExt toJSONObject]; [self handleSwitchRoomType:data]; } break; case NIMChatroomEventTypeEnter: { if (content.source.userId.integerValue == [AccountInfoStorage instance].getUid.integerValue){ [self.presenter getKickUserListWithRoomUid:@(self.roomInfo.uid).stringValue]; } if (content.source.userId.integerValue != [AccountInfoStorage instance].getUid.integerValue && self.userInfo.platformRole != 1) { onLineNumber += 1; }else { ///如果是自己的话 如果有坐骑的话 [self userEnterRoomSuccess]; ///在活动页面 判断是否显示 相亲加入的按钮 所以需要等用户进房成功之后才能获取 房间角色 [self.sideMenu onRoomUpdate]; [self.menuContainerView onRoomUpdate]; } break; } case NIMChatroomEventTypeAddBlack: case NIMChatroomEventTypeKicked: case NIMChatroomEventTypeExit: onLineNumber -= 1; break; case NIMChatroomEventTypeQueueChange: // 麦序上下麦 { NSDictionary* data = (NSDictionary *)content.ext; UserInfoModel* userInfo = [UserInfoModel modelWithJSON:[data objectForKey:NIMChatroomEventInfoQueueChangeItemValueKey]]; NSInteger changeType = [data[NIMChatroomEventInfoQueueChangeTypeKey] integerValue]; if (changeType == 1 && userInfo.uid == [AccountInfoStorage instance].getUid.integerValue) { [self cancelRoomArrangeMic]; } } break; case NIMChatroomEventTypeAddManager: { NIMChatroomNotificationMember *targets = [content.targets firstObject]; if (targets.userId.integerValue == self.userInfo.uid) { [XNDJTDDLoadingTool showSuccessWithMessage:YMLocalizedString(@"1.0.34_text_15")]; } } break; case NIMChatroomEventTypeRemoveManager: { NIMChatroomNotificationMember *targets = [content.targets firstObject]; if (targets.userId.integerValue == self.userInfo.uid) { [XNDJTDDLoadingTool showSuccessWithMessage:YMLocalizedString(@"1.0.34_text_16")]; } } break; default: break; } self.roomInfo.onlineNum = onLineNumber; [self.functionView updateOnlineCount:[NSString stringWithFormat:@"%ld",onLineNumber] countList:@[] isUpdateCount:YES]; [self.roomHeaderView onRoomUpdate]; [self.stageView handleNIMNotificationMessage:message]; [self.animationView handleNIMNotificationMessage:message]; [self.messageContainerView handleNIMNotificationMessage:message]; [self.sideMenu handleNIMNotificationMessage:message]; [self.menuContainerView handleNIMNotificationMessage:message]; [self.functionView handleNIMNotificationMessage:message]; [self.littleGameView handleNIMNotificationMessage:message]; if([self.stageView findMicroViewByUid:@(self.userInfo.uid).stringValue] != nil){ [XPSkillCardPlayerManager shareInstance].isMineInMic = YES; }else{ [XPSkillCardPlayerManager shareInstance].isMineInMic = NO; }; } - (void)handleSwitchRoomType:(NSDictionary *)data { int type = [data[@"type"] intValue]; switch (type) { case 1: // 房间信息变化 case 3: // 房间信息 & 麦位信息变化 { NSMutableDictionary *lastRoomInfoDic = [NSMutableDictionary dictionaryWithDictionary:[self.roomInfo model2dictionary]]; [lastRoomInfoDic addEntriesFromDictionary: ((NSString *)data[@"roomInfo"]).toJSONObject]; RoomInfoModel *newRoomInfo = [RoomInfoModel modelWithJSON:lastRoomInfoDic]; if (newRoomInfo.type != RoomType_MiniGame) { newRoomInfo.mgId = 0; } newRoomInfo.hasAnimationEffect = self.hasAnimationEffect; if (newRoomInfo.roomModeType == RoomModeType_Open_Blind && self.roomInfo.roomModeType != RoomModeType_Open_Blind) { ///普通房 切换为相亲房 newRoomInfo.datingState = RoomDatingStateChangeType_Open; } else if(newRoomInfo.roomModeType != RoomModeType_Open_Blind && self.roomInfo.roomModeType == RoomModeType_Open_Blind) { ///关闭了相亲房 newRoomInfo.datingState = RoomDatingStateChangeType_Close; } else { newRoomInfo.datingState = RoomDatingStateChangeType_Normal; } //房间类型是否变更了(从个播->普通,个播->小游戏等) newRoomInfo.hadChangeRoomType = self.roomInfo.type != newRoomInfo.type; BOOL anchorToOther = newRoomInfo.type != RoomType_Anchor && self.roomInfo.type == RoomType_Anchor;//个播变其他房 RoomType currentType = self.roomInfo.type; self.roomInfo = newRoomInfo; [self.backContainerView onRoomUpdate]; self.quickMessageContainerView.titleArray = self.roomInfo.speakTemplate; if (self.roomInfo.type == RoomType_Anchor && self.roomInfo.hadChangeRoomType) {///从其他房变为个播房 [self handleInitAnchorRoom]; [self showAnchorScrollTipView]; } else if (anchorToOther) { [self __removeAllViews]; [self.view addSubview:self.backContainerView]; [self.view addSubview:self.stageView]; [self.view addSubview:self.messageContainerView]; [self.view addSubview:self.quickMessageContainerView]; [self.view addSubview:self.menuContainerView]; [self.view addSubview:self.sideMenu]; [self.view addSubview:self.roomHeaderView]; [self.view bringSubviewToFront:self.menuContainerView]; [self.view addSubview:self.functionView]; [self.view bringSubviewToFront:self.animationView]; [self initSubViewConstraints]; [self changeStageViewOnRoomUpdate]; [self.stageView onRoomUpdate]; [self.menuContainerView onRoomUpdate]; [self.functionView onRoomUpdate]; [self.sideMenu onRoomUpdate]; [self.messageContainerView onRoomUpdate]; [self.littleGameView onRoomUpdate]; } else { if (self.roomInfo.type == RoomType_Anchor) { [self changeStageViewOnAnchorRoom]; } else if (self.roomInfo.type == RoomType_20Mic) { [self __layoutTwentyMicStage]; [self changeStageViewOnRoomUpdate]; [self.twentyMicStageView onRoomUpdate]; } else if (self.roomInfo.type == RoomType_19Mic) { [self __layoutNineteenMicStage]; [self changeStageViewOnRoomUpdate]; [self.nineteenMicStageView onRoomUpdate]; } else if (self.roomInfo.type == RoomType_15Mic) { [self __layoutFifteenMicStage]; [self changeStageViewOnRoomUpdate]; [self.fifteenMicStageView onRoomUpdate]; } else if (self.roomInfo.type == RoomType_10Mic) { [self __layoutTenMicStage]; [self changeStageViewOnRoomUpdate]; [self.tenMicStageView onRoomUpdate]; } else { [self changeStageViewOnRoomUpdate]; } [self.stageView onRoomUpdate]; [self.menuContainerView onRoomUpdate]; [self.functionView onRoomUpdate]; [self.sideMenu onRoomUpdate]; [self.messageContainerView onRoomUpdate]; [self.littleGameView onRoomUpdate]; } } break; } } - (void)handleNimCustomTypeMessage:(NIMMessage *)message { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) { AttachmentModel * attachment = (AttachmentModel *)obj.attachment; [self.stageView handleNIMCustomMessage:message]; [self.animationView handleNIMCustomMessage:message]; [self.menuContainerView handleNIMCustomMessage:message]; [self.sideMenu handleNIMCustomMessage:message]; [self.functionView handleNIMCustomMessage:message]; [self.littleGameView handleNIMCustomMessage:message]; [self.messageContainerView handleNIMCustomMessage:message]; switch (attachment.first) { case ClientMessage_Type: switch (attachment.second) { case ClientMessage_UpMic_Ask: [self handleUpMicAsk:attachment]; break; case ClientMessage_UpMic_Agree: [self handleUpMicAgree:attachment]; break; case ClientMessage_UpMic_Reject: [XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"20.20.62_text_4")]; break; } break; case CustomMessageType_First_Recharge_Reward: switch (attachment.second) { case Custom_Message_Sub_Room_First_Recharge_Reward: self.userInfo.isFirstCharge = NO; [self.menuContainerView onRoomUpdate]; [self.sideMenu onRoomUpdate]; break; } break; case CustomMessageType_Update_RoomInfo: switch (attachment.second) { case Custom_Message_Sub_Update_RoomInfo_MessageState: { ///兼容安卓和iOS 协议不同的问题 NSDictionary * dic= attachment.data[@"roomInfo"]; if (dic.allKeys.count <=0) { dic = attachment.data; } RoomInfoModel * roomInfo = [RoomInfoModel modelWithDictionary:dic]; self.roomInfo.isCloseScreen = roomInfo.isCloseScreen; [self.menuContainerView onRoomUpdate]; } break; case Custom_Message_Sub_Update_RoomInfo_AnimateEffect: { NSDictionary * dic= attachment.data[@"roomInfo"]; if (dic.allKeys.count <=0) { dic = attachment.data; } RoomInfoModel * roomInfo = [RoomInfoModel modelWithDictionary:dic]; self.roomInfo.hasAnimationEffect = roomInfo.hasAnimationEffect; [self.roomHeaderView onRoomUpdate]; } break; } break; case CustomMessageType_Queue: switch (attachment.second) { case Custom_Message_Sub_Queue_Invite: { NSDictionary *dic = attachment.data; NSString *uid = dic[@"uid"]; if (uid.integerValue == [AccountInfoStorage instance].getUid.integerValue) { [self cancelRoomArrangeMic]; } } break; } break; case CustomMessageType_Hall_Super_Admin: switch (attachment.second) { case Custom_Message_Sub_Hall_Super_Admin_Kick_Manager_Out_Room: { XPKickUserModel * userInfo = [XPKickUserModel modelWithJSON:attachment.data]; if (userInfo.targetUid == [AccountInfoStorage instance].getUid.integerValue) { [self.presenter exitNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [self cancelRoomArrangeMic]; [[RtcManager instance] exitRoom]; [self.presenter reportUserOutRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; [self.littleGameView handleSelfInExitEvent]; [self.littleGameView destroyMG]; [self dismissViewControllerAnimated:YES completion:nil]; } } break; } break; case CustomMessageType_RedPacket: switch (attachment.second) { case Custom_Message_Sub_RoomDiamandRedPacket: { XPReceiveRedPacketView *view = [[XPReceiveRedPacketView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; XPRedPacketModel *data = [XPRedPacketModel modelWithJSON:attachment.data]; view.delegate = self; self.isShowRedPacket = YES; data.validityType = 0; data.kind = 1; data.redEnvelopeId = attachment.data[@"redEnvelopeId"]; view.receiveModel = data; for (UIView *subView in self.view.subviews) { if([subView isKindOfClass:[XPReceiveRedPacketView class]]) { view.alphaView.backgroundColor = [UIColor clearColor]; break; } } [self.view addSubview:view]; [self.view bringSubviewToFront:view]; if(self.sideMenu.redPacketList == nil){ self.sideMenu.redPacketList = [NSMutableArray array]; } NSMutableArray *redPacketList = [NSMutableArray arrayWithArray:self.sideMenu.redPacketList]; [redPacketList insertObject:data atIndex:0]; self.sideMenu.redPacketList = redPacketList; } break; case Custom_Message_Sub_NewRoomDiamandRedPacket: { XPRedPacketModel *curData = [XPRedPacketModel modelWithJSON:attachment.data]; if(self.sideMenu.redPacketList == nil){ self.sideMenu.redPacketList = [NSMutableArray array]; } NSMutableArray *redPacketList = [NSMutableArray arrayWithArray:self.sideMenu.redPacketList]; [redPacketList insertObject:curData atIndex:0]; if(self.roomInfo.uid > 0 && curData.redEnvelopeNum.integerValue != redPacketList.count){ [self.presenter getRedPacket:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; return; } curData.redEnvelopeId = attachment.data[@"redEnvelopeId"]; if(curData.validityType == 0){ XPReceiveRedPacketView *view = [[XPReceiveRedPacketView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; view.delegate = self; self.isShowRedPacket = YES; view.receiveModel = curData; for (UIView *subView in self.view.subviews) { if([subView isKindOfClass:[XPReceiveRedPacketView class]]) { view.alphaView.backgroundColor = [UIColor clearColor]; break; } } [self.view addSubview:view]; [self.view bringSubviewToFront:view]; } self.sideMenu.redPacketList = redPacketList; } break; } break; case CustomMessageType_Free_Gift_Star_Reset_Time: switch (attachment.second) { case Custom_Message_Sub_Free_Gift_Star_Reset_Time: [self.presenter getFreeGiftData]; [[NSNotificationCenter defaultCenter]postNotificationName:kFreeGiftCountdownNotification object:nil userInfo:@{@"isReset":@(YES)}]; break; case Custom_Message_Sub_Update_Gift_Information: [self.presenter getFreeGiftData]; [[NSNotificationCenter defaultCenter]postNotificationName:kFreeGiftCountdownNotification object:nil userInfo:@{@"updateGiftInfo":attachment.data ?: @""}]; break; } break; case CustomMessageType_Custom_Room_Background: switch (attachment.second) { case Custom_Message_Sub_Custom_Room_Background: if ([attachment.data isKindOfClass:[NSDictionary class]]) { NSString *url = attachment.data[@"url"]; if (![NSString isEmpty:url]) { self.roomInfo.backPic = url;//@"https://tva1.moyu.im/mw600/9f0b0dd5ly1hvacrep5fhj20jg0t60w4.jpg"; [self.backContainerView onRoomUpdate]; } } break; } break; case CustomMessageType_RoomLevel_Update: switch (attachment.second) { case Custom_Message_Sub_RoomLevel_Update: if ([attachment.data isKindOfClass:[NSDictionary class]]) { NSString *url = attachment.data[@"roomLevelIcon"]; NSNumber *roomLevel = attachment.data[@"roomLevel"]; if (![NSString isEmpty:url] && roomLevel.integerValue > self.roomHeaderView.tag) { self.roomHeaderView.tag = roomLevel.integerValue; [self.roomHeaderView updateLevel:url]; self.roomInfo.roomLevelIcon = url; } } break; } break; } } } - (void)handleUpMicAsk:(AttachmentModel *)attachment { NSNumber *targetUid = [attachment.data objectForKey:@"targetUid"]; if (!targetUid || ![targetUid.stringValue isEqualToString:[AccountInfoStorage instance].getUid]) { return; } // 先清理之前的定时器(如果存在) if (self.upMicAskTimer) { [self.upMicAskTimer invalidate]; self.upMicAskTimer = nil; } TTAlertConfig *config = [[TTAlertConfig alloc] init]; config.title = YMLocalizedString(@"20.20.62_text_1"); config.message = YMLocalizedString(@"20.20.62_text_2"); config.actionStyle = TTAlertActionBothStyle; // 自定义按钮 config.confirmButtonConfig.title = YMLocalizedString(@"MessageContentGuildView5"); config.cancelButtonConfig.title = YMLocalizedString(@"MessageContentGuildView4"); // 再觸發的話,clean 舊內容 [TTPopup dismiss]; [self removeUpMicAskTimer]; @kWeakify(self); [TTPopup alertWithConfig:config confirmHandler:^{ @kStrongify(self); // 用户点击确认,清理定时器 [self removeUpMicAskTimer]; [self sendResponseUpMicMessage:attachment.data isAgree:YES]; } cancelHandler:^{ @kStrongify(self); // 用户点击取消,清理定时器 [self removeUpMicAskTimer]; [self sendResponseUpMicMessage:attachment.data isAgree:NO]; }]; // 设置10秒后自动移除弹窗的定时器 self.upMicAskTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(autoDismissUpMicAskPopup) userInfo:nil repeats:NO]; } - (void)removeUpMicAskTimer { if (self.upMicAskTimer) { [self.upMicAskTimer invalidate]; self.upMicAskTimer = nil; } } /** 自动移除上麦请求弹窗 10秒后自动调用,移除弹窗并清理定时器 */ - (void)autoDismissUpMicAskPopup { // 移除弹窗 [TTPopup dismiss]; // 清理定时器 if (self.upMicAskTimer) { [self.upMicAskTimer invalidate]; self.upMicAskTimer = nil; } NSLog(@"⏰ 上麦请求弹窗已自动移除(10秒超时)"); } - (void)handleUpMicAgree:(AttachmentModel *)attachment { NSDictionary *originalData = attachment.data; NSNumber *position = [originalData objectForKey:@"position"]; NSNumber *targetUid = [originalData objectForKey:@"targetUid"]; if (!position || !targetUid) { return; } NSNumber *sendTime = [originalData objectForKey:@"sendTime"]; if (!sendTime) { return; } else { int64_t nowMillis = (int64_t)([[NSDate date] timeIntervalSince1970] * 1000); if (nowMillis - sendTime.doubleValue > 10 * 1000) { // 已经超过 10 秒 return; } } NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic setValue:position forKey:@"micPosition"]; [dic setValue:targetUid forKey:@"uid"]; AttachmentModel *attachement = [[AttachmentModel alloc]init]; attachement.first = CustomMessageType_Queue; attachement.second = Custom_Message_Sub_Queue_Invite; attachement.data = dic; NIMMessage *message = [[NIMMessage alloc]init]; NIMCustomObject *object = [[NIMCustomObject alloc] init]; object.attachment = attachement; message.messageObject = object; //构造会话 NIMSession *session = [NIMSession session: @(self.roomInfo.roomId).stringValue type:NIMSessionTypeChatroom]; [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil]; } - (void)sendResponseUpMicMessage:(NSDictionary *)originalData isAgree:(BOOL)isAgree { AttachmentModel *attachment = [[AttachmentModel alloc] init]; attachment.first = ClientMessage_Type; attachment.second = isAgree ? ClientMessage_UpMic_Agree : ClientMessage_UpMic_Reject; attachment.data = originalData; NSString *sessionID = @(self.roomInfo.roomId).stringValue; NIMMessage *message = [[NIMMessage alloc]init]; NIMCustomObject *object = [[NIMCustomObject alloc] init]; object.attachment = attachment; message.messageObject = object; NIMSessionType sessionType = NIMSessionTypeChatroom; //构造会话 NIMSession *session = [NIMSession session:sessionID type:sessionType]; [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session completion:^(NSError * _Nullable error) { BOOL onMain = [NSThread isMainThread]; if (error) { NSLog(@"[[Send] ❌ 发送失败 | sessionId=%@ | code=%ld | desc=%@ | main=%@ | ts=%.3f", sessionID, (long)error.code, error.localizedDescription, onMain ? @"YES" : @"NO", [[NSDate date] timeIntervalSince1970]); } else { NSLog(@"[Send] ✅ 发送成功 | sessionId=%@ | main=%@ | ts=%.3f", sessionID, onMain ? @"YES" : @"NO", [[NSDate date] timeIntervalSince1970]); } }]; } #pragma mark - NIMBroadcastDelegate // 广播消息 - (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage{ if (broadcastMessage.content) { NSDictionary *msgDictionary = [broadcastMessage.content toJSONObject]; AttachmentModel *attachment = [AttachmentModel modelWithJSON:msgDictionary[@"body"]]; NSString *partitionId = [NSString stringWithFormat:@"%@",attachment.data[@"partitionId"]]; if(![partitionId isEqualToString:self.getUserInfo.partitionId]){ return; } BOOL isHave = NO; if(attachment.first == CustomMessageType_Look_Love && attachment.second == Custom_Message_Sub_Look_Love_InRoom_NeedAllMicSend){ isHave = YES; }else if(attachment.first == CustomMessageType_Super_Gift && (attachment.second == Custom_Message_Sub_Super_Gift || attachment.second == Custom_Message_Sub_Super_Gift_Room_Message)){ isHave = YES; }else if(attachment.first == CustomMessageType_General_Public_Screen && attachment.second == Custom_Message_Sub_General_Public_Screen_All_Room){ isHave = YES; }else if (attachment.first == CustomMessageType_Treasure_Fairy && (attachment.second == Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L4 || attachment.second == Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L5 || attachment.second == Custom_Message_Sub_Treasure_Fairy_Convert_L1 || attachment.second == Custom_Message_Sub_Treasure_Fairy_Convert_L2 || attachment.second == Custom_Message_Sub_Treasure_Fairy_Convert_L3)) { //夺宝精灵 isHave = YES; }else if (attachment.first == CustomMessageType_Tarot && (attachment.second == Custom_Message_Sub_Tarot_Advanced || attachment.second == Custom_Message_Sub_Tarot_Intermediate)){ isHave = YES; }else if(attachment.first == CustomMessageType_LuckyBag && attachment.second == Custom_Message_Sub_Room_Gift_LuckBag_FullScree){ isHave = YES; } if (attachment.first == CustomMessageType_RedPacket && attachment.second == Custom_Message_Sub_AllDiamandRedPacket) { if(self.isShowRedPacket == YES)return; XPRedPacketModel *data = [XPRedPacketModel modelWithDictionary:attachment.data]; data.validityType = 0; data.kind = 1; data.redEnvelopeId = attachment.data[@"redEnvelopeId"]; RoomInfoModel *roomInfo = self.roomInfo; XPReceiveRedPacketView *view = [[XPReceiveRedPacketView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; view.delegate = self; self.isShowRedPacket = YES; if (roomInfo.uid == data.roomUid.integerValue) { view.inAllPacketRoom = YES; } else { view.inAllPacketRoom = NO; } view.receiveModel = data; [self.view addSubview:view]; [self.view bringSubviewToFront:view]; } if(isHave == NO)return; attachment.isBroadcast = YES; NIMMessage *message = [NIMMessage new]; NIMCustomObject *object = [NIMCustomObject new]; object.attachment = attachment; message.messageObject = object; [self.messageContainerView handleNIMTextMessage:message]; } } //发送消息成功回调 - (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error { if (message.yidunAntiSpamRes) { NSDictionary * spamRes = message.yidunAntiSpamRes.toJSONObject; id spamResExt = ((NSString *)spamRes[@"ext"]).toJSONObject; NSDictionary *antispamDic = nil; if ([spamResExt isKindOfClass:[NSArray class]]) { antispamDic = [spamResExt xpSafeObjectAtIndex:0]; } else if ([spamResExt isKindOfClass:[NSDictionary class]]) { antispamDic = spamResExt[@"antispam"]; } NSDictionary *realAntiDic = nil; if ([[antispamDic allKeys] containsObject:@"antispam"]) { realAntiDic = antispamDic[@"antispam"];; } else { realAntiDic = antispamDic; } if (realAntiDic) { NSInteger suggestion = [realAntiDic[@"suggestion"] integerValue]; if (suggestion == 2) { [self showErrorToast:YMLocalizedString(@"XPRoomViewController10")]; } } } if (![message.session.sessionId isEqualToString:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]) { return; } if (error) { NSLog(@"%@", error); return; }; if (message.messageType == NIMMessageTypeCustom) { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) { AttachmentModel * attachment = (AttachmentModel *)obj.attachment; [self.stageView handleNIMCustomMessage:message]; [self.animationView handleNIMCustomMessage:message]; [self.functionView handleNIMCustomMessage:message]; if (attachment.first == CustomMessageType_Update_RoomInfo && attachment.second == Custom_Message_Sub_Update_RoomInfo_MessageState) { NSDictionary * dic= attachment.data[@"roomInfo"]; if (dic.allKeys.count <=0) { dic = attachment.data; } RoomInfoModel * roomInfo = [RoomInfoModel modelWithDictionary:dic]; self.roomInfo.isCloseScreen = roomInfo.isCloseScreen; [self.menuContainerView onRoomUpdate]; }else if(attachment.first == CustomMessageType_Update_RoomInfo && attachment.second == Custom_Message_Sub_Update_RoomInfo_AnimateEffect){ NSDictionary * dic= attachment.data[@"roomInfo"]; if (dic.allKeys.count <= 0) { dic = attachment.data; } RoomInfoModel * roomInfo = [RoomInfoModel modelWithDictionary:dic]; self.roomInfo.hasAnimationEffect = roomInfo.hasAnimationEffect; } [self.roomHeaderView onRoomUpdate]; [self.messageContainerView handleNIMCustomMessage:message]; } }else if(message.messageType == NIMMessageTypeText) { [self.messageContainerView handleNIMTextMessage:message];; } } #pragma mark - NIMLoginManagerDelegate - (void)onKickout:(NIMLoginKickoutResult *)result { // [self exitRoom]; [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - NIMConversationManagerDelegate - (void)didAddRecentSession:(NIMRecentSession *)recentSession totalUnreadCount:(NSInteger)totalUnreadCount { [self.menuContainerView addNIMRecentSession:recentSession]; } - (void)didUpdateRecentSession:(NIMRecentSession *)recentSession totalUnreadCount:(NSInteger)totalUnreadCount { [self.menuContainerView addNIMRecentSession:recentSession]; } - (void)didRemoveRecentSession:(NIMRecentSession *)recentSession totalUnreadCount:(NSInteger)totalUnreadCount { [self.menuContainerView removeNIMRecentSession:recentSession]; } #pragma mark - RoomDelegate - (RoomInfoModel *)getRoomInfo { return self.roomInfo; } - (UserInfoModel *)getUserInfo { return self.userInfo; } - (BOOL)isManagerOrOwner { return self.roomUid.integerValue == self.userInfo.uid || [self.superMangerList filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"uid == %d", self.userInfo.uid]] > 0; } -(NSMutableArray *)getPlayList{ return self.sideMenu.playList; } -(NSMutableArray *)getLittleGameList { return self.sideMenu.littleGameList; } - (void)exitRoom { [XNDJTDDLoadingTool showLoading]; [XPSkillCardPlayerManager shareInstance].micState = MICState_None; [self.stageView exitNIMRoom]; [self.menuContainerView menuResignFirstResponder]; [self.animationView resumeTimer]; switch (self.roomInfo.roomModeType) { case RoomModeType_Open_Micro_Mode: case RoomModeType_Open_Blind: [self exitRoomAndCancelArrangeMic]; break; case RoomModeType_Open_PK_Mode: [self exitRoomWhenPKing]; break; case RoomType_MiniGame: [self exitRoomWhenPlayMiniGame]; break; default: [self exitRoomPage]; break; } } - (BOOL)isSameRoom:(NSString *)targetUid { return [self.roomUid isEqualToString:targetUid]; } - (void)exitRoomAndCancelArrangeMic { NSString * roomUid = [NSString stringWithFormat:@"%ld", self.roomInfo.uid]; NSString * uid = [AccountInfoStorage instance].getUid; [Api getRoomArrangeMicList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if (code == 200) { ArrangeMicModel * arrangeMicModel= [ArrangeMicModel modelWithJSON:data.data]; if (arrangeMicModel.myPos.intValue > 0) { [TTPopup alertWithMessage:YMLocalizedString(@"XPRoomViewController11") confirmHandler:^{ __block NSString * grouptype = @"0"; if (self.roomInfo.roomModeType == RoomModeType_Open_Blind) { [arrangeMicModel.queue enumerateObjectsUsingBlock:^(ArrangeMicUserModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj.uid.integerValue == [AccountInfoStorage instance].getUid.integerValue) { grouptype = [NSString stringWithFormat:@"%ld", obj.groupType]; *stop = YES; } }]; } [Api cancelArrangeMic:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { } roomUid:roomUid operUid:uid groupType:grouptype]; [self exitRoomPage]; } cancelHandler:^{ }]; return; } } [self exitRoomPage]; } roomUid:roomUid operUid:uid page:@"1" pageSize:@"50"]; } - (void)exitRoomWhenPKing { NSString * roomUid = [NSString stringWithFormat:@"%ld", self.roomInfo.uid]; NSString * uid = [AccountInfoStorage instance].getUid; [Api getRoomPKUserList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if (code == 200) { ArrangeMicModel * arrangeMicModel= [ArrangeMicModel modelWithJSON:data.data]; if (arrangeMicModel.myPos.intValue > 0) { [TTPopup alertWithMessage:YMLocalizedString(@"XPRoomViewController11") confirmHandler:^{ __block NSString * grouptype = @"0"; [arrangeMicModel.queue enumerateObjectsUsingBlock:^(ArrangeMicUserModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj.uid.integerValue == [AccountInfoStorage instance].getUid.integerValue) { grouptype = [NSString stringWithFormat:@"%ld", obj.groupType]; *stop = YES; } }]; [Api cancelRoomPKArrangeMic:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { } roomUid:roomUid operUid:uid groupType:grouptype]; [self exitRoomPage]; } cancelHandler:^{ }]; return; } } [self exitRoomPage]; } roomUid:roomUid operUid:uid page:@"1" pageSize:@"50"]; } - (void)exitRoomWhenPlayMiniGame { if ([self.littleGameView isInSudGame]) { TTAlertConfig *config = [[TTAlertConfig alloc] init]; config.cancelButtonConfig.title = YMLocalizedString(@"XPRoomSettingInputView4"); config.confirmButtonConfig.title = YMLocalizedString(@"TTAlertConfig0"); config.message = YMLocalizedString(@"XPRoomViewController14"); @kWeakify(self); [TTPopup alertWithConfig:config confirmHandler:^{ // 知道了 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @kStrongify(self); [self exitRoomPage]; }); } cancelHandler:^{ }]; } else { [self exitRoomPage]; } } - (void)exitRoomPage { if (self.roomInfo.type == RoomType_MiniGame) { [self.littleGameView handleSelfInExitEvent]; [self.littleGameView destroyMG]; } [[XPRoomMiniManager shareManager] resetLocalMessage]; [[RtcManager instance] exitRoom]; [self.presenter exitNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]; [self.presenter reportUserOutRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; [self handleFirstOutRoom]; [self dismissViewControllerAnimated:YES completion:^{ [XNDJTDDLoadingTool hideHUD]; }]; } - (void)miniRoom { if(self.freeModel != nil){ [XPRoomMiniManager shareManager].curState = self.freeModel.curStage; } [self.menuContainerView menuResignFirstResponder]; NSDictionary *roomInfoDic = self.roomInfo.model2dictionary != nil ? self.roomInfo.model2dictionary : @{}; NSDictionary *userInfoDic = self.userInfo.model2dictionary != nil ? self.userInfo.model2dictionary : @{}; NSMutableDictionary *queueDic = self.getMicroQueue != nil ? self.getMicroQueue : [@{} mutableCopy]; if(self.roomInfo.type == RoomType_MiniGame) { if ([self.littleGameView isInSudGame]) { TTAlertConfig *config = [[TTAlertConfig alloc] init]; config.cancelButtonConfig.title = YMLocalizedString(@"XPRoomViewController15"); config.confirmButtonConfig.title = YMLocalizedString(@"XPRoomViewController16"); config.message = YMLocalizedString(@"XPRoomViewController17"); @kWeakify(self); [TTPopup alertWithConfig:config confirmHandler:^{ // 知道了 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @kStrongify(self); [[XPRoomMiniManager shareManager] configRoomInfo:self.roomInfo]; [[XPRoomMiniManager shareManager] configUserInfo:self.userInfo]; [[XPRoomMiniManager shareManager] configCurrentMusic:self.functionView.getCurrentMusic isPlaying:self.functionView.isPlaying]; NSDictionary * dic = @{@"roomInfo":roomInfoDic, @"userInfo":userInfoDic, @"microQueue":queueDic}; [[NSNotificationCenter defaultCenter] postNotificationName:kRoomMiniNotificationKey object:nil userInfo:dic]; [self.view endEditing:YES]; [self.littleGameView handleSelfInExitEvent]; [self.littleGameView destroyMG]; [self handleFirstOutRoom]; [self dismissViewControllerAnimated:YES completion:nil]; }); } cancelHandler:^{ }]; } else { [[XPRoomMiniManager shareManager] configRoomInfo:self.roomInfo]; [[XPRoomMiniManager shareManager] configUserInfo:self.userInfo]; [[XPRoomMiniManager shareManager] configCurrentMusic:self.functionView.getCurrentMusic isPlaying:self.functionView.isPlaying]; NSDictionary * dic = @{@"roomInfo":roomInfoDic, @"userInfo":userInfoDic, @"microQueue":queueDic}; [[NSNotificationCenter defaultCenter] postNotificationName:kRoomMiniNotificationKey object:nil userInfo:dic]; [self.view endEditing:YES]; [self.littleGameView handleSelfInExitEvent]; [self.littleGameView destroyMG]; [self handleFirstOutRoom]; [self dismissViewControllerAnimated:YES completion:nil]; } }else { [[XPRoomMiniManager shareManager] configRoomInfo:self.roomInfo]; [[XPRoomMiniManager shareManager] configUserInfo:self.userInfo]; [[XPRoomMiniManager shareManager] configCurrentMusic:self.functionView.getCurrentMusic isPlaying:self.functionView.isPlaying]; NSDictionary * dic = @{@"roomInfo":roomInfoDic, @"userInfo":userInfoDic, @"microQueue":queueDic}; [[NSNotificationCenter defaultCenter] postNotificationName:kRoomMiniNotificationKey object:nil userInfo:dic]; [self.view endEditing:YES]; [self handleFirstOutRoom]; [self dismissViewControllerAnimated:YES completion:nil]; } } - (void)showPKPanel { [self.functionView showPKPanelView]; } - (UINavigationController *)getCurrentNav { return self.navigationController; } -(UIView *)getSuperView{ return self.view; } - (NSMutableDictionary *)getMicroQueue { return [self.stageView getMicroQueue]; } - (NSArray *)getRoomSuperAdminList { return self.superMangerList; } - (NSArray *)getRoomPKGroupTeamList { return [self.functionView getRoomPKGroupTeamList]; } - (BOOL)isRoomPKPlaying { return [self.functionView isRoomPKPlaying]; } - (void)onMicroQueueUpdate:(NSMutableDictionary *)queue { [self.menuContainerView onMicroQueueUpdate:queue]; [self.functionView onRoomUpdate]; [self.functionView onMicroQueueUpdate:queue]; BOOL isOnMic = false; for (MicroQueueModel * info in queue.allValues) { if (info.userInfo.uid > 0 && [AccountInfoStorage instance].getUid.integerValue == info.userInfo.uid) { isOnMic = YES; break; } } if (isOnMic) { self.anchorScrollView.scrollEnabled = NO; } else { self.anchorScrollView.scrollEnabled = YES; } } - (CGPoint)animationPointAtStageViewByUid:(NSString *)uid { return [self.stageView animationPointAtStageViewByUid:uid]; } - (CGPoint)animationPointAtStageViewByIndex:(NSInteger)index { return [self.stageView animationPointAtStageViewByIndex:index]; } - (void)getRoomBoomInfoSuccess:(NSArray *)models { [[RoomBoomManager sharedManager] updateBoomDetailArray:models]; [self.sideMenu updateForBoomDetailArray:models]; } - (void)getRoomBoomExplosionSuccess:(BoomInfoModel *)model { [[RoomBoomManager sharedManager] receiveEnterRoomBoom:model]; } #pragma mark - 首次退出非自己的房间,处理是否需要弹新用户充值优惠 - (void)handleFirstOutRoom { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; if (![defaults boolForKey:kHadQuitOtherRoomKey] && self.userInfo.uid != self.roomInfo.uid && self.userInfo.showLimitCharge) { [defaults setBool:YES forKey:kHadQuitOtherRoomKey]; [defaults synchronize]; [[NSNotificationCenter defaultCenter] postNotificationName:kNewUserRechargeKey object:nil]; } } #pragma mark - XPRoomLittleGameContainerViewDelegate - (void)hiddenSudGamePostionView { [self.functionView hiddenSudGamePostionView]; } #pragma mark - AnchorRoomScrollViewDelegate - (void)anchorScrollViewScrollToNext:(AnchorRoomScrollView *)anchorScrollView { if (!self) { return; } [self.view endEditing:YES]; [self showAnchorLoading]; [self.presenter getCycleAnchorRoomList:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]; } - (void)anchorScrollViewScrollToPrevious:(AnchorRoomScrollView *)anchorScrollView { if (!self || self.anchorRoomList.count <= 0) { return; } [self.view endEditing:YES]; [self showAnchorLoading]; if (self.anchorIndex < self.anchorRoomList.count) { NSString * roomUid = [self.anchorRoomList xpSafeObjectAtIndex:self.anchorIndex]; [self.presenter getCurrentRoomInfo:roomUid]; self.anchorIndex --; }else { [self showErrorToast:YMLocalizedString(@"XPRoomViewController13")]; self.anchorScrollView.contentOffset = CGPointMake(0, KScreenHeight); } } #pragma mark - XPRoomSettingInputViewDelegate ///点击了完成 - (void)xPRoomSettingInputView:(XPRoomSettingInputView *)view didClickConfirm:(NSString *)text type:(RoomSettingInputType)type { NSString *pwdDes = [DESEncrypt encryptUseDES:text key:KeyWithType(KeyType_PasswordEncode)]; if ([pwdDes isEqualToString:self.roomInfo.roomPwd]) { [TTPopup dismiss]; view.isPwdError = NO; if (self.roomInfo.type == RoomType_Anchor) { [self __removeAllViews]; if (!self.anchorScrollView.superview) { [self.view insertSubview:self.anchorScrollView belowSubview:self.menuContainerView]; } [self.anchorScrollView addSubview:self.backContainerView]; [self.anchorScrollView addSubview:self.stageView]; [self.anchorScrollView addSubview:self.messageContainerView]; [self.anchorScrollView addSubview:self.quickMessageContainerView]; [self.anchorScrollView addSubview:self.sideMenu]; [self.anchorScrollView addSubview:self.roomHeaderView]; if (!self.menuContainerView.superview) { [self.view addSubview:self.menuContainerView]; } [self.anchorScrollView addSubview:self.functionView]; [self.view bringSubviewToFront:self.animationView]; [self updateViewConstraintsOnAnchorRoom]; [self changeStageViewOnAnchorRoom]; [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; [self.littleGameView onRoomEntered]; if ([XPRoomMiniManager shareManager].getRoomInfo.uid != self.roomUid.integerValue) {// 最小化进房 还是原来的房间的话 不需要重新进入云信 因为压根没退 [self.presenter enterNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId] user:self.userInfo]; [self.functionView onRoomEntered]; [self.messageContainerView onRoomEntered]; [self.menuContainerView onRoomEntered]; } else { //虽然没退出房间 但是队列还是要拿的 [self.stageView onRoomMiniEntered]; [self.messageContainerView onRoomMiniEntered]; [self.functionView onRoomMiniEntered]; [self.functionView onRoomEntered]; [self.menuContainerView onRoomMiniEntered]; } [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; } else { [self.roomHeaderView onRoomEntered]; [self.sideMenu onRoomEntered]; [self.menuContainerView onRoomEntered]; [self changeStageViewOnRoomUpdate]; [self.backContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; [self.functionView onRoomEntered]; [self.presenter enterNIMRoom:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId] user:self.userInfo]; [self.messageContainerView onRoomEntered]; [self.littleGameView onRoomEntered]; [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; } } else { view.isPwdError = YES; } } - (void)didClickCancel:(RoomSettingInputType)type { if (type == RoomSettingInputType_Input_Pwd) { [self enterRoomFail:0]; } } -(NSInteger)getPublicScreenType{ return self.messageContainerView.type; } - (void)displayMusicPanel { [self.functionView showMusicPanel]; } - (void)updateScreenMessageState:(BOOL)isClose { self.roomInfo.isCloseScreen = isClose; } #pragma mark - XPFirstRechargeViewDelegate -(void)rechargeHandle{} -(void)contactCustomerService{ TTAlertConfig *config = [[TTAlertConfig alloc]init]; config.title = YMLocalizedString(@"XPIAPRechargeViewController7"); config.message = YMLocalizedString(@"XPIAPRechargeViewController8"); TTAlertButtonConfig *confirmButtonConfig = [[TTAlertButtonConfig alloc]init]; confirmButtonConfig.title = YMLocalizedString(@"XPIAPRechargeViewController9"); UIImage *image = [UIImage gradientColorImageFromColors:@[UIColorFromRGB(0x13E2F5),UIColorFromRGB(0x9DB4FF),UIColorFromRGB(0xCC67FF)] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(200, 200)]; confirmButtonConfig.backgroundColor = [UIColor colorWithPatternImage:image]; confirmButtonConfig.cornerRadius = 38/2; config.confirmButtonConfig = confirmButtonConfig; @kWeakify(self); [TTPopup alertWithConfig:config confirmHandler:^{ @kStrongify(self); [self requestContactCustomerService]; } cancelHandler:^{ }]; } -(void)requestContactCustomerService{ [XNDJTDDLoadingTool showLoading]; [Api requestContactCustomerServiceCompletion:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { [XNDJTDDLoadingTool hideHUD]; if(code == 200){ NSString *uid = [NSString stringWithFormat:@"%@",data.data]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NIMSession * session = [NIMSession session:uid type:NIMSessionTypeP2P]; SessionViewController * sessionVC = [[SessionViewController alloc] initWithSession:session]; [self.getCurrentNav pushViewController:sessionVC animated:YES]; }); } }]; } - (XPRoomBackContainerView *)backContainerView { if (!_backContainerView) { _backContainerView = [[XPRoomBackContainerView alloc] initWithdelegate:self]; } return _backContainerView; } - (RoomHeaderView *)roomHeaderView { if (!_roomHeaderView) { _roomHeaderView = [[RoomHeaderView alloc] initWithDelegate:self]; } return _roomHeaderView; } - (MsRoomMessageMainView *)messageContainerView { if (!_messageContainerView) { _messageContainerView = [[MsRoomMessageMainView alloc] initWithDelegate:self]; } return _messageContainerView; } - (XPRoomQuickMessageContainView *)quickMessageContainerView { if(!_quickMessageContainerView) { _quickMessageContainerView = [[XPRoomQuickMessageContainView alloc] initWithDelegate:self]; } return _quickMessageContainerView; } - (XPRoomMenuContainerView *)menuContainerView { if (!_menuContainerView) { _menuContainerView = [[XPRoomMenuContainerView alloc] initWithDelegate:self]; @kWeakify(self); [_menuContainerView setUpdateHeight:^(CGFloat height) { @kStrongify(self); [self.menuContainerView mas_remakeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self.view); if (iPhoneXSeries) { make.bottom.mas_equalTo(self.view); } else { make.bottom.mas_equalTo(self.view).offset(-10); } make.height.mas_equalTo(height + kSafeAreaBottomHeight); }]; }]; } return _menuContainerView; } - (RoomSideMenu *)sideMenu { if (!_sideMenu) { _sideMenu = [[RoomSideMenu alloc] initWithDelegate:self]; } return _sideMenu; } - (RoomAnimationView *)animationView { if (!_animationView) { _animationView = [[RoomAnimationView alloc] initWithHostDelegate:self]; } return _animationView; } - (XPRoomFunctionContainerView *)functionView { if (!_functionView) { _functionView = [[XPRoomFunctionContainerView alloc] initWithDelegate:self]; } return _functionView; } - (StageView *)stageView { if (!_stageView) { _stageView = [[SocialStageView alloc] initWithDelegate:self]; _stageView.alpha = 0; } return _stageView; } - (TenMicStageView *)tenMicStageView { if (!_tenMicStageView) { _tenMicStageView = [[TenMicStageView alloc] initWithDelegate:self]; } return _tenMicStageView; } - (NineteenMicStageView *)nineteenMicStageView { if (!_nineteenMicStageView) { _nineteenMicStageView = [[NineteenMicStageView alloc] initWithDelegate:self]; } return _nineteenMicStageView; } - (TwentyMicStageView *)twentyMicStageView { if (!_twentyMicStageView) { _twentyMicStageView = [[TwentyMicStageView alloc] initWithDelegate:self]; } return _twentyMicStageView; } - (FifteenMicStageView *)fifteenMicStageView { if (!_fifteenMicStageView) { _fifteenMicStageView = [[FifteenMicStageView alloc] initWithDelegate:self]; } return _fifteenMicStageView; } - (XPRoomLittleGameContainerView *)littleGameView { if (!_littleGameView) { _littleGameView = [[XPRoomLittleGameContainerView alloc] initWithDelegate:self]; _littleGameView.delegate = self; } return _littleGameView; } - (AnchorRoomScrollView *)anchorScrollView { if (!_anchorScrollView) { _anchorScrollView = [[AnchorRoomScrollView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; _anchorScrollView.anchorScrollDelegate = self; _anchorScrollView.hostDelegate = self; if (@available(iOS 11.0, *)) { _anchorScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } } return _anchorScrollView; } - (AnchorRoomSrollTipView *)anchorScrollTipView { if (!_anchorScrollTipView) { _anchorScrollTipView = [[AnchorRoomSrollTipView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; } return _anchorScrollTipView; } - (NSMutableArray *)anchorRoomList { if (!_anchorRoomList) { _anchorRoomList = [NSMutableArray array]; } return _anchorRoomList; } -(XPFreeGiftsObtainView *)freeView{ if (!_freeView){ _freeView = [[XPFreeGiftsObtainView alloc]initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; } return _freeView; } - (PIRoomEnterRedPacketView *)redPacketView{ if(!_redPacketView){ _redPacketView = [[PIRoomEnterRedPacketView alloc]initWithFrame:CGRectZero]; _redPacketView.hidden = YES; _redPacketView.isInRoom = YES; _redPacketView.delegate = self; } return _redPacketView; } #pragma mark - 公共房间消息转发处理 - (void)handlePublicRoomMessageForward:(NSNotification *)notification { NIMMessage *message = notification.object; if (![message isKindOfClass:[NIMMessage class]]) { NSLog(@"XPRoomViewController: 收到无效的公共房间转发消息"); return; } // 检查房间是否处于活跃状态 if (!self.roomInfo || !self.messageContainerView) { NSLog(@"XPRoomViewController: 房间未就绪,忽略公共房间转发消息"); return; } // 使用现有的消息处理流程 // [self.messageContainerView handleNIMCustomMessage:message]; // [self.animationView handleNIMCustomMessage:message]; // [self handleNimCustomTypeMessage:message]; // [self onRecvMessages:@[message]]; switch (message.messageType) { case NIMMessageTypeNotification: [self handleNIMNotificationTypeMessage:message]; break; case NIMMessageTypeCustom: [self handleNimCustomTypeMessage:message]; break; case NIMMessageTypeText: [self.messageContainerView handleNIMTextMessage:message]; [self.littleGameView handleNIMTextMessage:message]; break; case NIMMessageTypeTip: [self.messageContainerView handleNIMTextMessage:message]; break; case NIMMessageTypeImage: [self.messageContainerView handleNIMImageMessage:message]; break; default: break; } } // 新增:StageViewManager 懒加载 - (StageViewManager *)stageViewManager { if (!_stageViewManager) { _stageViewManager = [[StageViewManager alloc] init]; NSLog(@"✅ StageViewManager 懒加载初始化成功"); } return _stageViewManager; } // 新增:设置 StageViewManager - (void)setupStageViewManager { // 触发懒加载 [self stageViewManager]; NSLog(@"✅ StageViewManager 设置完成"); } // 调试方法:检查 stageView 状态 - (void)debugStageViewStatus { NSLog(@"🔍 DEBUG: stageView 状态检查"); NSLog(@" - stageView: %@", self.stageView); NSLog(@" - stageView.alpha: %.2f", self.stageView.alpha); NSLog(@" - stageView.hidden: %@", self.stageView.hidden ? @"YES" : @"NO"); NSLog(@" - stageView.superview: %@", self.stageView.superview); NSLog(@" - stageView.frame: %@", NSStringFromCGRect(self.stageView.frame)); NSLog(@" - stageView.class: %@", NSStringFromClass([self.stageView class])); } @end