2025-08-08 10:49:36 +08:00
|
|
|
|
//
|
|
|
|
|
|
// QXRoomChatListView.m
|
|
|
|
|
|
// QXLive
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by 启星 on 2025/6/7.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#import "QXRoomChatListView.h"
|
|
|
|
|
|
#import "UIImage+WebP.h"
|
2025-10-20 09:43:10 +08:00
|
|
|
|
#define messageNameColor RGB16(0x00C8FF)
|
|
|
|
|
|
#define messageGiftColor RGB16(0xFFE309)
|
|
|
|
|
|
NSArray<NSValue *> *findAllOccurrencesOfString(NSString *fullString, NSString *substring) {
|
|
|
|
|
|
NSMutableArray<NSValue *> *occurrences = [NSMutableArray array];
|
|
|
|
|
|
NSRange searchRange = NSMakeRange(0, fullString.length);
|
|
|
|
|
|
NSRange foundRange;
|
|
|
|
|
|
|
|
|
|
|
|
while (searchRange.location < fullString.length) {
|
|
|
|
|
|
searchRange.length = fullString.length - searchRange.location;
|
|
|
|
|
|
foundRange = [fullString rangeOfString:substring
|
|
|
|
|
|
options:0
|
|
|
|
|
|
range:searchRange];
|
|
|
|
|
|
|
|
|
|
|
|
if (foundRange.location != NSNotFound) {
|
|
|
|
|
|
// 找到匹配,添加到数组
|
|
|
|
|
|
[occurrences addObject:[NSValue valueWithRange:foundRange]];
|
|
|
|
|
|
|
|
|
|
|
|
// 更新搜索范围,从当前匹配位置之后继续搜索
|
|
|
|
|
|
searchRange.location = foundRange.location + foundRange.length;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 没有更多匹配,退出循环
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return [occurrences copy];
|
|
|
|
|
|
}
|
2025-08-08 10:49:36 +08:00
|
|
|
|
NSInteger maxMessageCount = 20;
|
|
|
|
|
|
@interface QXRoomChatListView() <UITableViewDelegate,UITableViewDataSource,QXRoomSeatDelegate>
|
|
|
|
|
|
@property (nonatomic,strong)UITableView *tableView;
|
|
|
|
|
|
@property (nonatomic,strong)NSMutableArray *dataArray;
|
|
|
|
|
|
@property (nonatomic,strong)NSMutableArray *giftArray;
|
|
|
|
|
|
@property (nonatomic,strong)NSMutableArray *chatArray;
|
|
|
|
|
|
@property (nonatomic,assign)NSInteger messageCount;
|
|
|
|
|
|
@property (nonatomic,strong)UIButton *allBtn;
|
|
|
|
|
|
@property (nonatomic,strong)UIButton *chatBtn;
|
|
|
|
|
|
@property (nonatomic,strong)UIButton *giftBtn;
|
|
|
|
|
|
@property (nonatomic,strong)UIButton *selectedBtn;
|
|
|
|
|
|
@property (nonatomic,assign)BOOL isDragging;
|
|
|
|
|
|
@property (nonatomic,strong)UILabel *messageLabel;
|
|
|
|
|
|
@property (nonatomic,strong)UIButton *messageCountBtn;
|
|
|
|
|
|
@end
|
|
|
|
|
|
@implementation QXRoomChatListView
|
|
|
|
|
|
|
|
|
|
|
|
- (instancetype)init
|
|
|
|
|
|
{
|
|
|
|
|
|
self = [super init];
|
|
|
|
|
|
if (self) {
|
|
|
|
|
|
[self initSubviews];
|
|
|
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)initSubviews{
|
|
|
|
|
|
[self addSubview:self.tableView];
|
|
|
|
|
|
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.right.equalTo(self);
|
|
|
|
|
|
make.top.equalTo(self).offset(40);
|
|
|
|
|
|
make.bottom.equalTo(self).offset(-10);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.allBtn = [[UIButton alloc] init];
|
|
|
|
|
|
NSAttributedString *allAttrNor = [[NSAttributedString alloc] initWithString:QXText(@"全部") attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:14],NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
|
|
|
|
|
NSAttributedString *allAttrSel = [[NSAttributedString alloc] initWithString:QXText(@"全部") attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:16],NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
|
|
|
|
|
[self.allBtn setAttributedTitle:allAttrNor forState:UIControlStateNormal];
|
|
|
|
|
|
[self.allBtn setAttributedTitle:allAttrSel forState:UIControlStateSelected];
|
|
|
|
|
|
self.allBtn.selected = YES;
|
|
|
|
|
|
self.selectedBtn = self.allBtn;
|
|
|
|
|
|
[self.allBtn addTarget:self action:@selector(typeAction:) forControlEvents:(UIControlEventTouchUpInside)];
|
|
|
|
|
|
[self addSubview:self.allBtn];
|
|
|
|
|
|
[self.allBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.mas_equalTo(16);
|
|
|
|
|
|
make.top.equalTo(self);
|
|
|
|
|
|
make.height.mas_equalTo(40);
|
|
|
|
|
|
make.width.mas_equalTo(50);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
self.chatBtn = [[UIButton alloc] init];
|
|
|
|
|
|
NSAttributedString *chatAttrNor = [[NSAttributedString alloc] initWithString:QXText(@"聊天") attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:14],NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
|
|
|
|
|
NSAttributedString *chatAttrSel = [[NSAttributedString alloc] initWithString:QXText(@"聊天") attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:16],NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
|
|
|
|
|
[self.chatBtn setAttributedTitle:chatAttrNor forState:UIControlStateNormal];
|
|
|
|
|
|
[self.chatBtn setAttributedTitle:chatAttrSel forState:UIControlStateSelected];
|
|
|
|
|
|
[self.chatBtn addTarget:self action:@selector(typeAction:) forControlEvents:(UIControlEventTouchUpInside)];
|
|
|
|
|
|
[self addSubview:self.chatBtn];
|
|
|
|
|
|
[self.chatBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.allBtn.mas_right).offset(5);
|
|
|
|
|
|
make.top.equalTo(self);
|
|
|
|
|
|
make.height.mas_equalTo(40);
|
|
|
|
|
|
make.width.mas_equalTo(50);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
self.giftBtn = [[UIButton alloc] init];
|
|
|
|
|
|
NSAttributedString *giftAttrNor = [[NSAttributedString alloc] initWithString:QXText(@"礼物") attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:14],NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
|
|
|
|
|
NSAttributedString *giftAttrSel = [[NSAttributedString alloc] initWithString:QXText(@"礼物") attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:16],NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
|
|
|
|
|
[self.giftBtn setAttributedTitle:giftAttrNor forState:UIControlStateNormal];
|
|
|
|
|
|
[self.giftBtn setAttributedTitle:giftAttrSel forState:UIControlStateSelected];
|
|
|
|
|
|
[self.giftBtn addTarget:self action:@selector(typeAction:) forControlEvents:(UIControlEventTouchUpInside)];
|
|
|
|
|
|
[self addSubview:self.giftBtn];
|
|
|
|
|
|
[self.giftBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.chatBtn.mas_right).offset(5);
|
|
|
|
|
|
make.top.equalTo(self);
|
|
|
|
|
|
make.height.mas_equalTo(40);
|
|
|
|
|
|
make.width.mas_equalTo(50);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
self.messageCountBtn = [[UIButton alloc] init];;
|
|
|
|
|
|
[self.messageCountBtn setTitleColor:RGB16(0xB265FA) forState:(UIControlStateNormal)];
|
|
|
|
|
|
self.messageCountBtn.backgroundColor = [UIColor whiteColor];
|
|
|
|
|
|
[self.messageCountBtn addRoundedCornersWithRadius:10];
|
|
|
|
|
|
self.messageCountBtn.titleLabel.font = [UIFont systemFontOfSize:12];
|
|
|
|
|
|
[self.messageCountBtn addTarget:self action:@selector(scrollToBottom) forControlEvents:(UIControlEventTouchUpInside)];
|
|
|
|
|
|
[self addSubview:self.messageCountBtn];
|
|
|
|
|
|
self.messageCountBtn.hidden = YES;
|
|
|
|
|
|
[self.messageCountBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.right.mas_equalTo(-40);
|
|
|
|
|
|
make.bottom.equalTo(self);
|
|
|
|
|
|
make.height.mas_equalTo(20);
|
|
|
|
|
|
make.width.mas_equalTo(75);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// self.messageLabel = [[UILabel alloc] init];
|
|
|
|
|
|
// self.messageLabel.textColor = [UIColor whiteColor];
|
|
|
|
|
|
// self.messageLabel.text = @"张三进入了房间";
|
|
|
|
|
|
// self.messageLabel.font = [UIFont systemFontOfSize:12];
|
|
|
|
|
|
// [self addSubview:self.messageLabel];
|
|
|
|
|
|
// [self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
// make.left.mas_equalTo(16);
|
|
|
|
|
|
// make.bottom.equalTo(self).offset(-5);
|
|
|
|
|
|
// make.height.mas_equalTo(20);
|
|
|
|
|
|
// make.right.equalTo(self);
|
|
|
|
|
|
// }];
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
-(void)typeAction:(UIButton*)sender{
|
|
|
|
|
|
self.selectedBtn.selected = !self.selectedBtn.selected;
|
|
|
|
|
|
sender.selected = !sender.selected;
|
|
|
|
|
|
self.selectedBtn = sender;
|
|
|
|
|
|
[self.tableView reloadData];
|
|
|
|
|
|
[self scrollToBottom];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)scrollToBottom{
|
|
|
|
|
|
NSArray *arr;
|
|
|
|
|
|
if (self.selectedBtn == self.chatBtn) {
|
|
|
|
|
|
arr = self.chatArray;
|
|
|
|
|
|
}else if (self.selectedBtn == self.giftBtn) {
|
|
|
|
|
|
arr = self.giftArray;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
arr = self.dataArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (arr.count > 0) {
|
|
|
|
|
|
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:arr.count-1 inSection:0] atScrollPosition:(UITableViewScrollPositionBottom) animated:YES];
|
|
|
|
|
|
}
|
|
|
|
|
|
self.isDragging = NO;
|
|
|
|
|
|
self.messageCount = 0;
|
|
|
|
|
|
self.messageCountBtn.hidden = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)insertNoitce{
|
|
|
|
|
|
QXRoomChatListModel *model = [QXRoomChatListModel new];
|
|
|
|
|
|
model.messageType = QXRoomChatMessageTypeSystem;
|
2025-10-21 10:29:06 +08:00
|
|
|
|
model.text = @"羽声语音严禁未成年人进行直播或打赏,官方将24小时在线巡查。我们提倡绿色直播,直播间严禁出现涉政、涉恐、涉黄、涉赌等违法违规内容,严禁宣传封建迷信、宗教极端思想、出现低俗色情、吸烟酗酒等内容,严禁违反社会主义核心价值观、践踏社会道德底线、诱导打赏、低俗 PK 、买卖金币等行为,请大家共同遵守、监督并及时举报。请勿相信各类刷钻、购买礼包、游戏币及电商贩卖等非官方广告信息,谨防网络诈骗。";
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.dataArray addObject:model];
|
|
|
|
|
|
[self.tableView reloadData];
|
|
|
|
|
|
[self scrollToBottom];
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)insertMessage:(QXRoomChatListModel *)model{
|
2025-10-20 09:43:10 +08:00
|
|
|
|
/// 非礼物插入
|
|
|
|
|
|
if (model.messageType != QXRoomChatMessageTypeGift) {
|
|
|
|
|
|
[self.dataArray addObject:model];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-08 10:49:36 +08:00
|
|
|
|
if (model.messageType == QXRoomChatMessageTypeChat) {
|
|
|
|
|
|
[self.chatArray addObject:model];
|
|
|
|
|
|
}
|
|
|
|
|
|
if (model.messageType == QXRoomChatMessageTypeGift) {
|
|
|
|
|
|
[self.giftArray addObject:model];
|
|
|
|
|
|
}
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// if (self.dataArray.count>maxMessageCount) {
|
|
|
|
|
|
// [self.dataArray removeFirstObject];
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if (self.chatArray.count>maxMessageCount) {
|
|
|
|
|
|
// [self.chatArray removeFirstObject];
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if (self.giftArray.count>maxMessageCount) {
|
|
|
|
|
|
// [self.giftArray removeFirstObject];
|
|
|
|
|
|
// }
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.tableView reloadData];
|
|
|
|
|
|
if (self.isDragging) {
|
|
|
|
|
|
self.messageCount++;
|
|
|
|
|
|
self.messageCountBtn.hidden = NO;
|
|
|
|
|
|
[self.messageCountBtn setTitle:[NSString localizedStringWithFormat:QXText(@"%@条新消息"),[NSString stringWithFormat:@"%ld",self.messageCount]] forState:(UIControlStateNormal)];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
[self scrollToBottom];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)clearMessage{
|
|
|
|
|
|
[self.dataArray removeAllObjects];
|
|
|
|
|
|
[self.giftArray removeAllObjects];
|
|
|
|
|
|
[self.chatArray removeAllObjects];
|
|
|
|
|
|
[self.tableView reloadData];
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)previewUserInfoWithUserId:(NSString *)userId{
|
|
|
|
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(previewUserInfoWithUserId:)]) {
|
|
|
|
|
|
[self.delegate previewUserInfoWithUserId:userId];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
|
|
|
|
|
|
if (self.selectedBtn == self.chatBtn) {
|
|
|
|
|
|
return self.chatArray.count;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (self.selectedBtn == self.giftBtn) {
|
|
|
|
|
|
return self.giftArray.count;
|
|
|
|
|
|
}
|
|
|
|
|
|
return self.dataArray.count;
|
|
|
|
|
|
}
|
|
|
|
|
|
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
|
|
|
|
|
|
QXRoomChatListModel *model;
|
|
|
|
|
|
if (self.selectedBtn == self.chatBtn) {
|
|
|
|
|
|
model = self.chatArray[indexPath.row];
|
|
|
|
|
|
}else if (self.selectedBtn == self.giftBtn) {
|
|
|
|
|
|
model = self.giftArray[indexPath.row];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
model = self.dataArray[indexPath.row];
|
|
|
|
|
|
}
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// model.havBubble = indexPath.row%2;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
if (model.messageType == QXRoomChatMessageTypeChat) {
|
|
|
|
|
|
QXRoomChatListCell *cell = [QXRoomChatListCell cellWithTableView:tableView];
|
|
|
|
|
|
cell.delegate = self;
|
|
|
|
|
|
cell.message = model;
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}else if (model.messageType == QXRoomChatMessageTypeGift) {
|
|
|
|
|
|
QXRoomGiftListCell *cell = [QXRoomGiftListCell cellWithTableView:tableView];
|
|
|
|
|
|
cell.delegate = self;
|
|
|
|
|
|
cell.message = model;
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
QXRoomChatListSystemCell *cell = [QXRoomChatListSystemCell cellWithTableView:tableView];
|
|
|
|
|
|
cell.message = model;
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
|
|
|
|
|
|
if ([cell isKindOfClass:[QXRoomChatListCell class]]) {
|
|
|
|
|
|
QXRoomChatListCell *Listcell = (QXRoomChatListCell *)cell;
|
|
|
|
|
|
[Listcell loadBubble];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
|
|
|
|
|
|
if ([cell isKindOfClass:[QXRoomChatListCell class]]) {
|
|
|
|
|
|
QXRoomChatListCell *Listcell = (QXRoomChatListCell *)cell;
|
|
|
|
|
|
[Listcell.bubbleImageView sd_cancelLatestImageLoad];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
|
|
|
|
|
|
QXRoomChatListModel *model;
|
|
|
|
|
|
if (self.selectedBtn == self.chatBtn) {
|
|
|
|
|
|
model = self.chatArray[indexPath.row];
|
|
|
|
|
|
}else if (self.selectedBtn == self.giftBtn) {
|
|
|
|
|
|
model = self.giftArray[indexPath.row];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
model = self.dataArray[indexPath.row];
|
|
|
|
|
|
}
|
|
|
|
|
|
CGFloat height = 0;
|
|
|
|
|
|
if (model.messageType == QXRoomChatMessageTypeChat) {
|
|
|
|
|
|
height = [model.text heightForFont:[UIFont systemFontOfSize:14] width:ScaleWidth(280)-16-28-6-8-8];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
|
2025-08-08 10:49:36 +08:00
|
|
|
|
if (model.havBubble) {
|
|
|
|
|
|
/// 有气泡
|
|
|
|
|
|
height = 30+14+6+30 + height;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
// 无气泡
|
|
|
|
|
|
height = 30+14+6+12 + height;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}else if (model.messageType == QXRoomChatMessageTypeGift) {
|
|
|
|
|
|
height = [model.text heightForFont:[UIFont systemFontOfSize:14] width:ScaleWidth(280)-16-28-6-8-8];
|
|
|
|
|
|
height = 30+14+6+12 + height;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
height = [model.text heightForFont:[UIFont systemFontOfSize:14] width:ScaleWidth(280)-16-8-8*2] + 12+16+1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return height;
|
|
|
|
|
|
}
|
2025-10-20 09:43:10 +08:00
|
|
|
|
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
|
|
|
|
|
|
QXRoomChatListModel *model;
|
|
|
|
|
|
if (self.selectedBtn == self.chatBtn) {
|
|
|
|
|
|
model = self.chatArray[indexPath.row];
|
|
|
|
|
|
}else if (self.selectedBtn == self.giftBtn) {
|
|
|
|
|
|
model = self.giftArray[indexPath.row];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
model = self.dataArray[indexPath.row];
|
|
|
|
|
|
}
|
|
|
|
|
|
if (model.FromUserInfo.user_id.longValue > 0 && model.messageType == QXRoomChatMessageTypeSystem) {
|
|
|
|
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(previewUserInfoWithUserId:)]) {
|
|
|
|
|
|
[self.delegate previewUserInfoWithUserId:model.FromUserInfo.user_id];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-08 10:49:36 +08:00
|
|
|
|
|
|
|
|
|
|
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
|
|
|
|
|
|
CGFloat height = scrollView.frame.size.height;
|
|
|
|
|
|
CGFloat contentYoffset = scrollView.contentOffset.y;
|
|
|
|
|
|
CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset;
|
|
|
|
|
|
if (distanceFromBottom < height) {
|
|
|
|
|
|
self.isDragging = NO;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
|
|
|
|
|
|
self.isDragging = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
-(UITableView *)tableView{
|
|
|
|
|
|
if (!_tableView) {
|
|
|
|
|
|
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:(UITableViewStylePlain)];
|
|
|
|
|
|
_tableView.dataSource = self;
|
|
|
|
|
|
_tableView.delegate = self;
|
|
|
|
|
|
_tableView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
_tableView.tableFooterView = [UIView new];
|
|
|
|
|
|
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
|
|
|
|
|
_tableView.showsHorizontalScrollIndicator = NO;
|
|
|
|
|
|
_tableView.showsVerticalScrollIndicator = NO;
|
|
|
|
|
|
if (@available(iOS 15.0, *)) {
|
|
|
|
|
|
_tableView.sectionHeaderTopPadding = 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Fallback on earlier versions
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return _tableView;
|
|
|
|
|
|
}
|
|
|
|
|
|
-(NSMutableArray *)dataArray{
|
|
|
|
|
|
if (!_dataArray) {
|
|
|
|
|
|
_dataArray = [NSMutableArray array];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _dataArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
-(NSMutableArray *)giftArray{
|
|
|
|
|
|
if (!_giftArray) {
|
|
|
|
|
|
_giftArray =[ NSMutableArray array];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _giftArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
-(NSMutableArray *)chatArray{
|
|
|
|
|
|
if (!_chatArray) {
|
|
|
|
|
|
_chatArray = [NSMutableArray array];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _chatArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation QXRoomChatListCell
|
|
|
|
|
|
|
|
|
|
|
|
+(instancetype)cellWithTableView:(UITableView *)tableView{
|
|
|
|
|
|
static NSString* cellId = @"QXRoomChatListCell";
|
|
|
|
|
|
QXRoomChatListCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
|
|
|
|
|
|
if (!cell) {
|
|
|
|
|
|
cell = [[QXRoomChatListCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:cellId];
|
|
|
|
|
|
}
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
|
|
|
|
|
|
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
|
|
|
|
|
self.contentView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
|
|
[self initSubviews];
|
|
|
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)headerAction{
|
|
|
|
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(previewUserInfoWithUserId:)]) {
|
|
|
|
|
|
[self.delegate previewUserInfoWithUserId:self.message.FromUserInfo.user_id];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)setMessage:(QXRoomChatListModel *)message{
|
|
|
|
|
|
_message = message;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// self.titleLabel.text = message.text;
|
|
|
|
|
|
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:message.text];
|
|
|
|
|
|
if ([message.FromUserInfo.nickname isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:[message.text rangeOfString:message.FromUserInfo.nickname]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([message.ToUserInfo.nickname isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:[message.text rangeOfString:message.ToUserInfo.nickname]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([message.GiftInfo.gift_name isExist]) {
|
|
|
|
|
|
NSArray *arr = [message.GiftInfo.gift_name componentsSeparatedByString:@","];
|
|
|
|
|
|
for (NSString*gift_name in arr) {
|
|
|
|
|
|
NSArray<NSValue *> *occurrences = findAllOccurrencesOfString(message.text, gift_name);
|
|
|
|
|
|
for (NSValue *rangeValue in occurrences) {
|
|
|
|
|
|
NSRange range = [rangeValue rangeValue];
|
|
|
|
|
|
[attr yy_setColor:messageGiftColor range:range];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (message.GiftInfos.count > 0) {
|
|
|
|
|
|
for (QXGiftModel*gift in message.GiftInfos) {
|
|
|
|
|
|
if ([gift.gift_name isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageGiftColor range:[message.text rangeOfString:gift.gift_name]];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (message.ToUserInfos.count > 0) {
|
|
|
|
|
|
for (int i = 0; i < message.ToUserInfos.count; i++) {
|
|
|
|
|
|
QXUserHomeModel*md = message.ToUserInfos[i];
|
|
|
|
|
|
NSArray<NSValue *> *occurrences = findAllOccurrencesOfString(message.text, md.nickname);
|
|
|
|
|
|
for (NSValue *rangeValue in occurrences) {
|
|
|
|
|
|
NSRange range = [rangeValue rangeValue];
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:range];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
self.titleLabel.attributedText = attr;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
self.nameLabel.text = message.FromUserInfo.nickname;
|
|
|
|
|
|
[self.headerImageView sd_setImageWithURL:[NSURL URLWithString:message.FromUserInfo.avatar]];
|
|
|
|
|
|
self.iconBgView.hidden = YES;
|
|
|
|
|
|
for (int i = 0;i < message.FromUserInfo.icon.count;i++) {
|
|
|
|
|
|
if (i < 3) {
|
|
|
|
|
|
self.iconBgView.hidden = NO;
|
|
|
|
|
|
UIImageView *iconImageView = self.iconViewArray[i];
|
|
|
|
|
|
iconImageView.hidden = NO;
|
|
|
|
|
|
[iconImageView sd_setImageWithURL:[NSURL URLWithString:message.FromUserInfo.icon[i]]];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
self.iconBgView.hidden = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)initSubviews{
|
|
|
|
|
|
self.headerImageView = [[UIImageView alloc] init];
|
|
|
|
|
|
self.headerImageView.contentMode = UIViewContentModeScaleAspectFill;
|
|
|
|
|
|
self.headerImageView.backgroundColor = [UIColor whiteColor];
|
|
|
|
|
|
[self.headerImageView addRoundedCornersWithRadius:14];
|
|
|
|
|
|
[self.contentView addSubview:self.headerImageView];
|
|
|
|
|
|
|
|
|
|
|
|
[self.headerImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.mas_equalTo(16);
|
|
|
|
|
|
make.top.mas_equalTo(2);
|
|
|
|
|
|
make.size.mas_equalTo(CGSizeMake(28, 28));
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
UIButton *headerBtn = [[UIButton alloc] init];
|
|
|
|
|
|
[headerBtn addTarget:self action:@selector(headerAction) forControlEvents:(UIControlEventTouchUpInside)];
|
|
|
|
|
|
[self.contentView addSubview:headerBtn];
|
|
|
|
|
|
[headerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.top.equalTo(self.headerImageView).offset(-2);
|
|
|
|
|
|
make.bottom.right.equalTo(self.headerImageView).offset(2);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
self.nameLabel = [[UILabel alloc] init];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
self.nameLabel.textColor = RGB16(0xCCA882);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
self.nameLabel.font = [UIFont systemFontOfSize:12];
|
|
|
|
|
|
[self.contentView addSubview:self.nameLabel];
|
|
|
|
|
|
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.top.equalTo(self.contentView);
|
|
|
|
|
|
make.left.equalTo(self.headerImageView.mas_right).offset(6);
|
|
|
|
|
|
make.right.equalTo(self.contentView).offset(-6);
|
|
|
|
|
|
make.height.mas_equalTo(14);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.titleLabel = [[UILabel alloc] init];
|
|
|
|
|
|
self.titleLabel.textColor = [UIColor whiteColor];
|
|
|
|
|
|
self.titleLabel.font = [UIFont systemFontOfSize:14];
|
|
|
|
|
|
self.titleLabel.numberOfLines = 0;
|
|
|
|
|
|
[self.contentView addSubview:self.titleLabel];
|
|
|
|
|
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.nameLabel).offset(8);
|
|
|
|
|
|
make.top.equalTo(self.headerImageView.mas_bottom).offset(14);
|
|
|
|
|
|
make.right.mas_lessThanOrEqualTo(-8);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.nameLabel.text = @"张三站撒旦撒大萨达撒";
|
|
|
|
|
|
|
|
|
|
|
|
self.bubbleImageView = [[UIImageView alloc] init];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// UIImage * image = [UIImage imageWithColor:RGB16A(0x000000, 0.4)];
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.bubbleImageView addRoundedCornersWithRadius:6];
|
|
|
|
|
|
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// UIImage *image = [UIImage imageWithContentsOfFile:path];
|
|
|
|
|
|
// image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(20, 40, 20 , 40) resizingMode:(UIImageResizingModeStretch)];
|
|
|
|
|
|
// self.bubbleImageView.image = image;
|
|
|
|
|
|
self.bubbleImageView.backgroundColor = RGB16A(0xFFFFFF, 0.2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-08 10:49:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[self.contentView addSubview:self.bubbleImageView];
|
|
|
|
|
|
[self.bubbleImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.titleLabel).offset(-8);
|
|
|
|
|
|
make.top.equalTo(self.titleLabel).offset(-6);
|
|
|
|
|
|
make.bottom.equalTo(self.titleLabel).offset(6);
|
|
|
|
|
|
make.right.equalTo(self.titleLabel).offset(8);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.left.equalTo(self.titleLabel).offset(-55);
|
|
|
|
|
|
// make.top.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.bottom.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.right.equalTo(self.titleLabel).offset(55);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
[self.contentView bringSubviewToFront:self.titleLabel];
|
|
|
|
|
|
|
|
|
|
|
|
self.iconBgView = [[UIView alloc] init];
|
|
|
|
|
|
[self.contentView addSubview:self.iconBgView];
|
|
|
|
|
|
[self.iconBgView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.nameLabel);
|
|
|
|
|
|
make.right.equalTo(self.contentView);
|
|
|
|
|
|
make.height.mas_equalTo(16);
|
|
|
|
|
|
make.top.equalTo(self.nameLabel.mas_bottom).offset(2);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
2025-10-20 09:43:10 +08:00
|
|
|
|
CGFloat iconWidth = UserIconWidth;
|
|
|
|
|
|
CGFloat iconHeight = UserIconHeight;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
CGFloat margin = 6;
|
|
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
|
UIImageView *iconImageView = [[UIImageView alloc] init];
|
|
|
|
|
|
iconImageView.hidden = YES;
|
|
|
|
|
|
[self.iconBgView addSubview:iconImageView];
|
|
|
|
|
|
[iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.mas_equalTo(i*(iconWidth+margin));
|
|
|
|
|
|
make.width.mas_equalTo(iconWidth);
|
|
|
|
|
|
make.height.mas_equalTo(iconHeight);
|
|
|
|
|
|
make.centerY.equalTo(self.iconBgView);
|
|
|
|
|
|
}];
|
|
|
|
|
|
[self.iconViewArray addObject:iconImageView];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)loadBubble{
|
|
|
|
|
|
if (!self.message.havBubble) {
|
|
|
|
|
|
[self.bubbleImageView sd_cancelLatestImageLoad];
|
|
|
|
|
|
self.bubbleImageView.image = nil;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
self.bubbleImageView.backgroundColor = RGB16A(0xFFFFFF, 0.2);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.bubbleImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.titleLabel).offset(-8);
|
|
|
|
|
|
make.top.equalTo(self.titleLabel).offset(-6);
|
|
|
|
|
|
make.bottom.equalTo(self.titleLabel).offset(6);
|
|
|
|
|
|
make.right.equalTo(self.titleLabel).offset(8);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.left.equalTo(self.titleLabel).offset(-55);
|
|
|
|
|
|
// make.top.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.bottom.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.right.equalTo(self.titleLabel).offset(55);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
NSString *path = [[NSBundle mainBundle] pathForResource:@"气泡" ofType:@"webp"];
|
|
|
|
|
|
[self.bubbleImageView sd_setImageWithURL:[NSURL fileURLWithPath:path] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
|
|
|
|
|
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(20, 30, 20 , 30) resizingMode:(UIImageResizingModeStretch)];
|
|
|
|
|
|
self.bubbleImageView.image = image;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}];
|
|
|
|
|
|
CGFloat height = [self.message.text heightForFont:[UIFont systemFontOfSize:14] width:ScaleWidth(280)-16-28-6-8-8];
|
|
|
|
|
|
self.bubbleImageView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
[self.bubbleImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.titleLabel).offset(-48);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.height.mas_equalTo(height+12);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
make.height.mas_equalTo(height+60);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.width.mas_equalTo(ScaleWidth(280)-16-28-6-8-8);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
make.centerY.equalTo(self.titleLabel);
|
|
|
|
|
|
make.right.equalTo(self.titleLabel).offset(48);
|
|
|
|
|
|
}];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
-(NSMutableArray *)iconViewArray{
|
|
|
|
|
|
if (!_iconViewArray) {
|
|
|
|
|
|
_iconViewArray = [NSMutableArray array];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _iconViewArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation QXRoomGiftListCell
|
|
|
|
|
|
|
|
|
|
|
|
+(instancetype)cellWithTableView:(UITableView *)tableView{
|
|
|
|
|
|
static NSString* cellId = @"QXRoomGiftListCell";
|
|
|
|
|
|
QXRoomGiftListCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
|
|
|
|
|
|
if (!cell) {
|
|
|
|
|
|
cell = [[QXRoomGiftListCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:cellId];
|
|
|
|
|
|
}
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
|
|
|
|
|
|
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
|
|
|
|
|
self.contentView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
|
|
[self initSubviews];
|
|
|
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)headerAction{
|
|
|
|
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(previewUserInfoWithUserId:)]) {
|
|
|
|
|
|
[self.delegate previewUserInfoWithUserId:self.message.FromUserInfo.user_id];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)setMessage:(QXRoomChatListModel *)message{
|
|
|
|
|
|
_message = message;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// self.titleLabel.text = message.text;
|
|
|
|
|
|
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:message.text];
|
|
|
|
|
|
if ([message.FromUserInfo.nickname isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:[message.text rangeOfString:message.FromUserInfo.nickname]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([message.ToUserInfo.nickname isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:[message.text rangeOfString:message.ToUserInfo.nickname]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([message.GiftInfo.gift_name isExist]) {
|
|
|
|
|
|
NSArray *arr = [message.GiftInfo.gift_name componentsSeparatedByString:@","];
|
|
|
|
|
|
for (NSString*gift_name in arr) {
|
|
|
|
|
|
NSArray<NSValue *> *occurrences = findAllOccurrencesOfString(message.text, gift_name);
|
|
|
|
|
|
for (NSValue *rangeValue in occurrences) {
|
|
|
|
|
|
NSRange range = [rangeValue rangeValue];
|
|
|
|
|
|
[attr yy_setColor:messageGiftColor range:range];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (message.GiftInfos.count > 0) {
|
|
|
|
|
|
for (QXGiftModel*gift in message.GiftInfos) {
|
|
|
|
|
|
if ([gift.gift_name isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageGiftColor range:[message.text rangeOfString:gift.gift_name]];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (message.ToUserInfos.count > 0) {
|
|
|
|
|
|
for (int i = 0; i < message.ToUserInfos.count; i++) {
|
|
|
|
|
|
QXUserHomeModel*md = message.ToUserInfos[i];
|
|
|
|
|
|
NSArray<NSValue *> *occurrences = findAllOccurrencesOfString(message.text, md.nickname);
|
|
|
|
|
|
for (NSValue *rangeValue in occurrences) {
|
|
|
|
|
|
NSRange range = [rangeValue rangeValue];
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:range];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
self.titleLabel.attributedText = attr;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
self.nameLabel.text = message.FromUserInfo.nickname;
|
|
|
|
|
|
[self.headerImageView sd_setImageWithURL:[NSURL URLWithString:message.FromUserInfo.avatar]];
|
|
|
|
|
|
self.iconBgView.hidden = YES;
|
|
|
|
|
|
for (int i = 0;i < message.FromUserInfo.icon.count;i++) {
|
|
|
|
|
|
if (i < 3) {
|
|
|
|
|
|
self.iconBgView.hidden = NO;
|
|
|
|
|
|
UIImageView *iconImageView = self.iconViewArray[i];
|
|
|
|
|
|
iconImageView.hidden = NO;
|
|
|
|
|
|
[iconImageView sd_setImageWithURL:[NSURL URLWithString:message.FromUserInfo.icon[i]]];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
self.iconBgView.hidden = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)initSubviews{
|
|
|
|
|
|
self.headerImageView = [[UIImageView alloc] init];
|
|
|
|
|
|
self.headerImageView.contentMode = UIViewContentModeScaleAspectFill;
|
|
|
|
|
|
self.headerImageView.backgroundColor = [UIColor whiteColor];
|
|
|
|
|
|
[self.headerImageView addRoundedCornersWithRadius:14];
|
|
|
|
|
|
[self.contentView addSubview:self.headerImageView];
|
|
|
|
|
|
|
|
|
|
|
|
[self.headerImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.mas_equalTo(16);
|
|
|
|
|
|
make.top.mas_equalTo(2);
|
|
|
|
|
|
make.size.mas_equalTo(CGSizeMake(28, 28));
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
UIButton *headerBtn = [[UIButton alloc] init];
|
|
|
|
|
|
[headerBtn addTarget:self action:@selector(headerAction) forControlEvents:(UIControlEventTouchUpInside)];
|
|
|
|
|
|
[self.contentView addSubview:headerBtn];
|
|
|
|
|
|
[headerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.top.equalTo(self.headerImageView).offset(-2);
|
|
|
|
|
|
make.bottom.right.equalTo(self.headerImageView).offset(2);
|
|
|
|
|
|
}];
|
|
|
|
|
|
self.nameLabel = [[UILabel alloc] init];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
self.nameLabel.textColor = RGB16(0xCCA882);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
self.nameLabel.font = [UIFont systemFontOfSize:12];
|
|
|
|
|
|
[self.contentView addSubview:self.nameLabel];
|
|
|
|
|
|
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.top.equalTo(self.contentView);
|
|
|
|
|
|
make.left.equalTo(self.headerImageView.mas_right).offset(6);
|
|
|
|
|
|
make.right.equalTo(self.contentView).offset(-6);
|
|
|
|
|
|
make.height.mas_equalTo(14);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.titleLabel = [[UILabel alloc] init];
|
|
|
|
|
|
self.titleLabel.textColor = [UIColor whiteColor];
|
|
|
|
|
|
self.titleLabel.font = [UIFont systemFontOfSize:14];
|
|
|
|
|
|
self.titleLabel.numberOfLines = 0;
|
|
|
|
|
|
[self.contentView addSubview:self.titleLabel];
|
|
|
|
|
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.nameLabel).offset(8);
|
|
|
|
|
|
make.top.equalTo(self.headerImageView.mas_bottom).offset(14);
|
|
|
|
|
|
make.right.mas_lessThanOrEqualTo(-8);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.nameLabel.text = @"张三站撒旦撒大萨达撒";
|
|
|
|
|
|
|
|
|
|
|
|
self.bubbleImageView = [[UIImageView alloc] init];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// UIImage * image = [UIImage imageWithColor:RGB16A(0x000000, 0.4)];
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.bubbleImageView addRoundedCornersWithRadius:6];
|
|
|
|
|
|
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// UIImage *image = [UIImage imageWithContentsOfFile:path];
|
|
|
|
|
|
// image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(20, 40, 20 , 40) resizingMode:(UIImageResizingModeStretch)];
|
|
|
|
|
|
// self.bubbleImageView.image = image;
|
|
|
|
|
|
self.bubbleImageView.backgroundColor = RGB16A(0xFFFFFF, 0.2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-08 10:49:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[self.contentView addSubview:self.bubbleImageView];
|
|
|
|
|
|
[self.bubbleImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.titleLabel).offset(-8);
|
|
|
|
|
|
make.top.equalTo(self.titleLabel).offset(-6);
|
|
|
|
|
|
make.bottom.equalTo(self.titleLabel).offset(6);
|
|
|
|
|
|
make.right.equalTo(self.titleLabel).offset(8);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.left.equalTo(self.titleLabel).offset(-55);
|
|
|
|
|
|
// make.top.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.bottom.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.right.equalTo(self.titleLabel).offset(55);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
[self.contentView bringSubviewToFront:self.titleLabel];
|
|
|
|
|
|
|
|
|
|
|
|
self.iconBgView = [[UIView alloc] init];
|
|
|
|
|
|
[self.contentView addSubview:self.iconBgView];
|
|
|
|
|
|
[self.iconBgView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.nameLabel);
|
|
|
|
|
|
make.right.equalTo(self.contentView);
|
|
|
|
|
|
make.height.mas_equalTo(16);
|
|
|
|
|
|
make.top.equalTo(self.nameLabel.mas_bottom).offset(2);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
2025-10-20 09:43:10 +08:00
|
|
|
|
CGFloat iconWidth = UserIconWidth;
|
|
|
|
|
|
CGFloat iconHeight = UserIconHeight;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
CGFloat margin = 6;
|
|
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
|
UIImageView *iconImageView = [[UIImageView alloc] init];
|
|
|
|
|
|
iconImageView.hidden = YES;
|
|
|
|
|
|
[self.iconBgView addSubview:iconImageView];
|
|
|
|
|
|
[iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.mas_equalTo(i*(iconWidth+margin));
|
|
|
|
|
|
make.width.mas_equalTo(iconWidth);
|
|
|
|
|
|
make.height.mas_equalTo(iconHeight);
|
|
|
|
|
|
make.centerY.equalTo(self.iconBgView);
|
|
|
|
|
|
}];
|
|
|
|
|
|
[self.iconViewArray addObject:iconImageView];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-(void)loadBubble{
|
|
|
|
|
|
if (!self.message.havBubble) {
|
|
|
|
|
|
[self.bubbleImageView sd_cancelLatestImageLoad];
|
|
|
|
|
|
self.bubbleImageView.image = nil;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
self.bubbleImageView.backgroundColor = RGB16A(0xFFFFFF, 0.2);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.bubbleImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.titleLabel).offset(-8);
|
|
|
|
|
|
make.top.equalTo(self.titleLabel).offset(-6);
|
|
|
|
|
|
make.bottom.equalTo(self.titleLabel).offset(6);
|
|
|
|
|
|
make.right.equalTo(self.titleLabel).offset(8);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.left.equalTo(self.titleLabel).offset(-55);
|
|
|
|
|
|
// make.top.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.bottom.equalTo(self.titleLabel).offset(0);
|
|
|
|
|
|
// make.right.equalTo(self.titleLabel).offset(55);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}];
|
|
|
|
|
|
}else{
|
|
|
|
|
|
NSString *path = [[NSBundle mainBundle] pathForResource:@"气泡" ofType:@"webp"];
|
|
|
|
|
|
[self.bubbleImageView sd_setImageWithURL:[NSURL fileURLWithPath:path] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
|
|
|
|
|
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(20, 30, 20 , 30) resizingMode:(UIImageResizingModeStretch)];
|
|
|
|
|
|
self.bubbleImageView.image = image;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}];
|
|
|
|
|
|
CGFloat height = [self.message.text heightForFont:[UIFont systemFontOfSize:14] width:ScaleWidth(280)-16-28-6-8-8];
|
|
|
|
|
|
self.bubbleImageView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
[self.bubbleImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.titleLabel).offset(-48);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.height.mas_equalTo(height+12);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
make.height.mas_equalTo(height+60);
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// make.width.mas_equalTo(ScaleWidth(280)-16-28-6-8-8);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
make.centerY.equalTo(self.titleLabel);
|
|
|
|
|
|
make.right.equalTo(self.titleLabel).offset(48);
|
|
|
|
|
|
}];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
-(NSMutableArray *)iconViewArray{
|
|
|
|
|
|
if (!_iconViewArray) {
|
|
|
|
|
|
_iconViewArray = [NSMutableArray array];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _iconViewArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation QXRoomChatListSystemCell
|
|
|
|
|
|
|
|
|
|
|
|
+(instancetype)cellWithTableView:(UITableView *)tableView{
|
|
|
|
|
|
static NSString* cellId = @"QXRoomChatListSystemCell";
|
|
|
|
|
|
QXRoomChatListSystemCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
|
|
|
|
|
|
if (!cell) {
|
|
|
|
|
|
cell = [[QXRoomChatListSystemCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:cellId];
|
|
|
|
|
|
}
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
|
|
|
|
|
|
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
|
|
|
|
|
self.contentView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
|
|
[self initSubviews];
|
|
|
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)setMessage:(QXRoomChatListModel *)message{
|
|
|
|
|
|
_message = message;
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:message.text];
|
|
|
|
|
|
// if ([message.FromUserInfo.nickname isExist]) {
|
|
|
|
|
|
// [attr yy_setColor:RGB16(0xFFE309) range:[message.text rangeOfString:message.FromUserInfo.nickname]];
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if ([message.ToUserInfo.nickname isExist]) {
|
|
|
|
|
|
// [attr yy_setColor:RGB16(0xFFE309) range:[message.text rangeOfString:message.ToUserInfo.nickname]];
|
|
|
|
|
|
// }
|
|
|
|
|
|
//// self.titleLabel.text = message.text;
|
|
|
|
|
|
// self.titleLabel.attributedText = attr;
|
|
|
|
|
|
|
|
|
|
|
|
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:message.text];
|
|
|
|
|
|
if ([message.FromUserInfo.nickname isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:[message.text rangeOfString:message.FromUserInfo.nickname]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([message.ToUserInfo.nickname isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:[message.text rangeOfString:message.ToUserInfo.nickname]];
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([message.GiftInfo.gift_name isExist]) {
|
|
|
|
|
|
NSArray *arr = [message.GiftInfo.gift_name componentsSeparatedByString:@","];
|
|
|
|
|
|
for (NSString*gift_name in arr) {
|
|
|
|
|
|
NSArray<NSValue *> *occurrences = findAllOccurrencesOfString(message.text, gift_name);
|
|
|
|
|
|
for (NSValue *rangeValue in occurrences) {
|
|
|
|
|
|
NSRange range = [rangeValue rangeValue];
|
|
|
|
|
|
[attr yy_setColor:messageGiftColor range:range];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (message.GiftInfos.count > 0) {
|
|
|
|
|
|
for (QXGiftModel*gift in message.GiftInfos) {
|
|
|
|
|
|
if ([gift.gift_name isExist]) {
|
|
|
|
|
|
[attr yy_setColor:messageGiftColor range:[message.text rangeOfString:gift.gift_name]];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (message.ToUserInfos.count > 0) {
|
|
|
|
|
|
for (int i = 0; i < message.ToUserInfos.count; i++) {
|
|
|
|
|
|
QXUserHomeModel*md = message.ToUserInfos[i];
|
|
|
|
|
|
NSArray<NSValue *> *occurrences = findAllOccurrencesOfString(message.text, md.nickname);
|
|
|
|
|
|
for (NSValue *rangeValue in occurrences) {
|
|
|
|
|
|
NSRange range = [rangeValue rangeValue];
|
|
|
|
|
|
[attr yy_setColor:messageNameColor range:range];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
self.titleLabel.attributedText = attr;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)initSubviews{
|
|
|
|
|
|
self.bgView = [[UIView alloc] init];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
self.bgView.backgroundColor = RGB16A(0xFFFFFF, 0.2);
|
2025-08-08 10:49:36 +08:00
|
|
|
|
[self.bgView addRoundedCornersWithRadius:6];
|
|
|
|
|
|
[self.contentView addSubview:self.bgView];
|
|
|
|
|
|
[self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.mas_equalTo(16);
|
|
|
|
|
|
make.right.mas_lessThanOrEqualTo(-8);
|
|
|
|
|
|
make.top.mas_equalTo(6);
|
|
|
|
|
|
make.bottom.mas_equalTo(-6);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
self.titleLabel = [[UILabel alloc] init];
|
2025-10-20 09:43:10 +08:00
|
|
|
|
// self.titleLabel.textColor = RGB16(0XD1A9FE);
|
|
|
|
|
|
self.titleLabel.textColor = UIColor.whiteColor;
|
2025-08-08 10:49:36 +08:00
|
|
|
|
self.titleLabel.font = [UIFont systemFontOfSize:14];
|
|
|
|
|
|
self.titleLabel.numberOfLines = 0;
|
|
|
|
|
|
[self.bgView addSubview:self.titleLabel];
|
|
|
|
|
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.bgView).offset(8);
|
|
|
|
|
|
make.top.mas_equalTo(8);
|
|
|
|
|
|
make.bottom.mas_equalTo(-8);
|
|
|
|
|
|
make.right.mas_equalTo(-8);
|
|
|
|
|
|
}];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation QXRoomChatListModel
|
|
|
|
|
|
|
|
|
|
|
|
+(NSDictionary<NSString *,id> *)modelContainerPropertyGenericClass{
|
2025-10-20 09:43:10 +08:00
|
|
|
|
return @{
|
|
|
|
|
|
@"GiftInfo" : @"QXGiftModel",
|
|
|
|
|
|
@"GiftInfos" : @"QXGiftModel",
|
2025-08-08 10:49:36 +08:00
|
|
|
|
@"FromUserInfo":@"QXUserHomeModel",
|
|
|
|
|
|
@"nextInfo":@"QXSongListModel",
|
2025-10-20 09:43:10 +08:00
|
|
|
|
@"songInfo":@"QXSongListModel",
|
|
|
|
|
|
@"ToUserInfo":@"QXUserHomeModel",
|
|
|
|
|
|
@"ToUserInfos":@"QXUserHomeModel",
|
|
|
|
|
|
@"friend_user":@"QXRoomFriendRelationModel"
|
2025-08-08 10:49:36 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-20 20:05:55 +08:00
|
|
|
|
- (BOOL)isSameGiftFromSameSender:(QXRoomChatListModel *)otherGift {
|
|
|
|
|
|
if (!otherGift) return NO;
|
|
|
|
|
|
|
|
|
|
|
|
return [self.GiftInfo.gift_id isEqualToString:otherGift.GiftInfo.gift_id] &&
|
|
|
|
|
|
[self.FromUserInfo.nickname isEqualToString:otherGift.FromUserInfo.nickname] &&
|
|
|
|
|
|
[self.ToUserInfo.nickname isEqualToString:otherGift.ToUserInfo.nickname];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (instancetype)copy {
|
|
|
|
|
|
QXRoomChatListModel *copy = [[QXRoomChatListModel alloc] init];
|
|
|
|
|
|
QXGiftModel *gift = [[QXGiftModel alloc] init];
|
|
|
|
|
|
gift.gift_id = self.GiftInfo.gift_id;
|
|
|
|
|
|
gift.base_image = self.GiftInfo.base_image;
|
|
|
|
|
|
gift.gift_name = self.GiftInfo.gift_name;
|
|
|
|
|
|
copy.GiftInfo = gift;
|
|
|
|
|
|
QXUserHomeModel *fromUser = [[QXUserHomeModel alloc] init];
|
|
|
|
|
|
fromUser.nickname = self.FromUserInfo.nickname;
|
|
|
|
|
|
fromUser.avatar = self.FromUserInfo.avatar;
|
|
|
|
|
|
copy.FromUserInfo = fromUser;
|
|
|
|
|
|
QXUserHomeModel *toUser = [[QXUserHomeModel alloc] init];
|
|
|
|
|
|
toUser.nickname = self.FromUserInfo.nickname;
|
|
|
|
|
|
toUser.avatar = self.FromUserInfo.avatar;
|
|
|
|
|
|
copy.ToUserInfo = toUser;
|
|
|
|
|
|
copy.gift_num = self.gift_num;
|
|
|
|
|
|
return copy;
|
|
|
|
|
|
}
|
2025-08-08 10:49:36 +08:00
|
|
|
|
@end
|