优化 XPRoomPresenter、XPRoomViewController 和 XPMessageRemoteExtModel,移除冗余代码,增强 NIM 聊天室成员信息获取逻辑,新增房间类型和模式属性,提升代码可维护性和用户体验。同时,重构定时器管理和消息发送逻辑,确保功能的稳定性和一致性。

This commit is contained in:
edwinQQQ
2025-08-21 18:23:18 +08:00
parent 49975b5dc1
commit 09a2b2f02b
11 changed files with 266 additions and 71 deletions

View File

@@ -99,7 +99,6 @@
extModel.fromSayHelloChannel = userInfo.fromSayHelloChannel;
extModel.platformRole = userInfo.platformRole;
extModel.nick = userInfo.nick;
extModel.versionType = 1;
NSMutableDictionary *ext = [NSMutableDictionary dictionaryWithObject:extModel.model2dictionary forKey:[NSString stringWithFormat:@"%ld", userInfo.uid]];
request.roomExt = [ext toJSONString];

View File

@@ -9,4 +9,13 @@
@implementation XPMessageRemoteExtModel
- (instancetype)init
{
self = [super init];
if (self) {
self.versionType = 1;
}
return self;
}
@end

View File

@@ -19,8 +19,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic,copy) NSString *position;
///当前房主的 UID
@property(nonatomic, copy) NSString *roomUid;
///房間類型
@property(nonatomic, assign) NSInteger roomType;
///房間模式
@property (nonatomic, assign) NSInteger roomModeType;
@end
NS_ASSUME_NONNULL_END

View File

@@ -343,7 +343,8 @@
if (value &&
[value objectForKey:@"versionType"] &&
![member.userId isEqualToString:[AccountInfoStorage instance].getUid]) {
![member.userId isEqualToString:[AccountInfoStorage instance].getUid] &&
self.roomModeType == 0) {
AttachmentModel *attachment = [[AttachmentModel alloc] init];
attachment.first = ClientMessage_Type;
attachment.second = ClientMessage_UpMic_Ask;

View File

@@ -190,6 +190,7 @@
inviteUserMicVC.roomUid = [NSString stringWithFormat:@"%ld", self.hostDelegate.getRoomInfo.uid];
inviteUserMicVC.position = position;
inviteUserMicVC.roomType = self.hostDelegate.getRoomInfo.type;
inviteUserMicVC.roomModeType = self.hostDelegate.getRoomInfo.roomModeType;
inviteUserMicVC.blindDateVipUid = roomInfo.blindDateVipUid;
[self.hostDelegate.getCurrentNav pushViewController:inviteUserMicVC animated:YES];
}];

View File

@@ -672,6 +672,7 @@
if (error) return;
[RtcManager instance].localMuted = YES;
TTAlertConfig *config = [[TTAlertConfig alloc] init];
config.actionStyle = TTAlertActionConfirmStyle;
config.title = YMLocalizedString(@"StageView0");
config.message = YMLocalizedString(@"XPMiniRoomView3");
[TTPopup alertWithConfig:config confirmHandler:^{
@@ -1182,6 +1183,7 @@
inviteUserMicVC.isManagerOrOwner = ([position isEqualToString:@"-1"] && roomInfo.roomModeType == RoomModeType_Open_Blind);
inviteUserMicVC.roomId = roomId;
inviteUserMicVC.roomType = self.hostDelegate.getRoomInfo.type;
inviteUserMicVC.roomModeType = self.hostDelegate.getRoomInfo.roomModeType;
inviteUserMicVC.position = position;
inviteUserMicVC.roomUid = [NSString stringWithFormat:@"%ld", self.hostDelegate.getRoomInfo.uid];
inviteUserMicVC.blindDateVipUid = roomInfo.blindDateVipUid;

View File

@@ -7,6 +7,8 @@
#import <Foundation/Foundation.h>
@class NIMChatroomMember;
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, UserCardItemType){
UserCardItemType_Gift = 1,
@@ -64,6 +66,8 @@ typedef NS_ENUM(NSUInteger, UserCardItemType){
@property (nonatomic,copy) NSString *uid;
/// NIM 聊天室成员信息
@property (nonatomic,strong) NIMChatroomMember *nimMember;
@end

View File

@@ -6,6 +6,7 @@
//
#import "XPUserCardItemModel.h"
#import <NIMSDK/NIMSDK.h>
@implementation XPUserCardItemModel

View File

@@ -6,6 +6,7 @@
//
#import "UserRoomCardViewController.h"
#import <NIMSDK/NIMSDK.h>
#import "XPUserCardPresenter.h"
#import "XPRoomGiftAnimationParser.h"
@@ -888,6 +889,8 @@
@property(nonatomic, strong) UIActivityIndicatorView *loading;
@property(nonatomic, strong) UserInfoModel *controlUserInfo;
/// NIM
@property(nonatomic, strong) NIMChatroomMember *nimMember;
@end
@@ -1014,6 +1017,14 @@
NSString * roomId = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
NSString * roomUid = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.uid];
// NIM XPUserCardItemModel
if (self.nimMember) {
item.nimMember = self.nimMember;
NSLog(@"✅ UserRoomCard: 已将 NIM 成员信息存入 item - userId: %@, type: %ld", self.nimMember.userId, (long)self.nimMember.type);
} else {
NSLog(@"⚠️ UserRoomCard: NIM 成员信息未获取到item.nimMember 为 nil");
}
switch (item.type) {
case UserCardMicroType_UpDown:
[self handleUpDown:item];
@@ -1346,67 +1357,90 @@
}
- (void)buildUpMicMessage:(XPUserCardItemModel *)item {
AttachmentModel *attachment = [[AttachmentModel alloc] init];
attachment.first = ClientMessage_Type;
attachment.second = ClientMessage_UpMic_Ask;
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
[data setObject:@([[AccountInfoStorage instance].getUid integerValue])
forKey:@"uid"];
[data setObject:@(self.userInfoModel.uid)
forKey:@"targetUid"];
[data setObject:@(item.position.integerValue)
forKey:@"position"];
[data setObject:@(self.cardInfo.roomInfo.type)
forKey:@"roomType"];
[data setObject:self.userInfoModel.nick
forKey:@"targetNick"];
[data setObject:@(self.cardInfo.roomInfo.uid)
forKey:@"roomUid"];
int64_t millis = (int64_t)([[NSDate date] timeIntervalSince1970] * 1000);
[data setObject:@(millis)
forKey:@"sendTime"];
attachment.data = data;
NSString *sessionID = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
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]);
[XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"20.20.62_text_8")];
} else {
NSLog(@"[Send] ✅ 发送成功 | sessionId=%@ | main=%@ | ts=%.3f",
sessionID, onMain ? @"YES" : @"NO", [[NSDate date] timeIntervalSince1970]);
[self.navigationController popViewControllerAnimated:YES];
[XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"20.20.62_text_3")];
BOOL hasVerionType = NO;
NSDictionary *value = nil;
if (self.nimMember) {
NSError *error = nil;
NSData *data = [self.nimMember.roomExt dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error];
if (!error) {
NSLog(@"解析成功:%@", dict);
NSString *firstKey = dict.allKeys.firstObject;
if (![NSString isEmpty:firstKey]) {
value = dict[firstKey];
}
}
}];
}
// NSString * roomId = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
// NSMutableDictionary * dic = [NSMutableDictionary dictionary];
// [dic setValue:@(item.position.integerValue) forKey:@"micPosition"];
// [dic setValue:@(self.userInfoModel.uid) 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:roomId type:NIMSessionTypeChatroom];
// [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
if (value && [value objectForKey:@"versionType"]) {
hasVerionType = YES;
}
if (self.cardInfo.roomInfo.roomModeType != RoomModeType_Normal_Mode || !hasVerionType) {
NSString * roomId = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
NSMutableDictionary * dic = [NSMutableDictionary dictionary];
[dic setValue:@(item.position.integerValue) forKey:@"micPosition"];
[dic setValue:@(self.userInfoModel.uid) 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:roomId type:NIMSessionTypeChatroom];
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
} else {
AttachmentModel *attachment = [[AttachmentModel alloc] init];
attachment.first = ClientMessage_Type;
attachment.second = ClientMessage_UpMic_Ask;
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
[data setObject:@([[AccountInfoStorage instance].getUid integerValue])
forKey:@"uid"];
[data setObject:@(self.userInfoModel.uid)
forKey:@"targetUid"];
[data setObject:@(item.position.integerValue)
forKey:@"position"];
[data setObject:@(self.cardInfo.roomInfo.type)
forKey:@"roomType"];
[data setObject:self.userInfoModel.nick
forKey:@"targetNick"];
[data setObject:@(self.cardInfo.roomInfo.uid)
forKey:@"roomUid"];
int64_t millis = (int64_t)([[NSDate date] timeIntervalSince1970] * 1000);
[data setObject:@(millis)
forKey:@"sendTime"];
attachment.data = data;
NSString *sessionID = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
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]);
[XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"20.20.62_text_8")];
} else {
NSLog(@"[Send] ✅ 发送成功 | sessionId=%@ | main=%@ | ts=%.3f",
sessionID, onMain ? @"YES" : @"NO", [[NSDate date] timeIntervalSince1970]);
[self.navigationController popViewControllerAnimated:YES];
[XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"20.20.62_text_3")];
}
}];
}
[self dismissViewControllerAnimated:YES completion:^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"PopAfterUserCardAction" object:nil];
@@ -1552,6 +1586,9 @@
[self gotoUserInfoVC];
}];
// NIM
[self fetchNIMChatroomMember:userInfo];
//
[self updateCollectionViewFrame];
@@ -1603,6 +1640,27 @@
[self.loading stopAnimating];
}
#pragma mark - NIM Chatroom Member Management
/// NIM
- (void)fetchNIMChatroomMember:(UserInfoModel *)userInfo {
NSString *roomId = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
NSString *userId = [NSString stringWithFormat:@"%ld", userInfo.uid];
NIMChatroomMembersByIdsRequest *request = [[NIMChatroomMembersByIdsRequest alloc]init];
request.roomId = roomId;
request.userIds = @[userId];
@kWeakify(self);
[[NIMSDK sharedSDK].chatroomManager fetchChatroomMembersByIds:request completion:^(NSError * _Nullable error, NSArray<NIMChatroomMember *> * _Nullable members) {
@kStrongify(self);
if (!error && members) {
self.nimMember = [members firstObject];
NSLog(@"✅ UserRoomCard: 成功获取 NIM 成员信息 - userId: %@, type: %ld", self.nimMember.userId, (long)self.nimMember.type);
} else {
NSLog(@"❌ UserRoomCard: 获取 NIM 成员信息失败 - userId: %@, error: %@", userId, error.localizedDescription);
}
}];
}
- (void)onGetFunctionArraySccess:(NSArray<XPUserCardItemModel *> *)array {
NSMutableArray *temp_1 = @[].mutableCopy;

View File

@@ -0,0 +1,105 @@
# UserRoomCardViewController NIM 成员信息获取实施流程
## 实施概述
`UserRoomCardViewController.m` 中实现了通过 `userInfoModel` 获取 `NIMChatroomMember` 并传递给 `XPUserCardItemModel` 的完整流程。
## 实施步骤
### 1. 添加 NIM 成员信息属性
`UserRoomCardViewController` 的接口中添加了 `nimMember` 属性:
```objc
/// NIM 聊天室成员信息
@property(nonatomic, strong) NIMChatroomMember *nimMember;
```
### 2. 在 XPUserCardItemModel 中添加 nimMember 属性
`XPUserCardItemModel.h` 中添加了:
```objc
/// NIM 聊天室成员信息
@property (nonatomic,strong) NIMChatroomMember *nimMember;
```
使用前向声明 `@class NIMChatroomMember;` 避免循环依赖。
### 3. 实现获取 NIM 成员信息的方法
添加了 `fetchNIMChatroomMember:` 方法:
```objc
- (void)fetchNIMChatroomMember:(UserInfoModel *)userInfo {
NSString *roomId = [NSString stringWithFormat:@"%ld", self.cardInfo.roomInfo.roomId];
NSString *userId = [NSString stringWithFormat:@"%ld", userInfo.uid];
@kWeakify(self);
[[NIMSDK sharedSDK].chatroomManager fetchChatroomMemberById:userId
roomId:roomId
completion:^(NSError * _Nullable error, NIMChatroomMember * _Nullable member) {
@kStrongify(self);
if (!error && member) {
self.nimMember = member;
NSLog(@"✅ UserRoomCard: 成功获取 NIM 成员信息 - userId: %@, type: %ld", member.userId, (long)member.type);
} else {
NSLog(@"❌ UserRoomCard: 获取 NIM 成员信息失败 - userId: %@, error: %@", userId, error.localizedDescription);
}
}];
}
```
### 4. 在用户信息获取成功后调用
`onGetUserInfoSuccess:` 方法中添加了调用:
```objc
- (void)onGetUserInfoSuccess:(UserInfoModel *)userInfo {
// ... 现有代码 ...
// 获取 NIM 聊天室成员信息
[self fetchNIMChatroomMember:userInfo];
// ... 现有代码 ...
}
```
### 5. 在 handleTapItem 时传递 NIM 成员信息
`handleTapItem:` 方法开始时添加了:
```objc
- (void)handleTapItem:(XPUserCardItemModel *)item {
// ... 现有代码 ...
// 将 NIM 成员信息存入 XPUserCardItemModel
if (self.nimMember) {
item.nimMember = self.nimMember;
NSLog(@"✅ UserRoomCard: 已将 NIM 成员信息存入 item - userId: %@, type: %ld", self.nimMember.userId, (long)self.nimMember.type);
} else {
NSLog(@"⚠️ UserRoomCard: NIM 成员信息未获取到item.nimMember 为 nil");
}
// ... 现有代码 ...
}
```
## 流程总结
1. **初始化阶段**:当 `UserRoomCardViewController` 被展示时,在 `onGetUserInfoSuccess:` 中调用 `fetchNIMChatroomMember:` 获取 NIM 成员信息
2. **异步获取**:通过 `[NIMSDK sharedSDK].chatroomManager fetchChatroomMemberById:roomId:completion:]` 异步获取成员信息
3. **临时保存**:将获取到的 `NIMChatroomMember` 保存在 `self.nimMember` 属性中
4. **传递使用**:在 `handleTapItem:` 时,将 `self.nimMember` 赋值给 `item.nimMember`,供后续操作使用
## 使用场景
- 可以根据 `NIMChatroomMember.type` 判断用户是房主、管理员还是普通成员
- 可以根据 `NIMChatroomMember.onlineState` 判断用户在线状态
- 在权限控制、UI 显示等方面可以使用 NIM 成员信息
## 注意事项
1. NIM 成员信息获取是异步的,可能存在获取失败的情况
2.`handleTapItem` 中需要检查 `self.nimMember` 是否为 nil
3. 添加了详细的日志输出,便于调试和监控

View File

@@ -2354,25 +2354,21 @@ XPCandyTreeInsufficientBalanceViewDelegate>
config.confirmButtonConfig.title = YMLocalizedString(@"MessageContentGuildView5");
config.cancelButtonConfig.title = YMLocalizedString(@"MessageContentGuildView4");
// clean
[TTPopup dismiss];
[self removeUpMicAskTimer];
@kWeakify(self);
[TTPopup alertWithConfig:config
confirmHandler:^{
@kStrongify(self);
//
if (self.upMicAskTimer) {
[self.upMicAskTimer invalidate];
self.upMicAskTimer = nil;
}
[self removeUpMicAskTimer];
[self sendResponseUpMicMessage:attachment.data isAgree:YES];
} cancelHandler:^{
@kStrongify(self);
//
if (self.upMicAskTimer) {
[self.upMicAskTimer invalidate];
self.upMicAskTimer = nil;
}
[self removeUpMicAskTimer];
[self sendResponseUpMicMessage:attachment.data isAgree:NO];
}];
@@ -2384,6 +2380,13 @@ XPCandyTreeInsufficientBalanceViewDelegate>
repeats:NO];
}
- (void)removeUpMicAskTimer {
if (self.upMicAskTimer) {
[self.upMicAskTimer invalidate];
self.upMicAskTimer = nil;
}
}
/**
10
@@ -2405,10 +2408,20 @@ XPCandyTreeInsufficientBalanceViewDelegate>
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"];