// // PublicRoomManager.m // YUMI // // Created by YUMI on 2024/12/19. // #import "PublicRoomManager.h" #import "UserInfoModel.h" #import "ClientConfig.h" #import "AccountModel.h" #import "AccountInfoStorage.h" #import "XPMessageRemoteExtModel.h" #import "AttachmentModel.h" #import "YUMIConstant.h" #import "XPSkillCardPlayerManager.h" @interface PublicRoomManager () @property (nonatomic, assign) BOOL isInitialized; @property (nonatomic, assign) BOOL isInPublicRoom; @property (nonatomic, copy) NSString *currentPublicRoomId; @property (nonatomic, copy) NSString *currentUserId; @property (nonatomic, strong) UserInfoModel *userInfo; @end @implementation PublicRoomManager #pragma mark - 单例方法 + (instancetype)sharedManager { static dispatch_once_t onceToken; static PublicRoomManager *instance; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; [instance initialize]; }); return instance; } - (instancetype)init { self = [super init]; if (self) { _isInitialized = NO; _isInPublicRoom = NO; _currentPublicRoomId = nil; _currentUserId = nil; _userInfo = nil; } return self; } #pragma mark - 生命周期管理 - (void)initialize { // 防止重复初始化 if (self.isInitialized) { NSLog(@"PublicRoomManager: 已经初始化,跳过重复初始化"); return; } // 注册云信代理 [[NIMSDK sharedSDK].chatManager addDelegate:self]; [[NIMSDK sharedSDK].chatroomManager addDelegate:self]; // 标记为已初始化 self.isInitialized = YES; } - (BOOL)checkConfigPublicRoomID:(NSString *)partitionId { ClientDataModel *configInfo = [ClientConfig shareConfig].configInfo; if (!configInfo || !configInfo.publicChatRoomIdMap) { NSLog(@"PublicRoomManager: 配置信息未加载,等待配置更新"); return NO; } self.currentPublicRoomId = [configInfo.publicChatRoomIdMap objectForKey:partitionId]; return [NSString isEmpty:self.currentPublicRoomId]; } - (void)reset { NSLog(@"PublicRoomManager: 开始重置"); // 退出公共房间(同步等待完成) if (self.isInPublicRoom && self.currentPublicRoomId) { [self exitPublicRoomWithCompletion:^(NSError * _Nullable error) { if (error) { NSLog(@"PublicRoomManager: 退出公共房间失败: %@", error); } else { NSLog(@"PublicRoomManager: 退出公共房间成功"); self.currentUserId = nil; self.userInfo = nil; NSLog(@"PublicRoomManager: 重置完成"); } }]; } else { NSLog(@"PublicRoomManager: 不在房间,不处理"); } // 重置状态 self.isInitialized = NO; self.isInPublicRoom = NO; self.currentPublicRoomId = nil; } #pragma mark - 状态查询 - (BOOL)isInitialized { return _isInitialized; } - (BOOL)isInPublicRoom { return _isInPublicRoom; } - (NSString *)currentPublicRoomId { return _currentPublicRoomId; } #pragma mark - 私有方法 - (void)tryEnterPublicRoom { NSLog(@"PublicRoomManager: 开始尝试进入公共房间"); NSLog(@"PublicRoomManager: 当前状态 - isInitialized: %@, isInPublicRoom: %@, currentPublicRoomId: %@", self.isInitialized ? @"YES" : @"NO", self.isInPublicRoom ? @"YES" : @"NO", self.currentPublicRoomId ?: @"nil"); if (!self.isInitialized) { NSLog(@"PublicRoomManager: 管理器未初始化,无法进入公共房间"); return; } if (!self.userInfo) { NSLog(@"PublicRoomManager: 用户信息缺失,无法进入公共房间"); return; } // 获取公共房间ID NSString *partitionId = self.userInfo.partitionId; ClientDataModel *configInfo = [ClientConfig shareConfig].configInfo; NSDictionary *publicChatRoomIdMap = configInfo.publicChatRoomIdMap; NSLog(@"PublicRoomManager: 配置信息 - partitionId: %@, configInfo: %@, publicChatRoomIdMap: %@", partitionId ?: @"nil", configInfo ? @"存在" : @"nil", publicChatRoomIdMap ? @"存在" : @"nil"); if (!publicChatRoomIdMap) { NSLog(@"PublicRoomManager: 公共房间配置缺失"); return; } if (!partitionId) { NSLog(@"PublicRoomManager: 分区ID缺失"); return; } NSNumber *roomId = publicChatRoomIdMap[partitionId]; if (!roomId) { NSLog(@"PublicRoomManager: 未找到分区 %@ 对应的公共房间ID", partitionId); return; } NSLog(@"PublicRoomManager: 尝试进入公共房间,分区ID: %@, 房间ID: %@", partitionId, roomId); // 进入公共房间 [self enterPublicRoomWithRoomId:roomId.stringValue completion:^(NSError * _Nullable error) { if (error) { NSLog(@"PublicRoomManager: 进入公共房间失败: %@", error); } else { NSLog(@"PublicRoomManager: 进入公共房间成功,房间ID: %@", roomId.stringValue); } }]; } - (void)enterPublicRoomWithRoomId:(NSString *)roomId completion:(void(^)(NSError * _Nullable error))completion { if (!self.userInfo) { NSError *error = [NSError errorWithDomain:@"PublicRoomManager" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"用户信息缺失 nnn"}]; if (completion) { completion(error); } return; } // 创建进房请求 NIMChatroomEnterRequest *request = [[NIMChatroomEnterRequest alloc] init]; request.roomId = roomId; // 设置扩展信息 XPMessageRemoteExtModel *extModel = [[XPMessageRemoteExtModel alloc] init]; extModel.defUser = self.userInfo.defUser; extModel.erbanNo = self.userInfo.erbanNo; extModel.carName = self.userInfo.carName; extModel.inRoomNameplatePic = self.userInfo.nameplatePic; extModel.inRoomNameplateWord = self.userInfo.nameplateWord; extModel.isCustomWord = self.userInfo.isCustomWord; extModel.charmUrl = self.userInfo.userLevelVo.charmUrl; extModel.experLevelSeq = self.userInfo.userLevelVo.experLevelSeq; extModel.experUrl = self.userInfo.userLevelVo.experUrl; extModel.newUser = self.userInfo.newUser; extModel.vipIcon = self.userInfo.userVipInfoVO.nameplateUrl; extModel.iosBubbleUrl = self.userInfo.iosBubbleUrl; extModel.androidBubbleUrl = self.userInfo.androidBubbleUrl; extModel.enterHide = self.userInfo.userVipInfoVO.enterHide; extModel.preventKick = self.userInfo.userVipInfoVO.preventKick; extModel.enterRoomEffects = self.userInfo.userVipInfoVO.enterRoomEffects; extModel.gender = self.userInfo.gender; extModel.fromSayHelloChannel = self.userInfo.fromSayHelloChannel; extModel.platformRole = self.userInfo.platformRole; extModel.nick = self.userInfo.nick; NSMutableDictionary *ext = [NSMutableDictionary dictionaryWithObject:extModel.model2dictionary forKey:[NSString stringWithFormat:@"%ld", self.userInfo.uid]]; request.roomExt = [ext toJSONString]; // 进入房间 @kWeakify(self); [[NIMSDK sharedSDK].chatroomManager enterChatroom:request completion:^(NSError * _Nullable error, NIMChatroom * _Nullable chatroom, NIMChatroomMember * _Nullable me) { @kStrongify(self); dispatch_async(dispatch_get_main_queue(), ^{ if (error) { NSLog(@"PublicRoomManager: 进入公共房间失败: %@", error); if (completion) { completion(error); } } else { NSLog(@"PublicRoomManager: 进入公共房间成功,房间ID: %@", roomId); self.isInPublicRoom = YES; self.currentPublicRoomId = roomId; if (completion) { completion(nil); } } }); }]; } #pragma mark - 手动控制 - (void)enterPublicRoomWithCompletion:(void(^)(NSError * _Nullable error))completion { if (!self.isInitialized) { NSError *error = [NSError errorWithDomain:@"PublicRoomManager" code:-2 userInfo:@{NSLocalizedDescriptionKey: @"管理器未初始化"}]; if (completion) { completion(error); } return; } if (self.isInPublicRoom) { NSLog(@"PublicRoomManager: 已在公共房间中"); if (completion) { completion(nil); } return; } [self tryEnterPublicRoom]; } - (void)exitPublicRoomWithCompletion:(void(^)(NSError * _Nullable error))completion { if (!self.isInPublicRoom || !self.currentPublicRoomId) { NSLog(@"PublicRoomManager: 未在公共房间中"); if (completion) { completion(nil); } return; } NSLog(@"PublicRoomManager: room id-%@ 正在尝试退出公共房间", self.currentPublicRoomId); @kWeakify(self); [[NIMSDK sharedSDK].chatroomManager exitChatroom:self.currentPublicRoomId completion:^(NSError * _Nullable error) { @kStrongify(self); dispatch_async(dispatch_get_main_queue(), ^{ if (error) { NSLog(@"PublicRoomManager: 退出公共房间失败: %@", error); } else { NSLog(@"PublicRoomManager: 退出公共房间成功"); self.isInPublicRoom = NO; self.currentPublicRoomId = nil; } if (completion) { completion(error); } }); }]; } #pragma mark - 用户信息更新处理 - (void)updateUserInfo:(UserInfoModel *)userInfo { NSLog(@"PublicRoomManager: 开始更新用户信息"); NSLog(@"PublicRoomManager: 用户信息 - uid: %ld, partitionId: %@", userInfo.uid, userInfo.partitionId ?: @"nil"); if (!userInfo) { NSLog(@"PublicRoomManager: 用户信息为空,更新失败"); return; } if (!userInfo.partitionId) { NSLog(@"PublicRoomManager: 用户分区ID缺失,更新失败"); return; } // 检查用户是否切换 if (self.currentUserId && ![self.currentUserId isEqualToString:[NSString stringWithFormat:@"%ld", userInfo.uid]]) { NSLog(@"PublicRoomManager: 检测到用户切换,重置管理器"); [self reset]; } self.userInfo = userInfo; self.currentUserId = [NSString stringWithFormat:@"%ld", userInfo.uid]; if (![self checkConfigPublicRoomID:@(userInfo.uid).stringValue]) { return; } NSLog(@"PublicRoomManager: 用户信息更新完成 - currentUserId: %@, isInitialized: %@, isInPublicRoom: %@", self.currentUserId, self.isInitialized ? @"YES" : @"NO", self.isInPublicRoom ? @"YES" : @"NO"); // 注释掉自动进入房间逻辑,改为统一入口控制 // 如果已初始化但未在公共房间,尝试进入 // if (self.isInitialized && !self.isInPublicRoom) { // NSLog(@"PublicRoomManager: 条件满足,开始尝试进入公共房间"); // [self tryEnterPublicRoom]; // } else { // NSLog(@"PublicRoomManager: 条件不满足,跳过进入公共房间 - isInitialized: %@, isInPublicRoom: %@", // self.isInitialized ? @"YES" : @"NO", // self.isInPublicRoom ? @"YES" : @"NO"); // } } #pragma mark - 配置更新处理 - (void)updateConfig { if (!self.isInitialized) { NSLog(@"PublicRoomManager: 未初始化,跳过配置更新"); return; } ClientDataModel *configInfo = [ClientConfig shareConfig].configInfo; if (!configInfo || !configInfo.publicChatRoomIdMap) { NSLog(@"PublicRoomManager: 配置信息不完整,跳过配置更新"); return; } // 注释掉自动进入房间逻辑,改为统一入口控制 // 如果未在公共房间,尝试进入 // if (!self.isInPublicRoom) { // [self tryEnterPublicRoom]; // } } #pragma mark - NIMChatRoomManagerDelegate #define ConnectionStateStyleString(enum) \ [@[@"Entering", @"EnterOK", @"EnterFailed", @"LoseConnection"] objectAtIndex:(enum)] - (void)chatroom:(NSString *)roomId connectionStateChanged:(NIMChatroomConnectionState)state { NSLog(@"PublicRoomManager 房间连接状态: %@", ConnectionStateStyleString(state)); } #pragma mark - NIMChatManagerDelegate - (void)onRecvMessages:(NSArray *)messages { // 只处理公共房间的消息 for (NIMMessage *message in messages) { if (message.session.sessionType == NIMSessionTypeChatroom) { NSString *sessionId = message.session.sessionId; if ([sessionId isEqualToString:self.currentPublicRoomId]) { NIMMessageChatroomExtension *messageExt = (NIMMessageChatroomExtension *)message.messageExt; AttachmentModel *attachment; if (message.messageType == NIMMessageTypeCustom) { NIMCustomObject *obj = (NIMCustomObject *) message.messageObject; attachment = (AttachmentModel *) obj.attachment; if (attachment) { switch (attachment.first) { case CustomMessageType_Super_Gift: [self handleFirst_106:attachment message:message]; break; default: break; } } } // NSLog(@"PublicRoomManager: 收到公共房间消息: %@\n%@", // message.rawAttachContent, // messageExt.roomExt); } } } } - (void)handleFirst_106:(AttachmentModel *)attachment message:(NIMMessage *)message { // 只有用户在房间时,才会转发 if (![XPSkillCardPlayerManager shareInstance].isInRoom) { NSLog(@"PublicRoomManager: 用户未在房间中,跳过消息转发"); return; } switch (attachment.second) { case Custom_Message_Sub_Super_Gift: [[NSNotificationCenter defaultCenter] postNotificationName:@"MessageFromPublicRoomWithAttachmentNotification" object:message]; NSLog(@"PublicRoomManager: 转发 106 - 1061 类型消息到房间"); break; default: break; } } @end