| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- //
- // TUIMessageCell_Minimalist.m
- // TXIMSDK_TUIKit_iOS
- //
- // Created by annidyfeng on 2019/5/22.
- // Copyright © 2023 Tencent. All rights reserved.
- //
- #import "TUIMessageCell_Minimalist.h"
- #import <TIMCommon/TIMCommonModel.h>
- #import <TIMCommon/TIMDefine.h>
- #import "NSString+TUIEmoji.h"
- #import <TUICore/TUICore.h>
- #import <TIMCommon/TUIRelationUserModel.h>
- @interface TUIMessageCell_Minimalist ()
- @property(nonatomic, assign) TUIMessageStatus status;
- @property(nonatomic, strong) NSMutableArray *animationImages;
- @end
- @implementation TUIMessageCell_Minimalist
- - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
- self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
- if (self) {
- _replyLineView = [[UIImageView alloc] initWithFrame:CGRectZero];
- _replyLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- [self.contentView addSubview:_replyLineView];
- [self.messageModifyRepliesButton.titleLabel setFont:[UIFont systemFontOfSize:12]];
- if(isRTL()) {
- self.messageModifyRepliesButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
- }
- else {
- self.messageModifyRepliesButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
- }
- [self.messageModifyRepliesButton setTitleColor:RGBA(0, 95, 255, 1) forState:UIControlStateNormal];
- _msgStatusView = [[UIImageView alloc] initWithFrame:CGRectZero];
- _msgStatusView.contentMode = UIViewContentModeScaleAspectFit;
- _msgStatusView.layer.zPosition = FLT_MAX;
- UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onJumpToMessageInfoPage)];
- [_msgStatusView addGestureRecognizer:tap2];
- _msgStatusView.userInteractionEnabled = YES;
- [self.container addSubview:_msgStatusView];
- _msgTimeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
- _msgTimeLabel.textColor = RGB(102, 102, 102);
- _msgTimeLabel.font = [UIFont systemFontOfSize:12];
- _msgTimeLabel.rtlAlignment = TUITextRTLAlignmentTrailing;
- _msgTimeLabel.layer.zPosition = FLT_MAX;
- [self.container addSubview:_msgTimeLabel];
- self.animationImages = [NSMutableArray array];
- for (int i = 1; i <= 45; ++i) {
- NSString *imageName = [NSString stringWithFormat:@"msg_status_sending_%d", i];
- NSString *imagePath = TUIChatImagePath_Minimalist(imageName);
- UIImage *image = [[TUIImageCache sharedInstance] getResourceFromCache:imagePath];
- [self.animationImages addObject:image];
- }
- _replyAvatarImageViews = [NSMutableArray array];
- }
- return self;
- }
- - (void)prepareReactTagUI:(UIView *)containerView {
- NSDictionary *param = @{TUICore_TUIChatExtension_ChatMessageReactPreview_Delegate: self};
- [TUICore raiseExtension:TUICore_TUIChatExtension_ChatMessageReactPreview_MinimalistExtensionID parentView:containerView param:param];
- }
- - (void)onJumpToMessageInfoPage {
- if (self.delegate && [self.delegate respondsToSelector:@selector(onJumpToMessageInfoPage:selectCell:)]) {
- [self.delegate onJumpToMessageInfoPage:self.messageData selectCell:self];
- }
- }
- + (BOOL)requiresConstraintBasedLayout {
- return YES;
- }
- // this is Apple's recommended place for adding/updating constraints
- - (void)updateConstraints {
-
- [super updateConstraints];
- TUIMessageCellLayout *cellLayout = self.messageData.cellLayout;
- BOOL isInComing = (self.messageData.direction == MsgDirectionIncoming);
- [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (isInComing) {
- make.leading.mas_equalTo(self.container.mas_leading).mas_offset(7);
- } else {
- make.trailing.mas_equalTo(self.container.mas_trailing);
- }
- if (self.messageData.showName) {
- make.width.mas_greaterThanOrEqualTo(20);
- make.height.mas_greaterThanOrEqualTo(20);
- } else {
- make.height.mas_equalTo(0);
- }
- make.top.mas_equalTo(self.avatarView.mas_top);
- }];
- [self.selectedIcon mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(3);
- make.centerY.mas_equalTo(self.container.mas_centerY);
- if (self.messageData.showCheckBox) {
- make.width.mas_equalTo(20);
- make.height.mas_equalTo(20);
- } else {
- make.size.mas_equalTo(CGSizeZero);
- }
- }];
- [self.timeLabel sizeToFit];
- [self.timeLabel mas_updateConstraints:^(MASConstraintMaker *make) {
- if (self.messageData.showMessageTime) {
- make.width.mas_equalTo(self.timeLabel.frame.size.width);
- make.height.mas_equalTo(self.timeLabel.frame.size.height);
- } else {
- make.width.mas_equalTo(0);
- make.height.mas_equalTo(0);
- }
- }];
- CGSize csize = [self.class getContentSize:self.messageData];
- CGFloat contentWidth = csize.width;
- CGFloat contentHeight = csize.height;
- if (self.messageData.direction == MsgDirectionIncoming) {
- self.avatarView.hidden = !self.messageData.showAvatar;
- [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (self.messageData.showCheckBox) {
- make.leading.mas_equalTo(self.selectedIcon.mas_trailing).mas_offset(cellLayout.avatarInsets.left);
- } else {
- make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(cellLayout.avatarInsets.left);
- }
- make.top.mas_equalTo(cellLayout.avatarInsets.top);
- make.size.mas_equalTo(cellLayout.avatarSize);
- }];
- [self.container mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(cellLayout.messageInsets.left);
- make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(cellLayout.messageInsets.top);
- make.width.mas_equalTo(contentWidth);
- make.height.mas_equalTo(contentHeight);
- }];
- CGRect indicatorFrame = self.indicator.frame;
- [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.leading.mas_equalTo(self.container.mas_trailing).mas_offset(8);
- make.centerY.mas_equalTo(self.container.mas_centerY);
- make.size.mas_equalTo(indicatorFrame.size);
- }];
- self.retryView.frame = self.indicator.frame;
- self.readReceiptLabel.hidden = YES;
- } else {
- if (!self.messageData.showAvatar) {
- cellLayout.avatarSize = CGSizeZero;
- }
- [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-cellLayout.avatarInsets.right);
- make.top.mas_equalTo(cellLayout.avatarInsets.top);
- make.size.mas_equalTo(cellLayout.avatarSize);
- }];
- [self.container mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.trailing.mas_equalTo(self.avatarView.mas_leading).mas_offset(-cellLayout.messageInsets.right);
- make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(cellLayout.messageInsets.top);
- make.width.mas_equalTo(contentWidth);
- make.height.mas_equalTo(contentHeight);
- }];
- CGRect indicatorFrame = self.indicator.frame;
- [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8);
- make.centerY.mas_equalTo(self.container.mas_centerY);
- make.size.mas_equalTo(indicatorFrame.size);
- }];
- self.retryView.frame = self.indicator.frame;
- [self.readReceiptLabel sizeToFit];
- [self.readReceiptLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.bottom.mas_equalTo(self.container.mas_bottom);
- make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8);
- make.size.mas_equalTo(self.readReceiptLabel.frame.size);
- }];
- }
- if (!self.messageModifyRepliesButton.isHidden) {
- self.messageModifyRepliesButton.mm_sizeToFit();
- CGFloat repliesBtnTextWidth = self.messageModifyRepliesButton.frame.size.width;
- [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (isInComing) {
- make.leading.mas_equalTo(self.container.mas_leading);
- } else {
- make.trailing.mas_equalTo(self.container.mas_trailing);
- }
- make.top.mas_equalTo(self.container.mas_bottom);
- make.size.mas_equalTo(CGSizeMake(repliesBtnTextWidth + 10, 30));
- }];
- }
-
- if (self.messageData.showMessageModifyReplies && _replyAvatarImageViews.count > 0) {
- CGFloat lineViewW = 17;
- CGFloat avatarSize = 16;
- CGFloat repliesBtnW = kScale390(50);
- CGFloat avatarY = self.contentView.mm_h - (self.messageData.sameToNextMsgSender ? avatarSize : avatarSize * 2);
- if (self.messageData.direction == MsgDirectionIncoming) {
- UIImageView *preAvatarImageView = nil;
- for (int i = 0; i < _replyAvatarImageViews.count; ++i) {
- UIImageView *avatarView = _replyAvatarImageViews[i];
- if (i == 0) {
- preAvatarImageView = nil;
- }
- else {
- preAvatarImageView = _replyAvatarImageViews[i-1];
- }
- [avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (i == 0) {
- make.leading.mas_equalTo(_replyLineView.mas_trailing);
- }
- else {
- make.leading.mas_equalTo(preAvatarImageView.mas_centerX);
- }
- make.top.mas_equalTo(avatarY);
- make.width.height.mas_equalTo(avatarSize);
-
- }];
- avatarView.layer.masksToBounds = YES;
- avatarView.layer.cornerRadius = avatarSize / 2.0;
- }
- }
- else {
- __block UIImageView *preAvatarImageView = nil;
- NSInteger count = _replyAvatarImageViews.count;
- for (NSInteger i = (count - 1); i >=0; i--) {
- UIImageView *avatarView = _replyAvatarImageViews[i];
- [avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (!preAvatarImageView) {
- make.trailing.mas_equalTo(self.messageModifyRepliesButton.mas_leading);
- }
- else {
- make.trailing.mas_equalTo(preAvatarImageView.mas_centerX);
- }
- make.top.mas_equalTo(avatarY);
- make.width.height.mas_equalTo(avatarSize);
- }];
- avatarView.layer.masksToBounds = YES;
- avatarView.layer.cornerRadius = avatarSize / 2.0;
- preAvatarImageView = avatarView;
- }
- }
- UIImageView *lastAvatarImageView = _replyAvatarImageViews.lastObject;
- [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (self.messageData.direction == MsgDirectionIncoming) {
- make.leading.mas_equalTo(lastAvatarImageView.mas_trailing);
- }
- else {
- make.trailing.mas_equalTo(_replyLineView.mas_leading);
- }
-
- make.top.mas_equalTo(avatarY);
- make.width.mas_equalTo(repliesBtnW);
- make.height.mas_equalTo(avatarSize);
- }];
- [_replyLineView mas_remakeConstraints:^(MASConstraintMaker *make) {
- if (self.messageData.direction == MsgDirectionIncoming) {
- make.leading.mas_equalTo(self.container.mas_leading).mas_offset(- 1);
- }
- else {
- make.trailing.mas_equalTo(self.container.mas_trailing);
- }
- make.top.mas_equalTo(CGRectGetMaxY(self.container.frame) - 14);
- make.width.mas_equalTo(lineViewW);
- make.bottom.mas_equalTo(self.messageModifyRepliesButton.mas_centerY);
- }];
- } else {
- _replyLineView.frame = CGRectZero;
- self.messageModifyRepliesButton.frame = CGRectZero;
- }
- [_msgTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
- make.width.mas_equalTo(38);
- make.height.mas_equalTo(self.messageData.msgStatusSize.height);
- make.bottom.mas_equalTo(self.container).mas_offset(-kScale390(9));
- make.trailing.mas_equalTo(self.container).mas_offset(-kScale390(16));
- }];
- [_msgStatusView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.width.mas_equalTo(16);
- make.height.mas_equalTo(self.messageData.msgStatusSize.height);
- make.bottom.mas_equalTo(self.msgTimeLabel);
- make.trailing.mas_equalTo(_msgTimeLabel.mas_leading);
- }];
-
- }
- - (void)fillWithData:(TUIMessageCellData *)data {
- [super fillWithData:data];
- self.readReceiptLabel.hidden = YES;
- self.messageModifyRepliesButton.hidden = YES;
- [self.messageModifyRepliesButton setImage:nil forState:UIControlStateNormal];
- //react
- [self prepareReactTagUI:self.contentView];
-
- if (_replyAvatarImageViews.count > 0) {
- for (UIImageView *imageView in _replyAvatarImageViews) {
- [imageView removeFromSuperview];
- }
- [_replyAvatarImageViews removeAllObjects];
- }
- _replyLineView.hidden = YES;
- if (data.showMessageModifyReplies) {
- _replyLineView.hidden = NO;
- self.messageModifyRepliesButton.hidden = NO;
- // line
- UIImage *lineImage = nil;
- if (self.messageData.direction == MsgDirectionIncoming) {
- lineImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_reply_line_income")];
- } else {
- lineImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_reply_line_outcome")];
- }
- lineImage = [lineImage rtl_imageFlippedForRightToLeftLayoutDirection];
- UIEdgeInsets ei = UIEdgeInsetsFromString(@"{10,0,20,0}");
- ei = rtlEdgeInsetsWithInsets(ei);
- _replyLineView.image = [lineImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch];
- // avtar
- NSInteger avatarCount = 0;
- NSInteger avatarMaxCount = 4;
- NSMutableDictionary *existSenderMap = [NSMutableDictionary dictionary];
- for (NSDictionary *senderMap in self.messageData.messageModifyReplies) {
- NSString *sender = senderMap[@"messageSender"];
- TUIRelationUserModel *userModel = self.messageData.additionalUserInfoResult[sender];
- NSURL *headUrl = [NSURL URLWithString:userModel.faceURL];
- NSString *existSender = existSenderMap[@"messageSender"];
- if (!sender || [sender isEqualToString:existSender]) {
- //exist sender head not add again
- continue;
- }
- UIImageView *avatarView = [[UIImageView alloc] init];
- if (avatarCount < avatarMaxCount - 1) {
- existSenderMap[@"messageSender"] = sender;
- [avatarView sd_setImageWithURL:headUrl placeholderImage:DefaultAvatarImage];
- } else {
- [avatarView setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_reply_more_icon")]];
- }
- [_replyAvatarImageViews addObject:avatarView];
- [self.contentView addSubview:avatarView];
- if (++avatarCount >= avatarMaxCount) {
- break;
- }
- }
- }
- _msgTimeLabel.text = [TUITool convertDateToHMStr:self.messageData.innerMessage.timestamp];
- self.indicator.hidden = YES;
- _msgStatusView.hidden = YES;
- self.readReceiptLabel.hidden = YES;
- if (self.messageData.direction == MsgDirectionOutgoing) {
- self.status = TUIMessageStatus_Unkown;
- if (self.messageData.status == Msg_Status_Sending || self.messageData.status == Msg_Status_Sending_2) {
- [self updateMessageStatus:TUIMessageStatus_Sending];
- } else if (self.messageData.status == Msg_Status_Succ) {
- [self updateMessageStatus:TUIMessageStatus_Send_Succ];
- }
- [self updateReadLabelText];
- }
- // tell constraints they need updating
- [self setNeedsUpdateConstraints];
- // update constraints now so we can animate the change
- [self updateConstraintsIfNeeded];
- [self layoutIfNeeded];
- }
- - (void)updateReadLabelText {
- if (self.messageData.innerMessage.groupID.length > 0) {
- // group message
- if (self.messageData.messageReceipt == nil) {
- // haven't received the message receipt yet
- return;
- }
- NSInteger readCount = self.messageData.messageReceipt.readCount;
- NSInteger unreadCount = self.messageData.messageReceipt.unreadCount;
- if (unreadCount == 0) {
- // All read
- [self updateMessageStatus:TUIMessageStatus_All_People_Read];
- } else if (readCount > 0) {
- // Some read
- [self updateMessageStatus:TUIMessageStatus_Some_People_Read];
- }
- } else {
- // c2c message
- BOOL isPeerRead = self.messageData.messageReceipt.isPeerRead;
- if (isPeerRead) {
- [self updateMessageStatus:TUIMessageStatus_All_People_Read];
- }
- }
- }
- - (void)updateMessageStatus:(TUIMessageStatus)status {
- if (status <= self.status) {
- return;
- }
- if (self.messageData.showReadReceipt && self.messageData.direction == MsgDirectionOutgoing && self.messageData.innerMessage.needReadReceipt &&
- (self.messageData.innerMessage.userID || self.messageData.innerMessage.groupID)) {
- _msgStatusView.hidden = NO;
- _msgStatusView.image = nil;
- }
- if (_msgStatusView.isAnimating) {
- [_msgStatusView stopAnimating];
- _msgStatusView.animationImages = nil;
- }
- switch (status) {
- case TUIMessageStatus_Sending: {
- _msgStatusView.animationImages = self.animationImages;
- [_msgStatusView startAnimating];
- } break;
- case TUIMessageStatus_Send_Succ: {
- _msgStatusView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_status_send_succ")];
- } break;
- case TUIMessageStatus_Some_People_Read: {
- _msgStatusView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_status_some_people_read")];
- } break;
- case TUIMessageStatus_All_People_Read: {
- _msgStatusView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_status_all_people_read")];
- } break;
- default:
- break;
- }
- self.status = status;
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
- }
- #pragma mark - TUIMessageCellProtocol
- + (CGFloat)getHeight:(TUIMessageCellData *)data withWidth:(CGFloat)width {
- NSAssert([data isKindOfClass:TUIMessageCellData.class], @"data must be kind of TUIMessageCellData");
- CGFloat height = [super getHeight:data withWidth:width];
- if (data.sameToNextMsgSender) {
- height -= kScale375(16);
- }
- return height;
- }
- @end
|