Files
peko-ios/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m
2024-11-28 18:45:28 +08:00

1455 lines
60 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// YMRoomMessageView.m
// YUMI
//
// Created by YUMI on 2021/10/11.
//
#import "XPRoomMessageContainerView.h"
///Third
#import <Masonry/Masonry.h>
#import <NIMSDK/NIMSDK.h>
///Tool
#import "DJDKMIMOMColor.h"
#import "YUMIMacroUitls.h"
#import "XPRoomMessageConstant.h"
#import "XPRoomMessageParser.h"
#import "AccountInfoStorage.h"
#import "XPRoomMiniManager.h"
#import "PLTimeUtil.h"
#import "ClientConfig.h"
#import <POP.h>
#import "ThemeColor+Room.h"
#import "NSArray+Safe.h"
#import "Api+Room.h"
///Model
#import "RoomInfoModel.h"
#import "AttachmentModel.h"
#import "RoomFaceSendInfoModel.h"
#import "XPMessageRemoteExtModel.h"
#import "RoomPKChooseUserModel.h"
#import "CandyTreeResultModel.h"
#import "RoomSailingPrizeModel.h"
#import "UserInfoModel.h"
#import "XPMessageInfoModel.h"
#import "GiftReceiveInfoModel.h"
#import "XPGiftStorage.h"
///View
#import "XPRoomMessageTableViewCell.h"
#import "XPRoomMessageHeaderView.h"
#import "PIRoomMessagePhotoAlbumCell.h"
#import "PIRoomMessageUnlockPhotoAlbumView.h"
#import "PIRoomPhotoAlbumItemModel.h"
#import "SDPhotoBrowser.h"
#import "XPSkillCardPlayerManager.h"
#import "RoomCahtCell.h"
// Boom
#import "BoomInfoModel.h"
NSString * const kRoomShowTopicKey = @"kRoomShowTopicKey";
@interface XPRoomMessageContainerView ()<UITableViewDelegate, UITableViewDataSource, XPRoomMessageTableViewCellDelegate, UIGestureRecognizerDelegate,PIRoomMessagePhotoAlbumCellDelegate,SDPhotoBrowserDelegate,PIRoomMessageUnlockPhotoAlbumViewDelegate>
///房间的代理
@property (nonatomic,weak) id<RoomHostDelegate> hostDelegate;
///列表
@property (nonatomic,strong) UITableView *messageTableView;
///头部
@property (nonatomic,strong) XPRoomMessageHeaderView *headerView;
///底部有新的消息
@property (nonatomic,strong) UIButton *messageTipsBtn;
///有人at你
@property (nonatomic, strong) UIButton *atTipBtn;
///是否处于正在爬楼
@property (nonatomic,assign) BOOL isPending;
///是否是最小化进房的
@property (nonatomic,assign) BOOL isMiniEnter;
///数据源
@property (nonatomic,strong) NSMutableArray<XPMessageInfoModel *> *datasource;
@property (nonatomic,strong) NSMutableArray<XPMessageInfoModel *> *datasource_chat;
@property (nonatomic,strong) NSMutableArray<XPMessageInfoModel *> *datasource_gift;
///临时存放消息的数组
@property (nonatomic,strong) NSMutableArray *incomingMessages;
///有多少人at我
@property (nonatomic, assign) NSInteger atCount;
///@我的消息位置集合
@property (nonatomic, strong) NSMutableArray *locationArray;
///messageView 持有这个工具类 进行数据的分发操作 TODO: 有需要在改
@property (nonatomic,strong) XPRoomMessageParser *messageParser;
@property(nonatomic,strong) PIRoomPhotoAlbumItemModel *lookUpModel;
@property(nonatomic,assign) BOOL isLoadHistoryMessage;
@property (nonatomic, assign) NSInteger displayType;
@property (nonatomic, strong) NSMutableDictionary<NSIndexPath *, NSNumber *> *heightCache;
@property (nonatomic, strong) NSMutableDictionary<NSIndexPath *, NSNumber *> *heightCache_2;
@end
@implementation XPRoomMessageContainerView
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (instancetype)initWithDelegate:(id<RoomHostDelegate>)delegate {
self = [super init];
if (self) {
self.heightCache = @{}.mutableCopy;
self.heightCache_2 = @{}.mutableCopy;
self.displayType = 1;
self.isLoadHistoryMessage = YES;
self.hostDelegate = delegate;
[self initSubViews];
[self initSubViewConstraints];
}
return self;
}
- (void)changeType:(NSInteger)type {
self.displayType = type;
[self updateAllDataSource];
[self.messageTableView reloadData];
if (self.displayType == 1) {
self.messageTableView.tableHeaderView = self.headerView;
} else {
self.messageTableView.tableHeaderView = nil;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self scrollToBottom:YES];
});
}
- (void)updateAllDataSource {
self.datasource_chat = @[].mutableCopy;
self.datasource_gift = @[].mutableCopy;
for (XPMessageInfoModel *model in self.datasource) {
switch (model.first) {
case NIMMessageTypeText:
[self.datasource_chat addObject:model];
break;
case CustomMessageType_Gift:
case CustomMessageType_RoomBoom:
case CustomMessageType_Candy_Tree:
case CustomMessageType_Super_Gift:
case CustomMessageType_AllMicroSend:
case CustomMessageType_Treasure_Fairy:
[self.datasource_gift addObject:model];
break;
}
}
}
- (UIView *)listView {
return self;
}
- (void)showUserCard:(NSInteger)uid{
[self.messageParser showUserCard:uid];
}
#pragma mark - Response
- (void)messageTipsBtnAction:(UIButton *)sender {
self.isPending = NO;
self.messageTipsBtn.hidden = YES;
[self appendAndScrollToBottom];
}
- (void)atTipsBtnAction:(UIButton *)sender {
self.isPending = YES;
[self appendAndScrollToAtUser];
}
///追加数据源
- (void)appendAndScrollToAtUser {
if (self.incomingMessages.count < 1) {
NSInteger rows = self.datasource.count;
if (!self.locationArray.count) {
[self.messageTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(rows-1) inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
self.messageTipsBtn.hidden = YES;
self.isPending = NO;
self.atCount = 0;
self.atTipBtn.hidden = YES;
return;
}
int index = [self.locationArray[0] intValue];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
if (rows > indexPath.row) {
[self.messageTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
if (rows == indexPath.row + 1) {
self.messageTipsBtn.hidden = YES;
self.isPending = NO;
}
} else {
[self.messageTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(rows-1) inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
//滚动到底部时隐藏@提示
self.messageTipsBtn.hidden = YES;
}
if (self.locationArray.count) {
[self.locationArray removeObjectAtIndex:0];
self.atCount -= 1;
[self.atTipBtn setTitle:[NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageContainerView0"), (unsigned long)self.locationArray.count] forState:UIControlStateNormal];
if (self.locationArray.count == 0) {
self.atTipBtn.hidden = YES;
}
} else {
self.atTipBtn.hidden = YES;
}
} else {
if (self.datasource.count > kRoomMessageMaxLength) {
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, kRoomMessageMaxLength/2)];
NSArray *needRemoveMsgArray = [self.datasource objectsAtIndexes:set];
[self.datasource removeObjectsInArray:needRemoveMsgArray];
[self updateAllDataSource];
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
for (int i = 0; i<self.locationArray.count; i++) {///移除掉前面消息的数据后前面如果有at我的消息也一并移除掉
NSNumber *number = self.locationArray[i];
if (number.integerValue < kRoomMessageMaxLength / 2) {
self.atCount--;
[indexSet addIndex:i];
}
}
[self.locationArray removeObjectsAtIndexes:indexSet];
for (int i = 0; i<self.locationArray.count; i++) {//移除前面的at消息后,后面的at消息需要更新索引
NSNumber *number = self.locationArray[i];
number = @(number.integerValue - kRoomMessageMaxLength / 2);
[self.locationArray replaceObjectAtIndex:i withObject:number];
}
}
// 执行插入
NSMutableArray *indexPaths = [NSMutableArray array];
for (id item in self.incomingMessages) {
XPMessageInfoModel *model = nil;
if ([item isKindOfClass:[NIMMessage class]]) {
model = [self.messageParser parseMessageAttribute:item];
} else if ([item isKindOfClass:[NIMBroadcastMessage class]]) {
model = [self.messageParser parseBroadcastMessageAttribute:item];
}
if (!model) {
continue;
}
[self.datasource addObject:model];
[indexPaths addObject:[NSIndexPath indexPathForRow:self.datasource.count - 1 inSection:0]];
if ([item isKindOfClass:[NIMMessage class]]) {
id nickNameInfos = [(NIMMessage*)item remoteExt][@"atUids"];
if ([nickNameInfos isKindOfClass:[NSArray class]]) {
for (NSString *nick in nickNameInfos) {
if ([nick isEqualToString:[AccountInfoStorage instance].getUid]) {
[self.locationArray addObject:@(self.datasource.count-1)];
}
}
}
}
}
[self updateAllDataSource];
[self.incomingMessages removeAllObjects];
[self.messageTableView reloadData];
NSInteger rows = self.datasource.count;
if (!self.locationArray.count) {
[self.messageTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(rows-1) inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
self.messageTipsBtn.hidden = YES;
self.isPending = NO;
self.atCount = 0;
self.atTipBtn.hidden = YES;
return;
}
int index = [self.locationArray[0] intValue];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
if (rows > indexPath.row) {
[self.messageTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
if (rows == indexPath.row + 1) {
self.messageTipsBtn.hidden = YES;
self.isPending = NO;
}
} else {
[self.messageTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(rows-1) inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
//滚动到底部时隐藏@提示
self.messageTipsBtn.hidden = YES;
}
if (self.locationArray.count) {
[self.locationArray removeObjectAtIndex:0];
self.atCount -= 1;
[self.atTipBtn setTitle:[NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageContainerView1"), (unsigned long)self.locationArray.count] forState:UIControlStateNormal];
if (self.locationArray.count == 0) {
self.atTipBtn.hidden = YES;
}
} else {
self.atTipBtn.hidden = YES;
}
}
}
#pragma mark - @我
///查找有多少人@我
- (void)findAtMeNumber {
if (self.incomingMessages.count) {
NIMMessage *message = self.incomingMessages.lastObject;
if (![message isKindOfClass:[NIMMessage class]] || ![message respondsToSelector:@selector(remoteExt)]) {
return;
}
id nickNameNifo = message.remoteExt[@"atUids"];
if ([nickNameNifo isKindOfClass:[NSArray class]]) {
for (NSString *nick in nickNameNifo) {
if ([nick isEqualToString:[AccountInfoStorage instance].getUid]) {
self.atCount += 1;
}
}
}
if (self.atCount > 0) {
self.atTipBtn.hidden = NO;
[self.atTipBtn setTitle:[NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageContainerView2"), self.atCount] forState:UIControlStateNormal];
} else {
self.atTipBtn.hidden = YES;
}
}
}
#pragma mark - Private Method
- (void)initSubViews {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addCustomMessage:) name:@"message" object:nil];
[self addSubview:self.messageTableView];
[self addSubview:self.messageTipsBtn];
[self addSubview:self.atTipBtn];
self.messageTableView.tableHeaderView = self.headerView;
}
- (void)initSubViewConstraints {
RoomInfoModel *infoModel = self.hostDelegate.getRoomInfo;
CGFloat top = infoModel.type == RoomType_MiniGame ? 0 : 10;
[self.messageTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self).offset(15);
make.bottom.trailing.mas_equalTo(self);
make.top.equalTo(self).mas_offset(top);
}];
[self.messageTipsBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_greaterThanOrEqualTo(100);
make.height.mas_equalTo(30);
make.bottom.mas_equalTo(self.mas_bottom).offset(-5);
make.leading.mas_equalTo(self);
}];
[self.atTipBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(100);
make.height.mas_equalTo(30);
make.bottom.mas_equalTo(self.mas_bottom).offset(-5);
make.leading.mas_equalTo(self);
}];
}
///是否是当前房间
- (BOOL)isCurrentRoom:(NSString *)sessionId {
if ([sessionId isEqualToString:[NSString stringWithFormat:@"%ld", self.hostDelegate.getRoomInfo.roomId]]) {
return YES;
}
return NO;
}
///判断是否隐身进房
- (BOOL)handleHideEnter:(NIMMessage *)message {
NIMMessageChatroomExtension * messageExt = (NIMMessageChatroomExtension *)message.messageExt;
NSDictionary * dic = [(NSDictionary *)messageExt.roomExt.toJSONObject objectForKey:message.from];
XPMessageRemoteExtModel * extModel = [XPMessageRemoteExtModel modelWithJSON:dic];
return (extModel.enterHide || extModel.platformRole == 1);
}
#pragma mark - 添加数据并且做自动滚动
///添加信息
- (void)addRoomMessage:(id)messageData {
if(self.isLoadHistoryMessage == YES)return;
[self.incomingMessages addObject:messageData];
if ([messageData isKindOfClass:[NIMBroadcastMessage class]]) {
NIMBroadcastMessage *broadcastMessage = (NIMBroadcastMessage *)messageData;
[[XPRoomMiniManager shareManager] saveRoomMessage:broadcastMessage];
} else if ([messageData isKindOfClass:[NIMMessage class]]) {
NIMMessage *message = (NIMMessage *)messageData;
if (!self.isMiniEnter) {/// 最小化进房的话 不需要重新保存
if (self.hostDelegate.getRoomInfo.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];
}
}
}
if (self.isPending) {
self.messageTipsBtn.hidden = NO;
[self findAtMeNumber];
} else {
[self appendAndScrollToBottom];
}
}
///追加数据源
- (void)appendAndScrollToBottom {
if (self.incomingMessages.count < 1) {
///滚动到底部如果有人at自己后income消息在点击at按钮处做了拼接处理因为点击at按钮跳转到的是对应的at人消息如果后面有其他消息时点有更多按钮时需要滚动到最底部
[self scrollToBottom:YES];
return;
}
if (self.datasource.count > kRoomMessageMaxLength) {
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, kRoomMessageMaxLength/2)];
NSArray *needRemoveMsgArray = [self.datasource objectsAtIndexes:set];
[self.datasource removeObjectsInArray:needRemoveMsgArray];
}
@kWeakify(self);
[self.incomingMessages enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
@kStrongify(self);
if ([obj isKindOfClass:[NIMMessage class]]) {
XPMessageInfoModel *model = [self.messageParser parseMessageAttribute:(NIMMessage *)obj];
[self.datasource addObject:model];
} else if ([obj isKindOfClass:[NIMBroadcastMessage class]]) {
XPMessageInfoModel *model = [self.messageParser parseBroadcastMessageAttribute:(NIMBroadcastMessage *)obj];
if (model) {
[self.datasource addObject:model];
}
}
}];
[self updateAllDataSource];
[self.incomingMessages removeAllObjects];
[self.messageTableView reloadData];
//执行插入动画并滚动
[self scrollToBottom:YES];
}
///执行插入动画并滚动
- (void)scrollToBottom:(BOOL)animated {
NSArray *source = @[];
switch (self.displayType) {
case 1:
source = self.datasource;
break;
case 2:
source = self.datasource_chat;
break;
case 3:
source = self.datasource_gift;
break;
default:
source = self.datasource;
break;
}
if(source.count > 0){
NSIndexPath *ip = [NSIndexPath indexPathForRow:source.count-1 inSection:0]; //取最后一行数据
[self.messageTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:animated]; //滚动到最后一行
self.atCount = 0;
self.atTipBtn.hidden = YES;
[self.locationArray removeAllObjects];
}
}
///自定义消息 是否可以加到 公屏 需要自己维护
- (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 xpSafeObjectAtIndex: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.hostDelegate.getUserInfo.userLevelVo.experLevelSeq > prizeModel.userLevelLimit) {
return YES;
}
} else if(attachment.first == CustomMessageType_Room_Album){
return YES;
}else if(attachment.first == CustomMessageType_Gift) {
if(attachment.data[@"isRoomAlbum"] != nil){
BOOL isRoomAlbum = [attachment.data[@"isRoomAlbum"] boolValue];
if(isRoomAlbum == YES){
return NO;
}
}
GiftReceiveInfoModel *info = [GiftReceiveInfoModel modelWithJSON:attachment.data];
GiftInfoModel *giftInfo = info.gift == nil ? info.giftInfo : info.gift;
if (giftInfo == nil) {
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:info.giftId];
}
if (giftInfo.giftType == GiftType_super){
return NO;
}
}else if(attachment.first == CustomMessageType_AllMicroSend){
GiftReceiveInfoModel *info = [GiftReceiveInfoModel modelWithJSON:attachment.data];
GiftInfoModel *giftInfo = info.gift == nil ? info.giftInfo : info.gift;
if (giftInfo == nil) {
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:info.giftId];
}
if (giftInfo.giftType == GiftType_super){
return NO;
}
}
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_Look_Love):
[NSSet setWithObjects:
@(Custom_Message_Sub_Look_Love_Me),
@(Custom_Message_Sub_Look_Love_InRoom),
@(Custom_Message_Sub_Look_Love_AllRoom),
@(Custom_Message_Sub_Look_Love_AllRoom_Notify),
@(Custom_Message_Sub_Look_Love_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_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),
@(Custom_Message_Sub_Room_Gift_LuckBag_FullScree),
nil],
@(CustomMessageType_Gift_Compound):
[NSSet setWithObjects:@(Custom_Message_Sub_Gift_Compound),
nil],
@(CustomMessageType_Tarot):
[NSSet setWithObjects:
@(Custom_Message_Sub_Tarot_Novice),
@(Custom_Message_Sub_Tarot_Advanced),
@(Custom_Message_Sub_Tarot_Intermediate),
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],
@(CustomMessageType_RedPacket):
[NSSet setWithObjects:
@(Custom_Message_Sub_OpenRedPacketSuccess),
nil],
@(CustomMessageType_Treasure_Fairy):
[NSSet setWithObjects:
@(Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L1),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L2),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L3),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L4),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L5),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Ball_L1),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Ball_L2),
@(Custom_Message_Sub_Treasure_Fairy_Draw_Ball_L3),
@(Custom_Message_Sub_Treasure_Fairy_Convert_L1),
@(Custom_Message_Sub_Treasure_Fairy_Convert_L2),
@(Custom_Message_Sub_Treasure_Fairy_Convert_L3),
nil],
@(CustomMessageType_Guardian_Planet):
[NSSet setWithObjects:
@(Custom_Message_Sub_Guardian_Planet_One_Room),
@(Custom_Message_Sub_Guardian_Planet_All_Room),
nil],
@(CustomMessageType_General_Public_Screen):
[NSSet setWithObjects:
@(Custom_Message_Sub_General_Public_Screen_One_Room),
@(Custom_Message_Sub_General_Public_Screen_All_Room),
nil],
@(CustomMessageType_Super_Gift):
[NSSet setWithObjects:
@(Custom_Message_Sub_Super_Gift),
nil],
};
}
- (void)addCustomMessage:(NSNotification *)notification {
self.isMiniEnter = NO;
if (self.hostDelegate.getRoomInfo.isCloseScreen) {return;}
NIMMessage * message = notification.object;
[self addRoomMessage:message];
}
///用户进入房间显示 房间话题
- (void)createUserEnterRoomAddRoomTopicMessage {
if ([ClientConfig shareConfig].configInfo.hideNoticeVersion == YES) {
return;
}
RoomInfoModel * roomInfo = self.hostDelegate.getRoomInfo;
if (roomInfo.uid == [AccountInfoStorage instance].getUid.integerValue) {return;}
NSString * key = [NSString stringWithFormat:@"%@_%@_%ld", kRoomShowTopicKey, [AccountInfoStorage instance].getUid, roomInfo.uid];
NSDate * oldDate = [[NSUserDefaults standardUserDefaults] valueForKey:key];
NSDate * date = [NSDate date];
if (roomInfo.introduction.length > 0) {
if (oldDate) {
NSDateComponents *compons = [PLTimeUtil compareTwoDate:date secondDate:[NSDate date]];
if (ABS(compons.year) > 0 || ABS(compons.month) > 0 || ABS(compons.day) > 0) {
NIMMessage * message = [[NIMMessage alloc] init];
NIMTipObject *tipObject = [[NIMTipObject alloc] init];
message.messageObject = tipObject;
NSString * content = [NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageContainerView3"), roomInfo.introduction];
message.text = content;
message.localExt = @{@"isRoomTopic": @(NO)};
[message setValue:@(NIMMessageTypeTip) forKey:@"messageType"];
[message setValue:[NIMSession session:[NSString stringWithFormat:@"%ld", roomInfo.roomId] type:NIMSessionTypeChatroom] forKey:@"session"];
[self addRoomMessage:message];
[[NSUserDefaults standardUserDefaults] setValue:@(YES) forKey:key];
[[NSUserDefaults standardUserDefaults] synchronize];
}
} else {
NIMMessage * message = [[NIMMessage alloc] init];
NSString * content = [NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageContainerView3"), roomInfo.introduction];
message.text = content;
message.localExt = @{@"isRoomTopic": @(NO)};
[message setValue:@(NIMMessageTypeTip) forKey:@"messageType"];
[message setValue:[NIMSession session:[NSString stringWithFormat:@"%ld", roomInfo.roomId] type:NIMSessionTypeChatroom] forKey:@"session"];
[self addRoomMessage:message];
[[NSUserDefaults standardUserDefaults] setValue:@(YES) forKey:key];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
NIMMessage * message = [[NIMMessage alloc] init];
NIMTipObject *tipObject = [[NIMTipObject alloc] init];
message.messageObject = tipObject;
message.text = YMLocalizedString(@"XPRoomMessageContainerView5");
message.localExt = @{@"isRoomTopic": @(YES)};
[message setValue:@(NIMMessageTypeTip) forKey:@"messageType"];
[message setValue:[NIMSession session:[NSString stringWithFormat:@"%ld", roomInfo.roomId] type:NIMSessionTypeChatroom] forKey:@"session"];
[self addRoomMessage:message];
}
- (void)handleBroadcastMessageAttachment:(AttachmentModel *)attachment; {
// if (attachment.first == CustomMessageType_RoomBoom) {
// Boom632Model *m = [Boom632Model modelWithJSON:attachment.data];
// NIMMessage * message = [[NIMMessage alloc] init];
// message.text = YMLocalizedString(@"XPRoomMessageContainerView5");
// message.localExt = @{@"isRoomTopic": @(YES)};
// [message setValue:@(NIMMessageTypeTip) forKey:@"messageType"];
// [message setValue:[NIMSession session:[NSString stringWithFormat:@"%ld", roomInfo.roomId] type:NIMSessionTypeChatroom] forKey:@"session"];
// [self addRoomMessage:message];
// }
}
- (void)handleBroadcastMessage:(NIMBroadcastMessage *)message {
[self addRoomMessage:message];
}
#pragma mark - RoomGuestDelegate
- (void)handleNIMCustomAttachment:(AttachmentModel *)attachment{
}
- (void)handleNIMCustomMessage:(NIMMessage *)message {
self.isMiniEnter = NO;
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) {
[self.datasource removeAllObjects];
[self updateAllDataSource];
[self.incomingMessages removeAllObjects];
[self.locationArray removeAllObjects];
self.atCount = 0;
self.atTipBtn.hidden = YES;
self.messageTipsBtn.hidden = YES;
self.isPending = NO;
[[XPRoomMiniManager shareManager] resetLocalMessage];
[self addRoomMessage:message];
return;
} else if (attachment.first == CustomMessageType_Update_RoomInfo && attachment.second == Custom_Message_Sub_Update_RoomInfo_CleanScreen) {
[self.datasource removeAllObjects];
[self updateAllDataSource];
[self.incomingMessages removeAllObjects];
[self.locationArray removeAllObjects];
self.atCount = 0;
self.atTipBtn.hidden = YES;
self.messageTipsBtn.hidden = YES;
self.isPending = NO;
[[XPRoomMiniManager shareManager] resetLocalMessage];
[self addRoomMessage:message];
return;
} else if(attachment.first == CustomMessageType_Candy_Tree && attachment.second == Custom_Message_Sub_Candy_Tree_Me) {
CandyTreeGiftInfoModel * model = [CandyTreeGiftInfoModel modelWithDictionary:attachment.data];
if (model.uid.integerValue != [AccountInfoStorage instance].getUid.integerValue) {
return;
}
} else if (attachment.first == CustomMessageType_Kick_User) {
NSString * uid = [AccountInfoStorage instance].getUid;
NSString * roomId = [NSString stringWithFormat:@"%ld", self.hostDelegate.getRoomInfo.roomId];
NIMChatroomMembersByIdsRequest *request = [[NIMChatroomMembersByIdsRequest alloc]init];
request.roomId = roomId;
request.userIds = @[uid];
[[NIMSDK sharedSDK].chatroomManager fetchChatroomMembersByIds:request completion:^(NSError * _Nullable error, NSArray<NIMChatroomMember *> * _Nullable members) {
if (error == nil) {
NIMChatroomMember * member = members.firstObject;
BOOL isCreator = member.type == NIMChatroomMemberTypeCreator;
BOOL isManager = member.type == NIMChatroomMemberTypeManager;
if (isCreator || isManager) {
[self addRoomMessage:message];
}
}
}];
return;
}
}
if (self.hostDelegate.getRoomInfo.isCloseScreen) {
return;
}
if ([self isCanDisplayMessage:message]) {
[self addRoomMessage:message];
}
}
- (void)handleNIMNotificationMessage:(NIMMessage *)message {
self.isMiniEnter = NO;
NIMNotificationObject *notiMsg = (NIMNotificationObject *)message.messageObject;
NIMChatroomNotificationContent *content = (NIMChatroomNotificationContent *)notiMsg.content;
RoomInfoModel * roomInfo = self.hostDelegate.getRoomInfo;
if (content.eventType == NIMChatroomEventTypeEnter) {
if (roomInfo.isCloseScreen) {
self.isLoadHistoryMessage = NO;
AttachmentModel *attachment = [[AttachmentModel alloc]init];
attachment.first = CustomMessageType_Update_RoomInfo;
attachment.second = Custom_Message_Sub_Update_RoomInfo_MessageState;
attachment.data = @{@"roomInfo":self.hostDelegate.getRoomInfo.model2dictionary};
NIMMessage *message = [[NIMMessage alloc]init];
NIMCustomObject *object = [[NIMCustomObject alloc] init];
object.attachment = attachment;
message.messageObject = object;
[self addRoomMessage:message];
return;
} else {
NIMChatroomNotificationMember *member = content.targets[0];
if (member.userId.integerValue == [AccountInfoStorage instance].getUid.integerValue) {
///自己进房成功后拉取历史消息
if(self.datasource.count > 0)
{
self.isLoadHistoryMessage = NO;
return;
}
[self handleFetchHistoryMessage:message];
} else {
self.isLoadHistoryMessage = NO;
BOOL hideEnter = [self handleHideEnter:message];
if (!hideEnter) {
///插入进房消息及房间公告提示
[self addRoomMessage:message];
}
}
}
} else if(content.eventType == NIMChatroomEventTypeInfoUpdated) {
if (roomInfo.isCloseScreen) {return;}
if (roomInfo.datingState == RoomDatingStateChangeType_Open) {
NSString * uid = [AccountInfoStorage instance].getUid;
NSString * roomId = [NSString stringWithFormat:@"%ld", roomInfo.roomId];
NIMChatroomMembersByIdsRequest *request = [[NIMChatroomMembersByIdsRequest alloc]init];
request.roomId = roomId;
request.userIds = @[uid];
[[NIMSDK sharedSDK].chatroomManager fetchChatroomMembersByIds:request completion:^(NSError * _Nullable error, NSArray<NIMChatroomMember *> * _Nullable members) {
if (error == nil) {
NIMChatroomMember * member = members.firstObject;
BOOL isCreator = member.type == NIMChatroomMemberTypeCreator;
BOOL isManager = member.type == NIMChatroomMemberTypeManager;
if (isCreator || isManager) {
[self addRoomMessage:message];
}
}
}];
}
}
}
- (void)handleFetchHistoryMessage:(NIMMessage *)message {
RoomInfoModel * roomInfo = self.hostDelegate.getRoomInfo;
NSString *roomId = [NSString stringWithFormat:@"%ld", self.hostDelegate.getRoomInfo.roomId];
NIMHistoryMessageSearchOption *option = [[NIMHistoryMessageSearchOption alloc] init];
option.limit = [ClientConfig shareConfig].configInfo.roomMessageCount;
option.startTime = self.hostDelegate.getRoomInfo.clearScreenTime / 1000.0;
option.order = NIMMessageSearchOrderAsc;
option.messageTypes = @[@(NIMMessageTypeText),@(NIMMessageTypeCustom)];
[[NIMSDK sharedSDK].chatroomManager fetchMessageHistory:roomId option:option result:^(NSError * _Nullable error, NSArray<NIMMessage *> * _Nullable messages) {
if(error != nil){
self.isLoadHistoryMessage = NO;
}
if (messages.count) {
//如果拉取的数量等于请求的数量说明这个时间点以后的消息数量大于等于需要拉取的数量直接拉取最新的50条
if (messages.count == [ClientConfig shareConfig].configInfo.roomMessageCount) {
NIMHistoryMessageSearchOption *option = [[NIMHistoryMessageSearchOption alloc] init];
option.limit = [ClientConfig shareConfig].configInfo.roomMessageCount;
option.order = NIMMessageSearchOrderDesc;
option.messageTypes = @[@(NIMMessageTypeText),@(NIMMessageTypeCustom)];
@kWeakify(self);
[[NIMSDK sharedSDK].chatroomManager fetchMessageHistory:roomId option:option result:^(NSError * _Nullable error, NSArray<NIMMessage *> * _Nullable messages) {
@kStrongify(self);
if(error != nil){
self.isLoadHistoryMessage = NO;
}
if (self.datasource.count > kRoomMessageMaxLength) {
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, kRoomMessageMaxLength/2)];
NSArray *needRemoveMsgArray = [self.datasource objectsAtIndexes:set];
[self.datasource removeObjectsInArray:needRemoveMsgArray];
}
// 执行插入
for (NIMMessage *item in messages.reverseObjectEnumerator) {
[self dealWithHistoryDataWithMessage:item];
}
self.isLoadHistoryMessage = NO;
BOOL hideEnter = [self handleHideEnter:message];
if (!hideEnter) {
///插入进房消息及房间公告提示
[self addRoomMessage:message];
}
if (!roomInfo.hasAnimationEffect) {
[self roomInfoNoGiftAnimationMessage:message];
}
[self createUserEnterRoomAddRoomTopicMessage];
[self updateAllDataSource];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.messageTableView reloadData];
[self scrollToBottom:YES];
});
}];
return;
}
if (self.datasource.count > kRoomMessageMaxLength) {
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, kRoomMessageMaxLength/2)];
NSArray *needRemoveMsgArray = [self.datasource objectsAtIndexes:set];
[self.datasource removeObjectsInArray:needRemoveMsgArray];
}
// 执行插入
for (NIMMessage *item in messages) {
[self dealWithHistoryDataWithMessage:item];
}
self.isLoadHistoryMessage = NO;
BOOL hideEnter = [self handleHideEnter:message];
if (!hideEnter) {
///插入进房消息及房间公告提示
[self addRoomMessage:message];
}
if (!roomInfo.hasAnimationEffect) {
[self roomInfoNoGiftAnimationMessage:message];
}
[self createUserEnterRoomAddRoomTopicMessage];
[self updateAllDataSource];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.messageTableView reloadData];
[self scrollToBottom:YES];
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{///回到主线程
self.isLoadHistoryMessage = NO;
BOOL hideEnter = [self handleHideEnter:message];
if (!hideEnter) {
///插入进房消息及房间公告提示
[self addRoomMessage:message];
}
if (!roomInfo.hasAnimationEffect) {
[self roomInfoNoGiftAnimationMessage:message];
}
[self createUserEnterRoomAddRoomTopicMessage];
});
}
}];
}
-(void)dealWithHistoryDataWithMessage:(NIMMessage *)item{
BOOL isHaveSave = NO;
if(item.messageType == NIMMessageTypeText){
isHaveSave = YES;
}else if(item.messageType == NIMMessageTypeCustom){
NIMCustomObject *obj = (NIMCustomObject *)item.messageObject;
if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) {
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
if (attachment.first == CustomMessageType_Room_Album && attachment.second == Custom_Message_Sub_Room_Album) {
isHaveSave = YES;
}
}
}
if(isHaveSave == NO)return;
[self.datasource addObject:[self.messageParser parseMessageAttribute:item]];
if (!self.isMiniEnter) {/// 最小化进房的话 不需要重新保存
if (self.hostDelegate.getRoomInfo.isCloseScreen) {
NIMCustomObject *obj = (NIMCustomObject *)item.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:item];
}
}
} else {
[[XPRoomMiniManager shareManager] saveRoomMessage:item];
}
}
}
- (void)handleNIMTextMessage:(NIMMessage *)message {
self.isMiniEnter = NO;
if (self.hostDelegate.getRoomInfo.isCloseScreen) {return;}
[self addRoomMessage:message];
}
- (void)roomInfoNoGiftAnimationMessage:(NIMMessage *)message {
self.isMiniEnter = NO;
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];
}
- (void)onRoomMiniEntered {
self.isMiniEnter = YES;
self.isLoadHistoryMessage = NO;
///最小化进房 不需要请求任何接口 但是如果不加延迟的话 无法滚动到底部 原因还不知道
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSArray * temArray = [XPRoomMiniManager shareManager].getLocalCurrentRoomMessage;
[temArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[NIMMessage class]]) {
XPMessageInfoModel *model = [self.messageParser parseMessageAttribute:(NIMMessage *)obj];
[self.datasource addObject:model];
} else if ([obj isKindOfClass:[NIMBroadcastMessage class]]) {
XPMessageInfoModel *model = [self.messageParser parseBroadcastMessageAttribute:(NIMBroadcastMessage *)obj];
if (model) {
[self.datasource addObject:model];
}
}
}];
[self updateAllDataSource];
[self.messageTableView reloadData];
//执行插入动画并滚动
[self scrollToBottom:YES];
});
}
- (void)onRoomEntered {
[[XPRoomMiniManager shareManager] resetLocalMessage];
self.headerView.bubbleColor = self.hostDelegate.getRoomInfo.type == RoomType_MiniGame ? [UIColor colorWithWhite:1 alpha:0.2] : [UIColor colorWithWhite:1 alpha:0.3];
}
- (void)onRoomUpdate {
///改变公屏的背景样式
if (self.hostDelegate.getRoomInfo.hadChangeRoomType) {
self.headerView.bubbleColor = self.hostDelegate.getRoomInfo.type == RoomType_MiniGame ? [UIColor colorWithWhite:1 alpha:0.2] : [UIColor colorWithWhite:1 alpha:0.3];
[self.messageTableView reloadData];
}
RoomInfoModel *infoModel = self.hostDelegate.getRoomInfo;
CGFloat top = infoModel.type == RoomType_MiniGame ? 0 : 10;
[self.messageTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self).offset(15);
make.bottom.trailing.mas_equalTo(self);
make.top.equalTo(self).mas_offset(top);
}];
}
#pragma mark - ScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 手动拖拽开始
self.isPending = YES;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
// 手动拖拽结束decelerate0松手时静止1松手时还在运动,会触发DidEndDecelerating方法
if (!decelerate) {
[self finishDraggingWith:scrollView];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// 静止后触发(手动)
[self finishDraggingWith:scrollView];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
if (!self.isPending && self.incomingMessages.count <= 0) {
[self scrollToBottom:YES];
}
}
/**
手动拖拽动作彻底完成(减速到零)
*/
- (void)finishDraggingWith:(UIScrollView *)scrollView {
CGFloat contentSizeH = scrollView.contentSize.height;
CGFloat contentOffsetY = scrollView.contentOffset.y;
CGFloat sizeH = scrollView.frame.size.height;
self.isPending = contentSizeH - contentOffsetY - sizeH > 20.0;
if (!self.isPending) {
self.messageTipsBtn.hidden = YES;
self.atTipBtn.hidden = YES;
self.atCount = 0;
[self.locationArray removeAllObjects];
if (self.incomingMessages.count > 0) {
[self appendAndScrollToBottom];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"roomMessageTabelViewStopScroll" object:nil];
}
#pragma mark - UITableViewDelegate And UITableViewDataSource
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *source = @[];
switch (self.displayType) {
case 1: {
source = self.datasource;
XPMessageInfoModel *model = [source xpSafeObjectAtIndex:indexPath.row];
NSNumber *cacheHeight = self.heightCache[indexPath];
if (cacheHeight) {
return cacheHeight.floatValue;
} else {
CGFloat height = [self calculateHeightForMessage:model];
self.heightCache[indexPath] = @(height);
return height;
}
}
break;
case 2: {
source = self.datasource_chat;
XPMessageInfoModel *model = [source xpSafeObjectAtIndex:indexPath.row];
NSNumber *cacheHeight = self.heightCache_2[indexPath];
if (cacheHeight) {
return cacheHeight.floatValue;
} else {
CGFloat height = [self calculateHeightForMessage:model];
self.heightCache_2[indexPath] = @(height);
return height;
}
}
break;
case 3:
source = self.datasource_gift;
break;
default:
source = self.datasource;
break;
}
// // 如果 model 中有高度数据,使用 model 的高度
// if (model.rowHeight > 0) {
//// NSLog(@"---00--- : %f", model.rowHeight);
// return model.rowHeight;
// }
// 否则,使用自适应高度
return UITableViewAutomaticDimension;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch (self.displayType) {
case 1:
return self.datasource.count;
break;
case 2:
return self.datasource_chat.count;
break;
case 3:
return self.datasource_gift.count;
break;
default:
return self.datasource.count;
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *source = @[];
switch (self.displayType) {
case 1:
source = self.datasource;
break;
case 2:
source = self.datasource_chat;
break;
case 3:
source = self.datasource_gift;
break;
default:
source = self.datasource;
break;
}
XPMessageInfoModel *model = [source xpSafeObjectAtIndex:indexPath.row];
NSString *cellKey = NSStringFromClass([XPRoomMessageTableViewCell class]);
if(model.first == CustomMessageType_Room_Album){
PIRoomMessagePhotoAlbumCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([PIRoomMessagePhotoAlbumCell class])];
cell.delegate = self;
cell.messageInfo = model;
cell.roomType = self.hostDelegate.getRoomInfo.type;
return cell;
}
else if (model.isBoom) {
cellKey = @"XPRoomMessageTableViewCell_Boom";
}
RoomCahtCell *cell = [RoomCahtCell cellFor:tableView];
cell.messageInfo = model;
// XPRoomMessageTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellKey];
// cell.delegate = self;
// cell.isLeftBoomImage = model.isBoom;
// cell.messageInfo = model;
// cell.roomType = self.hostDelegate.getRoomInfo.type;
return cell;
}
- (CGFloat)calculateHeightForMessage:(XPMessageInfoModel *)messageInfo {
if (!messageInfo) return 60; // 返回默认高度
CGFloat totalHeight = 0;
// 1. 计算富文本内容的高度
NSMutableAttributedString *content = [[NSMutableAttributedString alloc] initWithAttributedString:messageInfo.content];
CGFloat maxWidth = kRoomMessageMaxWidth - 24; // 内容最大宽度
CGSize boundingSize = CGSizeMake(maxWidth, CGFLOAT_MAX);
YYTextContainer *textContainer = [YYTextContainer containerWithSize:boundingSize];
YYTextLayout *textLayout = [YYTextLayout layoutWithContainer:textContainer text:content];
totalHeight += textLayout.textBoundingSize.height;
// // 2. 计算图片的高度(如果存在图片)
// if (messageInfo.bubbleImageUrl && !messageInfo.isHiddenBubble) {
// UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:messageInfo.bubbleImageUrl];
// if (cachedImage) {
// CGFloat imageWidth = cachedImage.size.width;
// CGFloat imageHeight = cachedImage.size.height;
// CGFloat scale = imageWidth / imageHeight;
// CGFloat adjustedImageHeight = maxWidth / scale; // 根据宽度调整高度
// totalHeight += adjustedImageHeight;
// } else {
// // 如果图片尚未加载,使用默认占位高度
// totalHeight += 100; // 默认图片高度
// }
// }
// 3. 加上内边距
totalHeight += 16 * 2; // 顶部和底部的 padding
return totalHeight;
}
#pragma mark - XPRoomMessageTableViewCellDelegate
- (void)xPRoomMessageTableViewCellDidTapEmpty:(XPRoomMessageTableViewCell *)view {
if (self.delegate && [self.delegate respondsToSelector:@selector(xPRoomMessageContainerViewlDidTapEmpty:)]) {
[self.delegate xPRoomMessageContainerViewlDidTapEmpty:self];
}
}
-(void)clickDidTapEmptyAction{
if (self.delegate && [self.delegate respondsToSelector:@selector(xPRoomMessageContainerViewlDidTapEmpty:)]) {
[self.delegate xPRoomMessageContainerViewlDidTapEmpty:self];
}
}
#pragma mark - PIRoomMessagePhotoAlbumCell
- (void)pIRoomMessagePhotoAlbumCellDelegateDidTapEmpty:(PIRoomMessagePhotoAlbumCell *)view{
if (self.delegate && [self.delegate respondsToSelector:@selector(xPRoomMessageContainerViewlDidTapEmpty:)]) {
[self.delegate xPRoomMessageContainerViewlDidTapEmpty:self];
}
}
-(void)unlockAlbumHandleWithInfo:(PIRoomPhotoAlbumItemModel *_Nonnull)info{
PIRoomMessageUnlockPhotoAlbumView *albumView = [[PIRoomMessageUnlockPhotoAlbumView alloc]initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
albumView.albumModel = info;
albumView.delegate = self;
[TTPopup popupView:albumView style:TTPopupStyleAlert];
}
-(void)pIRoomMessagePhotoAlbumCell:(PIRoomMessagePhotoAlbumCell *_Nonnull)cell lookUpAlbumPhotoWithAlbumModel:(PIRoomPhotoAlbumItemModel *_Nonnull)albumModel;{
SDPhotoBrowser *browser = [[SDPhotoBrowser alloc]init];
browser.sourceImagesContainerView = cell;
browser.delegate = self;
browser.imageCount = 1;
browser.currentImageIndex = 0;
browser.isMe = NO;
self.lookUpModel = albumModel;
[browser show];
}
- (void)pIRoomMessagePhotoAlbumCell:(PIRoomMessagePhotoAlbumCell *)cell lookUpUserCardModel:(PIRoomPhotoAlbumItemModel *)albumModel{
[self.messageParser showUserCard:albumModel.uid.integerValue];
}
#pragma mark - PIRoomMessageUnlockPhotoAlbumViewDelegate
- (void)unlockRoomAlbumImageWithAlbumModel:(PIRoomPhotoAlbumItemModel *)albumModel{
[XNDJTDDLoadingTool showLoading];
[Api unlockRoomAlbumPhoto:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
[XNDJTDDLoadingTool hideHUD];
if(code == 200){
NSMutableDictionary *getData = [NSMutableDictionary dictionary];
[getData addEntriesFromDictionary:data.data];
AttachmentModel *attachment = [[AttachmentModel alloc] init];
attachment.first = CustomMessageType_Gift;
attachment.second = Custom_Message_Sub_Gift_Send;
NSDictionary *targetUsers = ((NSArray *)[getData objectForKey:@"targetUsers"]).firstObject;
[getData setObject:[targetUsers valueForKeyPath:@"uid"] forKey:@"targetUid"];
[getData setObject:[targetUsers valueForKeyPath:@"nick"] forKey:@"targetNick"];
[getData setObject:[targetUsers valueForKeyPath:@"avatar"] forKey:@"targetAvatar"];
[getData setObject:@(YES) forKey:@"isRoomAlbum"];
attachment.data = getData;
[self sendCustomMessage:attachment];
if(albumModel.ID != nil){
if(![[XPSkillCardPlayerManager shareInstance].photoIdList containsObject:albumModel.ID]){
if([XPSkillCardPlayerManager shareInstance].photoIdList == nil){
[XPSkillCardPlayerManager shareInstance].photoIdList = [NSMutableArray arrayWithArray:@[albumModel.ID]];
}else{
[[XPSkillCardPlayerManager shareInstance].photoIdList addObject:albumModel.ID];
}
}
[[NSNotificationCenter defaultCenter]postNotificationName:@"kGetgetUnlockRoomAlbumPhotoListNot" object:nil];
}
return;
}
[XNDJTDDLoadingTool showErrorWithMessage:msg];
} id:albumModel.ID roomUid:@(self.hostDelegate.getRoomInfo.uid).stringValue];
}
- (void)sendCustomMessage:(AttachmentModel *)attachment {
NSString *sessionID = [NSString stringWithFormat:@"%ld", [self.hostDelegate getRoomInfo].roomId];
NIMMessage *message = [[NIMMessage alloc]init];
NIMCustomObject *object = [[NIMCustomObject alloc] init];
object.attachment = attachment;
message.messageObject = object;
UserInfoModel *userInfo = [self.hostDelegate getUserInfo];
XPMessageRemoteExtModel *extModel = [[XPMessageRemoteExtModel alloc] init];
extModel.androidBubbleUrl = userInfo.androidBubbleUrl;
extModel.iosBubbleUrl = userInfo.iosBubbleUrl;
extModel.fromSayHelloChannel = userInfo.fromSayHelloChannel;
NSMutableDictionary *remoteExt = [NSMutableDictionary dictionaryWithObject:extModel.model2dictionary forKey:[NSString stringWithFormat:@"%ld", userInfo.uid]];
message.remoteExt = remoteExt;
NIMSessionType sessionType = NIMSessionTypeChatroom;
//构造会话
NIMSession *session = [NIMSession session:sessionID type:sessionType];
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
}
#pragma mark - SDPhotoBrowserDelegate
- (NSURL *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index{
if(self.lookUpModel != nil){
return [[NSURL alloc]initWithString:self.lookUpModel.photoUrl];
}
return nil;
}
- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index {
return [UIImageConstant defaultBannerPlaceholder];
}
#pragma mark - Getters And Setters
- (UITableView *)messageTableView {
if (!_messageTableView) {
_messageTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_messageTableView.delegate = self;
_messageTableView.dataSource = self;
_messageTableView.rowHeight = UITableViewAutomaticDimension;
_messageTableView.estimatedRowHeight = 100; // 预估高度
_messageTableView.tableFooterView = [UIView new];
_messageTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_messageTableView.backgroundColor = [UIColor clearColor];
_messageTableView.showsVerticalScrollIndicator = NO;
_messageTableView.tag = 666;
if (@available(iOS 11.0, *)) {
_messageTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[_messageTableView registerClass:[XPRoomMessageTableViewCell class] forCellReuseIdentifier:@"XPRoomMessageTableViewCell_Boom"];
[_messageTableView registerClass:[XPRoomMessageTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPRoomMessageTableViewCell class])];
[_messageTableView registerClass:[PIRoomMessagePhotoAlbumCell class] forCellReuseIdentifier:NSStringFromClass([PIRoomMessagePhotoAlbumCell class])];
[RoomCahtCell registerTo:_messageTableView];
}
return _messageTableView;
}
- (XPRoomMessageHeaderView *)headerView {
if (!_headerView) {
_headerView = [[XPRoomMessageHeaderView alloc] init];
}
return _headerView;
}
- (UIButton *)messageTipsBtn {
if (!_messageTipsBtn) {
_messageTipsBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_messageTipsBtn setTitle:YMLocalizedString(@"XPRoomMessageContainerView6") forState:UIControlStateNormal];
[_messageTipsBtn setTitleColor:[DJDKMIMOMColor appMainColor] forState:UIControlStateNormal];
_messageTipsBtn.layer.cornerRadius = 15.0;
_messageTipsBtn.layer.masksToBounds = YES;
_messageTipsBtn.titleLabel.font = [UIFont systemFontOfSize:12.0];
_messageTipsBtn.backgroundColor = [UIColor whiteColor];
[_messageTipsBtn addTarget:self action:@selector(messageTipsBtnAction:) forControlEvents:UIControlEventTouchUpInside];
_messageTipsBtn.hidden = YES;
}
return _messageTipsBtn;
}
- (UIButton *)atTipBtn {
if (!_atTipBtn) {
_atTipBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_atTipBtn setTitle:YMLocalizedString(@"XPRoomMessageContainerView7") forState:UIControlStateNormal];
[_atTipBtn setTitleColor:[DJDKMIMOMColor appMainColor] forState:UIControlStateNormal];
_atTipBtn.layer.cornerRadius = 15.0;
_atTipBtn.layer.masksToBounds = YES;
_atTipBtn.titleLabel.font = [UIFont systemFontOfSize:12.0];
_atTipBtn.backgroundColor = [UIColor whiteColor];
[_atTipBtn addTarget:self action:@selector(atTipsBtnAction:) forControlEvents:UIControlEventTouchUpInside];
_atTipBtn.hidden = YES;
}
return _atTipBtn;
}
- (NSMutableArray<XPMessageInfoModel *> *)datasource {
if (!_datasource) {
_datasource = [NSMutableArray array];
}
return _datasource;
}
- (NSMutableArray<XPMessageInfoModel *> *)datasource_chat {
if (!_datasource_chat) {
_datasource_chat = [NSMutableArray array];
}
return _datasource_chat;
}
- (NSMutableArray<XPMessageInfoModel *> *)datasource_gift {
if (!_datasource_gift) {
_datasource_gift = [NSMutableArray array];
}
return _datasource_gift;
}
- (NSMutableArray *)incomingMessages {
if (!_incomingMessages) {
_incomingMessages = [NSMutableArray array];
}
return _incomingMessages;
}
- (NSMutableArray *)locationArray {
if (!_locationArray) {
_locationArray = [NSMutableArray array];
}
return _locationArray;
}
- (XPRoomMessageParser *)messageParser {
if (!_messageParser) {
_messageParser = [[XPRoomMessageParser alloc] init];
_messageParser.hostDelegate = self.hostDelegate;
}
return _messageParser;
}
@end