// // XPMiniRoomView.m // xplan-ios // // Created by 冯硕 on 2021/12/3. // #import "XPMiniRoomView.h" ///Third #import #import ///Tool #import "XPMacro.h" #import "ThemeColor.h" #import "NetImageView.h" #import "RtcManager.h" #import "UIButton+EnlargeTouchArea.h" #import "TTPopup.h" #import "XCHudTool.h" #import "XPRoomMiniManager.h" #import "AccountInfoStorage.h" #import "Api+ArrangeMic.h" #import "Api+Room.h" #import "XPCoreDataManager.h" #import "NSArray+Safe.h" #import "NSMutableDictionary+Saft.h" ///Model #import "RoomInfoModel.h" #import "MicroQueueModel.h" #import "MicroStateModel.h" #import "UserInfoModel.h" #import "AttachmentModel.h" #import "ArrangeMicModel.h" #import "RoomFaceSendInfoModel.h" #import "MicroInviteExtModel.h" #import "Music+CoreDataClass.h" #import "RoomPKChooseUserModel.h" #import "RoomSailingPrizeModel.h" ///View #import "XPRoomViewController.h" #import "XPNoteView.h" UIKIT_EXTERN NSString * kRoomBackMusicPlayMusicFinishKey; UIKIT_EXTERN NSString * kRoomBackMusicAudioMixingVolumeKey; UIKIT_EXTERN NSString * kRoomBackMusicCaptureVolumeKey; UIKIT_EXTERN NSString * kRoomBackMusicPlayMusicOrderKey; @interface XPMiniRoomView () ///底部的底图 @property (nonatomic,strong) UIImageView *backImageView; ///头像 @property (nonatomic,strong) NetImageView *avatarImageView; ///昵称 @property (nonatomic,strong) UILabel *nickLabel; ///id @property (nonatomic,strong) UILabel *idLabel; ///关闭 @property (nonatomic,strong) UIButton *closeButton; ///音符 @property (nonatomic,strong) XPNoteView *noteView; ///房间最小化 @property (nonatomic,strong) RoomInfoModel *roomInfo; ///房间最小化的时候 传入的用户信息 @property (nonatomic,strong) UserInfoModel *userInfo; ///当前最小化的房间的uid 如果没有的话 为nil @property (nonatomic,strong) NSString *currentRoomUid; ///房间的id @property (nonatomic,strong) NSString *currentRoomId; ///麦序 @property (nonatomic, strong) NSMutableDictionary *micQueue; ///正在播放的音乐 @property (nonatomic,strong) Music *currentMusic; ///当前的下表 @property (nonatomic,assign) NSInteger currentIndex; ///数据库请求 @property (nonatomic,strong) NSFetchRequest *request; @end @implementation XPMiniRoomView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [[NIMSDK sharedSDK].chatroomManager addDelegate:self]; [[NIMSDK sharedSDK].chatManager addDelegate:self]; [[NIMSDK sharedSDK].loginManager addDelegate:self]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(roomBackMusicPlayFinish:) name:kRoomBackMusicPlayMusicFinishKey object:nil]; [self initEvents]; [self initSubViews]; [self initSubViewConstraints]; } return self; } #pragma mark - Public Method - (void)configRoomMiniView:(RoomInfoModel *)roomInfo userInfo:(UserInfoModel *)userInfo micQueue:(NSMutableDictionary *)micQueue { self.hidden = NO; self.currentRoomUid = [NSString stringWithFormat:@"%ld", roomInfo.uid]; self.currentRoomId = [NSString stringWithFormat:@"%ld", roomInfo.roomId]; self.roomInfo = roomInfo; self.userInfo = userInfo; self.micQueue = micQueue; [self startAvatarAnimation]; [self.noteView startAnimation]; } - (void)hiddenRoomMiniView { [self.avatarImageView.layer removeAllAnimations]; [self.noteView stopAnimation]; self.currentRoomUid = nil; self.currentRoomId = nil; self.roomInfo = nil; self.userInfo = nil; self.micQueue = nil; self.hidden = YES; } #pragma mark - Private Method - (void)initSubViews { self.frame = CGRectMake(KScreenWidth - 140 * 1.2, KScreenHeight - kSafeAreaBottomHeight - 150, 140 * 1.2, 34 * 1.2); [self addSubview:self.backImageView]; [self.backImageView addSubview:self.avatarImageView]; [self.backImageView addSubview:self.noteView]; [self.backImageView addSubview:self.nickLabel]; [self.backImageView addSubview:self.idLabel]; [self.backImageView addSubview:self.closeButton]; } - (void)initSubViewConstraints { [self.backImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self); }]; [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(self.backImageView).offset(5); make.top.bottom.mas_equalTo(self.backImageView).inset(5); make.height.mas_equalTo(self.avatarImageView.mas_width); }]; [self.nickLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(self.avatarImageView.mas_right).offset(5); make.bottom.mas_equalTo(self.avatarImageView.mas_centerY).offset(-1.5); }]; [self.idLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(self.nickLabel); make.top.mas_equalTo(self.avatarImageView.mas_centerY).offset(1.5); }]; [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(15, 15)); make.centerY.mas_equalTo(self.backImageView); make.right.mas_equalTo(self.backImageView).offset(-11); }]; [self.noteView mas_makeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(self.avatarImageView); make.height.mas_equalTo(12); make.width.mas_equalTo(12); }]; } - (void)initEvents { UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(roomMiniTag:)]; pan.delaysTouchesBegan = YES; [self addGestureRecognizer:pan]; UITapGestureRecognizer *enterRoomTag = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(enterRomRecognizer:)]; [self addGestureRecognizer:enterRoomTag]; } - (void)startAvatarAnimation { CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ]; rotationAnimation.duration = 3; rotationAnimation.cumulative = YES; rotationAnimation.repeatCount = MAXFLOAT; rotationAnimation.removedOnCompletion = NO; [self.avatarImageView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"]; } - (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"]; } } ///自定义消息 是否可以加到 公屏 需要自己维护 - (BOOL)isCanDisplayMessage:(NIMMessage *)message { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) { AttachmentModel *attachment = (AttachmentModel *)obj.attachment; if (attachment.first == CustomMessageType_Face && attachment.second == Custom_Message_Sub_Face_Send) { if ([attachment.data[@"data"] isKindOfClass:[NSArray class]]) { NSArray * array = [RoomFaceSendInfoModel modelsWithArray:attachment.data[@"data"]]; for (int i = 0; i< array.count; i++) { RoomFaceSendInfoModel * sendInfo = [array safeObjectAtIndex1:i]; if (sendInfo.resultIndexes.count <=0) { return NO; } } } }else if (attachment.first == CustomMessageType_Room_PK && attachment.second == Custom_Message_Sub_Room_PK_Manager_Up_Mic) { if (attachment.data && [attachment.data allKeys].count > 0) { for (NSDictionary * dic in [attachment.data allValues]) { RoomPKChooseUserModel * userModel = [RoomPKChooseUserModel modelWithDictionary:dic]; if (userModel.groupType == GroupType_Red || userModel.groupType == GroupType_Blue) { return YES; } } } return NO; } else if(attachment.first == CustomMessageType_Room_Sailing && (attachment.second == Custom_Message_Sub_Sailing_AllRoom_Notify || attachment.second == Custom_Message_Sub_Sailing_InRoom_NeedAllMicSend)) { RoomSailingPrizeModel * prizeModel = [RoomSailingPrizeModel modelWithDictionary:attachment.data]; if (self.userInfo.userLevelVo.experLevelSeq > prizeModel.userLevelLimit) { return YES; } } return [[[self supportMessageDic] objectForKey:@(attachment.first)] containsObject:@(attachment.second)]; } return NO; } - (NSDictionary *)supportMessageDic { return @{ @(CustomMessageType_AllMicroSend): [NSSet setWithObjects: @(Custom_Message_Sub_AllMicroSend), @(Custom_Message_Sub_AllMicroLuckySend), @(Custom_Message_Sub_AllBatchSend), @(Custom_Message_Sub_AllBatchMicroLuckySend), nil], @(CustomMessageType_Gift): [NSSet setWithObjects: @(Custom_Message_Sub_Gift_Send), @(Custom_Message_Sub_Gift_LuckySend), nil], @(CustomMessageType_Room_Tip): [NSSet setWithObjects: @(Custom_Message_Sub_Room_Tip_ShareRoom), @(Custom_Message_Sub_Room_Tip_Attention_Owner), nil], @(CustomMessageType_Kick_User): [NSSet setWithObjects: @(Custom_Message_Sub_Kick_BeKicked), @(Custom_Message_Sub_Kick_BlackList), nil], @(CustomMessageType_Queue): [NSSet setWithObjects: @(Custom_Message_Sub_Queue_Kick), nil], @(CustomMessageType_Candy_Tree): [NSSet setWithObjects: @(Custom_Message_Sub_Candy_Tree_Me), @(Custom_Message_Sub_Candy_Tree_InRoom), @(Custom_Message_Sub_Candy_Tree_AllRoom), @(Custom_Message_Sub_Candy_Tree_AllRoom_Notify), @(Custom_Message_Sub_Candy_Tree_InRoom_NeedAllMicSend), nil], @(CustomMessageType_Arrange_Mic): [NSSet setWithObjects: @(Custom_Message_Sub_Arrange_Mic_Mode_Open), @(Custom_Message_Sub_Arrange_Mic_Mode_Close), @(Custom_Message_Sub_Arrange_Mic_Free_Mic_Open), @(Custom_Message_Sub_Arrange_Mic_Free_Mic_Close), nil], @(CustomMessageType_Update_RoomInfo): [NSSet setWithObjects: @(Custom_Message_Sub_Update_RoomInfo_MessageState), @(Custom_Message_Sub_Update_RoomInfo_AnimateEffect), nil], @(CustomMessageType_Collection_Room): [NSSet setWithObjects: @(Custom_Message_Sub_Collect_Room_Tips), nil], @(CustomMessageType_RoomPlay_Dating): [NSSet setWithObjects: @(Custom_Message_Sub_Room_Play_Dating_Pick_Heart), @(Custom_Message_Sub_Room_Play_Dating_Result_Mutual), @(Custom_Message_Sub_Room_Play_Dating_Result_Not_Mutual), nil], @(CustomMessageType_Noble_VIP): [NSSet setWithObjects: @(Custom_Message_Sub_Room_Open_Noble_VIP), @(Custom_Message_Sub_Room_Noble_LevelUp), @(Custom_Message_Sub_AllRoom_Noble_LevelUp_Suspend), nil], @(CustomMessageType_Face): [NSSet setWithObjects: @(Custom_Message_Sub_Face_Send), nil], @(CustomMessageType_Anchor_FansTeam): [NSSet setWithObjects: @(Custom_Message_Sub_FansTeam_Open_Success), @(Custom_Message_Sub_FansTeam_Open_Fail), @(Custom_Message_Sub_FansTeam_Join_Success), @(Custom_Message_Sub_FansTeam_Out_Success), nil], @(CustomMessageType_Hall_Super_Admin): [NSSet setWithObjects: @(Custom_Message_Sub_Hall_Super_Admin_Kick_Manager_Out_Room), nil], @(CustomMessageType_Tarot): [NSSet setWithObjects: @(Custom_Message_Sub_Tarot), nil], @(CustomMessageType_Room_PK): [NSSet setWithObjects: @(Custom_Message_Sub_Room_PK_Manager_Up_Mic), @(Custom_Message_Sub_Room_PK_Mode_Close), @(Custom_Message_Sub_Room_PK_Result), @(Custom_Message_Sub_Room_PK_Mode_Open), @(Custom_Message_Sub_Room_PK_Start), @(Custom_Message_Sub_Room_PK_Re_Start), nil], @(CustomMessageType_LuckyBag): [NSSet setWithObjects: @(Custom_Message_Sub_Room_Gift_LuckBag_Server), nil], @(CustomMessageType_Gift_Compound): [NSSet setWithObjects:@(Custom_Message_Sub_Gift_Compound), nil], @(CustomMessageType_Room_Sailing): [NSSet setWithObjects: @(Custom_Message_Sub_Sailing_Me), @(Custom_Message_Sub_Sailing_InRoom), @(Custom_Message_Sub_Sailing_AllRoom), @(Custom_Message_Sub_Sailing_AllRoom_Notify), @(Custom_Message_Sub_Sailing_InRoom_NeedAllMicSend), nil], }; } #pragma mark - NIMChatroomManagerDelegate - (void)chatroomBeKicked:(NIMChatroomBeKickedResult *)result { ///如果不是最小化的是 没必要监听 if ([XPRoomMiniManager shareManager].getRoomInfo == nil) return; if (result.reason == 2) { [XCHUDTool showErrorWithMessage:@"您被管理员踢出直播间"]; } else if (result.reason == 5) { [XCHUDTool showErrorWithMessage:@"您已被管理员拉黑"]; } [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [[RtcManager instance] exitRoom]; [self cancelRoomArrangeMic]; [self hiddenRoomMiniView]; } #pragma mark - NIMLoginManagerDelegate - (void)onKickout:(NIMLoginKickoutResult *)result { ///如果不是最小化的是 没必要监听 if ([XPRoomMiniManager shareManager].getRoomInfo == nil) return; [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [[RtcManager instance] exitRoom]; [self hiddenRoomMiniView]; } #pragma mark - NIMChatManagerDelegate - (void)onRecvMessages:(NSArray *)messages { ///如果不是最小化的是 没必要监听 if ([XPRoomMiniManager shareManager].getRoomInfo == nil) return; for (NIMMessage * message in messages) { // 非房间内消息不处理 if (message.session.sessionType != NIMSessionTypeChatroom) { continue; } // 非本房间不处理 if (![message.session.sessionId isEqualToString:[NSString stringWithFormat:@"%ld", self.roomInfo.roomId]]) { continue; } if (message.messageType == NIMMessageTypeNotification) { NIMNotificationObject *notiMsg = (NIMNotificationObject *)message.messageObject; NIMChatroomNotificationContent *content = (NIMChatroomNotificationContent *)notiMsg.content; [self handleNIMNotificationMessage:content]; [self handleNIMNotificationSaveMessage:message]; } else if (message.messageType == NIMMessageTypeCustom) { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) { [self handleNIMCustomMessage:obj.attachment]; if ([self isCanDisplayMessage:message]) { [[XPRoomMiniManager shareManager] saveRoomMessage:message]; } } }else if(message.messageType == NIMMessageTypeText) { [self handleNIMTextMessage:message]; } else if(message.messageType == NIMMessageTypeTip) { [self handleNIMTextMessage:message]; } } } - (void)handleNIMNotificationMessage:(NIMChatroomNotificationContent *)content { BOOL microQueueChanged = NO; switch (content.eventType) { case NIMChatroomEventTypeInfoUpdated: // 麦序状态更新 { NSDictionary *data = [content.notifyExt toJSONObject]; int type = [data[@"type"] intValue]; NSArray* microStates; switch (type) { case 2: microStates = @[[MicroStateModel modelWithJSON:data[@"micInfo"]]]; break; case 3: microStates = [MicroStateModel modelsWithArray:data[@"micInfo"]]; break; } if (microStates && microStates.count > 0) { for (MicroStateModel *microState in microStates) { MicroQueueModel *micSequence = [self.micQueue objectForKey:[NSString stringWithFormat:@"%d", microState.position]]; micSequence.microState = microState; } microQueueChanged = YES; } NSMutableDictionary *lastRoomInfoDic = [NSMutableDictionary dictionaryWithDictionary:[self.roomInfo model2dictionary]]; [lastRoomInfoDic addEntriesFromDictionary: ((NSString *)data[@"roomInfo"]).toJSONObject]; RoomInfoModel *newRoomInfo = [RoomInfoModel modelWithJSON:lastRoomInfoDic]; //TODO: 从小游戏房间切换到普通房间的话 mgid不会被清除掉 if (newRoomInfo.type != RoomType_MiniGame) { newRoomInfo.mgId = 0; } 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; } self.roomInfo = newRoomInfo; } break; case NIMChatroomEventTypeQueueChange: // 麦序上下麦 { NSDictionary* data = (NSDictionary *)content.ext; NSString* position = [data objectForKey:NIMChatroomEventInfoQueueChangeItemKey]; UserInfoModel* userInfo = [UserInfoModel modelWithJSON:[data objectForKey:NIMChatroomEventInfoQueueChangeItemValueKey]]; NSInteger changeType = [data[NIMChatroomEventInfoQueueChangeTypeKey] integerValue]; // 先清除该用户旧的麦位 for (MicroQueueModel *sequence in self.micQueue.allValues) { if (userInfo.uid == sequence.userInfo.uid) { sequence.userInfo = nil; } } if (changeType == 1) { // 上麦 MicroQueueModel *sequence = [self.micQueue objectForKey:position]; sequence.userInfo = userInfo; } microQueueChanged = YES; } break; case NIMChatroomEventTypeExit: case NIMChatroomEventTypeKicked: { for (NIMChatroomNotificationMember *member in content.targets) { for (MicroQueueModel *sequence in self.micQueue.allValues) { if (member.userId.integerValue == sequence.userInfo.uid) { sequence.userInfo = nil; microQueueChanged = YES; } } } } break; default: break; } if (microQueueChanged) { [self microQueueUpdated]; } } - (void)microQueueUpdated { BOOL selfNeedBroadcast = NO; for (int i = 0; i < self.micQueue.allKeys.count; i++) { MicroQueueModel * model = [self.micQueue objectForKey:[NSString stringWithFormat:@"%d", i]]; if (model.userInfo.uid == [AccountInfoStorage instance].getUid.integerValue) { selfNeedBroadcast = model.microState.micState == MicroMicStateType_Open; } } if (self.roomInfo.type == RoomType_Anchor && [[AccountInfoStorage instance].getUid isEqualToString:[NSString stringWithFormat:@"%ld", self.roomInfo.uid]]) { selfNeedBroadcast = YES;///个播房房主默认角色为主播 } [[RtcManager instance] broadcast:selfNeedBroadcast]; } - (void)handleNIMCustomMessage:(AttachmentModel *)attachment { if(attachment.first == CustomMessageType_Queue && attachment.second == Custom_Message_Sub_Queue_Invite) { NSDictionary *dic = attachment.data; MicroInviteExtModel *inviteModel = [MicroInviteExtModel modelWithDictionary:dic]; if (inviteModel.uid.integerValue == self.userInfo.uid) { NSString *position = inviteModel.micPosition; MicroQueueModel *micro = [self.micQueue objectForKey:position]; if (!micro || micro.userInfo) return; // 当前麦位有人,什么都不做。 RoomInfoModel* roomInfo = self.roomInfo; NSString* roomId = [NSString stringWithFormat:@"%ld", roomInfo.roomId]; UserInfoModel* userInfo = self.userInfo; NIMChatroomQueueUpdateRequest *request = [[NIMChatroomQueueUpdateRequest alloc]init]; request.key = position; request.value = [[self configUpdateChatRoomQueueExt:userInfo] toJSONString]; request.roomId = roomId; request.transient = YES; [[NIMSDK sharedSDK].chatroomManager updateChatroomQueueObject:request completion:^(NSError * _Nullable error) { if (error) return; [self cancelRoomArrangeMic]; [RtcManager instance].localMuted = YES; TTAlertConfig *config = [[TTAlertConfig alloc] init]; config.title = @"房主或管理员拉你上麦"; config.message = @"你已被房主或管理员拉上麦,但并未开启麦克风。如需要说话,请打开麦克风。"; [TTPopup alertWithConfig:config confirmHandler:^{ } cancelHandler:^{ }]; }]; } } else if (attachment.first == CustomMessageType_Update_RoomInfo && attachment.second == Custom_Message_Sub_Update_RoomInfo_MessageState) { [[XPRoomMiniManager shareManager] resetLocalMessage]; } } #pragma mark - 最小化 公屏的显示问题 ///添加信息 - (void)addRoomMessage:(NIMMessage *)message { if (self.roomInfo.isCloseScreen) { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) { AttachmentModel *attachment = (AttachmentModel *)obj.attachment; if (attachment.first == CustomMessageType_Update_RoomInfo && attachment.second == Custom_Message_Sub_Update_RoomInfo_MessageState){ [[XPRoomMiniManager shareManager] saveRoomMessage:message]; } } } else { [[XPRoomMiniManager shareManager] saveRoomMessage:message]; } } - (void)handleNIMNotificationSaveMessage:(NIMMessage *)message { NIMNotificationObject *notiMsg = (NIMNotificationObject *)message.messageObject; NIMChatroomNotificationContent *content = (NIMChatroomNotificationContent *)notiMsg.content; RoomInfoModel * roomInfo = self.roomInfo; if (content.eventType == NIMChatroomEventTypeEnter) { if (roomInfo.isCloseScreen) { AttachmentModel *attachement = [[AttachmentModel alloc]init]; attachement.first = CustomMessageType_Update_RoomInfo; attachement.second = Custom_Message_Sub_Update_RoomInfo_MessageState; attachement.data = @{@"roomInfo":self.roomInfo.model2dictionary}; NIMMessage *message = [[NIMMessage alloc]init]; NIMCustomObject *object = [[NIMCustomObject alloc] init]; object.attachment = attachement; message.messageObject = object; [self addRoomMessage:message]; return; } else { [self addRoomMessage:message]; NIMChatroomNotificationMember *member = content.targets[0]; if (member.userId.integerValue == [AccountInfoStorage instance].getUid.integerValue) { if (!roomInfo.hasAnimationEffect) { [self roomInfoNoGiftAnimationMessage:message]; } } } } else if(content.eventType == NIMChatroomEventTypeInfoUpdated) { if (roomInfo.isCloseScreen) {return;} if (roomInfo.datingState == RoomDatingStateChangeType_Open) { [self addRoomMessage:message]; } } } - (void)handleNIMTextMessage:(NIMMessage *)message { [self addRoomMessage:message]; } - (void)roomInfoNoGiftAnimationMessage:(NIMMessage *)message { AttachmentModel *attachement = [[AttachmentModel alloc]init]; attachement.first = CustomMessageType_Update_RoomInfo; attachement.second = Custom_Message_Sub_Update_RoomInfo_AnimateEffect; NIMMessage *tempMessage = [[NIMMessage alloc]init]; NIMCustomObject *customObject = [[NIMCustomObject alloc]init]; customObject.attachment = attachement; tempMessage.messageObject = customObject; [self addRoomMessage:tempMessage]; } - (NSDictionary *)configUpdateChatRoomQueueExt:(UserInfoModel *)userInfo { NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:@(userInfo.gender) forKey:@"gender"]; [dic safeSetObject:userInfo.avatar forKey:@"avatar"]; [dic safeSetObject:@(userInfo.uid) forKey:@"uid"]; [dic safeSetObject:userInfo.nick forKey:@"nick"]; NSString * headWearUrl = userInfo.headwearEffect.length > 0 ? userInfo.headwearEffect : userInfo.headwearPic; if (headWearUrl.length > 0) { [dic safeSetObject:headWearUrl forKey:@"headWearUrl"]; } if (userInfo.micCircle.length) { [dic safeSetObject:userInfo.micCircle forKey:@"micCircle"]; } if (userInfo.micNickColor.length) { [dic safeSetObject:userInfo.micNickColor forKey:@"micNickColor"]; } [dic safeSetObject:@(userInfo.userVipInfoVO.enterHide) forKey:@"enterHide"]; [dic safeSetObject:@(userInfo.userVipInfoVO.preventKick) forKey:@"preventKick"]; return dic; } #pragma mark - Event Response - (void)closeButtonAction:(UIButton *)sender { [[NIMSDK sharedSDK].chatroomManager exitChatroom:self.currentRoomId completion:nil]; [self reportOutRoom]; [[RtcManager instance] exitRoom]; [[XPRoomMiniManager shareManager] configRoomInfo:nil]; [[XPRoomMiniManager shareManager] configUserInfo:nil]; [[XPRoomMiniManager shareManager] configCurrentMusic:nil isPlaying:NO]; [[XPRoomMiniManager shareManager] resetLocalMessage]; [self hiddenRoomMiniView]; } - (void)reportOutRoom { if ([[AccountInfoStorage instance] getTicket].length < 1) { return; } [Api requestReportUserOutRoom:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { } uid:[[AccountInfoStorage instance] getUid] roomUid:self.currentRoomUid ticket:[[AccountInfoStorage instance] getTicket]]; } - (void)enterRomRecognizer:(UITapGestureRecognizer *)tap { if (self.currentRoomUid > 0 && self.controller) { [XPRoomViewController openMiniRoom:self.currentRoomUid viewController:self.controller]; } } - (void)roomMiniTag:(UIPanGestureRecognizer*)p { UIWindow *appWindow = [UIApplication sharedApplication].delegate.window; CGPoint panPoint = [p locationInView:appWindow]; if (p.state == UIGestureRecognizerStateBegan) { self.alpha = 1; } else if(p.state == UIGestureRecognizerStateChanged) { self.center = CGPointMake(panPoint.x, panPoint.y); } else if(p.state == UIGestureRecognizerStateEnded || p.state == UIGestureRecognizerStateCancelled) { self.alpha = 1; CGFloat touchWidth = self.frame.size.width; CGFloat touchHeight = self.frame.size.height; CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width; CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height; // fabs 是取绝对值的意思 CGFloat left = fabs(panPoint.x); CGFloat right = fabs(screenWidth - left); CGFloat top = fabs(panPoint.y); CGFloat bottom = fabs(screenHeight - top); CGFloat minSpace = 0; minSpace = MIN(MIN(MIN(top, left), bottom), right); CGPoint newCenter; CGFloat targetY = 0; //校正Y if (panPoint.y < 15 + touchHeight / 2.0) { targetY = 15 + touchHeight / 2.0; }else if (panPoint.y > (screenHeight - touchHeight / 2.0 - 15)) { targetY = screenHeight - touchHeight / 2.0 - 15; }else{ targetY = panPoint.y; } if (minSpace == left) { newCenter = CGPointMake(15+touchWidth/2.0, targetY); }else if (minSpace == right) { newCenter = CGPointMake(screenWidth - touchWidth/2.0 - 15, targetY); }else if (minSpace == top) { newCenter = CGPointMake(panPoint.x, touchWidth / 3); }else { newCenter = CGPointMake(panPoint.x, screenHeight - touchWidth / 3); } [UIView animateWithDuration:0.25 animations:^{ if (newCenter.y + self.frame.size.height / 2 > KScreenHeight - kSafeAreaBottomHeight - 44) { self.center = CGPointMake(newCenter.x, KScreenHeight - self.frame.size.height / 2 - kSafeAreaBottomHeight - 44); }else { self.center = newCenter; } }]; } } #pragma mark - 背景音乐的播放 - (void)roomBackMusicPlayFinish:(NSNotification *)notification { NSString * filePath = [notification object]; Music * currentMusic = [XPRoomMiniManager shareManager].getCurrentMusic; if (filePath && currentMusic) { self.currentMusic = currentMusic; NSArray * array = [[XPCoreDataManager shareInstance].managedObjectContext executeFetchRequest:self.request error:nil]; __block NSInteger currentIndex = 0; [array enumerateObjectsUsingBlock:^(Music * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj.musicName isEqualToString:currentMusic.musicId]) { currentIndex = idx; *stop = YES; } }]; self.currentIndex = currentIndex; NSInteger order = [[NSUserDefaults standardUserDefaults] integerForKey:kRoomBackMusicPlayMusicOrderKey]; if (order == 0) { NSInteger index = self.currentIndex +1; [self playNextMusic:index]; } else { [self playNextMusic:currentIndex]; } } } - (void)playNextMusic:(NSInteger)index { NSArray * array = [[XPCoreDataManager shareInstance].managedObjectContext executeFetchRequest:self.request error:nil]; if (index >= array.count) { index = 0; if (self.currentMusic) { [[RtcManager instance] changePlayState:BackMusicPlayState_Resume]; } else { Music * music = [array safeObjectAtIndex1:index]; [self playCurrentMusic:music index:index]; } } else { Music * music = [array safeObjectAtIndex1:index]; [self playCurrentMusic:music index:index]; } } - (void)playCurrentMusic:(Music *)music index:(NSInteger)index { NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; int musicVolum = (int)[defaults integerForKey:kRoomBackMusicAudioMixingVolumeKey]; musicVolum = musicVolum > 0 ? musicVolum : 50; int captureVolum = (int)[defaults integerForKey:kRoomBackMusicCaptureVolumeKey]; captureVolum = captureVolum > 0 ? captureVolum : 50; self.currentMusic = music; self.currentIndex = index; NSString * documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; documentsPath = [NSString stringWithFormat:@"%@/music/",documentsPath]; NSString * musicPath; if (music.musicName) { musicPath = [documentsPath stringByAppendingString:music.musicName]; } else { return; } [[RtcManager instance] playBackMusic:musicPath musicId:0 completion:^(NSString * filePath) { NSInteger order = [[NSUserDefaults standardUserDefaults] integerForKey:kRoomBackMusicPlayMusicOrderKey]; if (order == 0) { NSInteger index = self.currentIndex + 1; [self playNextMusic:index]; } else { [self playNextMusic:self.currentIndex]; } }]; [[RtcManager instance] updateUserSound:captureVolum]; [[RtcManager instance] updateMusicSound:musicVolum]; } #pragma mark - Getters And Setters - (void)setRoomInfo:(RoomInfoModel *)roomInfo { _roomInfo = roomInfo; if (_roomInfo) { self.avatarImageView.imageUrl = _roomInfo.avatar; if (_roomInfo.title.length > 8) { _roomInfo.title = [NSString stringWithFormat:@"%@…", [_roomInfo.title substringToIndex:8]]; } self.nickLabel.text = _roomInfo.title; self.idLabel.text = [NSString stringWithFormat:@"%@号:%ld", AppName,_roomInfo.erbanNo]; } } - (UIImageView *)backImageView { if (!_backImageView) { _backImageView = [[UIImageView alloc] init]; _backImageView.userInteractionEnabled = YES; _backImageView.image = [UIImage imageNamed:@"room_mini_background"]; } return _backImageView; } - (NetImageView *)avatarImageView { if (!_avatarImageView) { NetImageConfig * config = [[NetImageConfig alloc] init]; config.imageType = ImageTypeUserIcon; config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; _avatarImageView = [[NetImageView alloc] initWithConfig:config]; _avatarImageView.layer.masksToBounds = YES; _avatarImageView.layer.cornerRadius = (34 * 1.2 - 10)/2; _avatarImageView.userInteractionEnabled = YES; } return _avatarImageView; } - (UILabel *)nickLabel { if (!_nickLabel) { _nickLabel = [[UILabel alloc] init]; _nickLabel.font = [UIFont systemFontOfSize:12]; _nickLabel.textColor = [UIColor whiteColor]; _nickLabel.userInteractionEnabled = YES; } return _nickLabel; } - (UILabel *)idLabel { if (!_idLabel) { _idLabel = [[UILabel alloc] init]; _idLabel.font = [UIFont systemFontOfSize:10]; _idLabel.textColor = [UIColor whiteColor]; _idLabel.userInteractionEnabled = YES; } return _idLabel; } - (UIButton *)closeButton { if (!_closeButton) { _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_closeButton setImage:[UIImage imageNamed:@"room_mini_close"] forState:UIControlStateNormal]; [_closeButton addTarget:self action:@selector(closeButtonAction:) forControlEvents:UIControlEventTouchUpInside]; [_closeButton setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; } return _closeButton; } - (XPNoteView *)noteView { if (!_noteView) { _noteView = [[XPNoteView alloc] init]; _noteView.userInteractionEnabled = YES; _noteView.pillarColor = [UIColor colorWithWhite:1 alpha:0.6]; _noteView.pillarWidth = 2; [_noteView startAnimation]; } return _noteView; } - (NSFetchRequest *)request { if (!_request) { _request = [NSFetchRequest fetchRequestWithEntityName:@"Music"]; } return _request; } @end