| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- // Created by Tencent on 2023/06/09.
- // Copyright © 2023 Tencent. All rights reserved.
- #import "TUIMessageDataProvider.h"
- #import <AVFoundation/AVFoundation.h>
- #import <TIMCommon/TUIRelationUserModel.h>
- #import <TIMCommon/TUISystemMessageCellData.h>
- #import <TUICore/TUILogin.h>
- #import "TUIChatCallingDataProvider.h"
- #import "TUICloudCustomDataTypeCenter.h"
- #import "TUIFaceMessageCellData.h"
- #import "TUIFileMessageCellData.h"
- #import "TUIImageMessageCellData.h"
- #import "TUIJoinGroupMessageCellData.h"
- #import "TUIMergeMessageCellData.h"
- #import "TUIMessageDataProvider+MessageDeal.h"
- #import "TUIMessageProgressManager.h"
- #import "TUIReplyMessageCellData.h"
- #import "TUITextMessageCellData.h"
- #import "TUIVideoMessageCellData.h"
- #import "TUIVoiceMessageCellData.h"
- /**
- * The maximum editable time after the message is recalled, default is (2 * 60)
- */
- #define MaxReEditMessageDelay 2 * 60
- #define kIsCustomMessageFromPlugin @"kIsCustomMessageFromPlugin"
- static Class<TUIMessageDataProviderDataSource> gDataSourceClass = nil;
- @implementation TUIMessageDataProvider
- #pragma mark - Life cycle
- - (void)dealloc {
- gCallingDataProvider = nil;
- }
- + (void)setDataSourceClass:(Class<TUIMessageDataProviderDataSource>)dataSourceClass {
- gDataSourceClass = dataSourceClass;
- }
- #pragma mark - TUIMessageCellData parser
- + (nullable TUIMessageCellData *)getCellData:(V2TIMMessage *)message {
- // 1 Parse cell data
- TUIMessageCellData *data = [self parseMessageCellDataFromMessageStatus:message];
- if (data == nil) {
- data = [self parseMessageCellDataFromMessageCustomData:message];
- }
- if (data == nil) {
- data = [self parseMessageCellDataFromMessageElement:message];
- }
- // 2 Fill in property if needed
- if (data) {
- [self fillPropertyToCellData:data ofMessage:message];
- } else {
- NSLog(@"current message will be ignored in chat page, msg:%@", message);
- }
- return data;
- }
- + (nullable TUIMessageCellData *)parseMessageCellDataFromMessageStatus:(V2TIMMessage *)message {
- TUIMessageCellData *data = nil;
- if (message.status == V2TIM_MSG_STATUS_LOCAL_REVOKED) {
- data = [TUIMessageDataProvider getRevokeCellData:message];
- }
- return data;
- }
- + (nullable TUIMessageCellData *)parseMessageCellDataFromMessageCustomData:(V2TIMMessage *)message {
- TUIMessageCellData *data = nil;
- if ([message isContainsCloudCustomOfDataType:TUICloudCustomDataType_MessageReply]) {
- /**
- * Determine whether to include "reply-message"
- */
- data = [TUIReplyMessageCellData getCellData:message];
- } else if ([message isContainsCloudCustomOfDataType:TUICloudCustomDataType_MessageReference]) {
- /**
- * Determine whether to include "quote-message"
- */
- data = [TUIReferenceMessageCellData getCellData:message];
- }
- return data;
- }
- + (nullable TUIMessageCellData *)parseMessageCellDataFromMessageElement:(V2TIMMessage *)message {
- TUIMessageCellData *data = nil;
- switch (message.elemType) {
- case V2TIM_ELEM_TYPE_TEXT: {
- data = [TUITextMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_IMAGE: {
- data = [TUIImageMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_SOUND: {
- data = [TUIVoiceMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_VIDEO: {
- data = [TUIVideoMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_FILE: {
- data = [TUIFileMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_FACE: {
- data = [TUIFaceMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_GROUP_TIPS: {
- data = [self getSystemCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_MERGER: {
- data = [TUIMergeMessageCellData getCellData:message];
- } break;
- case V2TIM_ELEM_TYPE_CUSTOM: {
- data = [self getCustomMessageCellData:message];
- } break;
- default:
- data = [self getUnsupportedCellData:message];
- break;
- }
- return data;
- }
- + (void)fillPropertyToCellData:(TUIMessageCellData *)data ofMessage:(V2TIMMessage *)message {
- data.innerMessage = message;
- if (message.groupID.length > 0 && !message.isSelf && ![data isKindOfClass:[TUISystemMessageCellData class]]) {
- data.showName = YES;
- }
- switch (message.status) {
- case V2TIM_MSG_STATUS_SEND_SUCC:
- data.status = Msg_Status_Succ;
- break;
- case V2TIM_MSG_STATUS_SEND_FAIL:
- data.status = Msg_Status_Fail;
- break;
- case V2TIM_MSG_STATUS_SENDING:
- data.status = Msg_Status_Sending_2;
- break;
- default:
- break;
- }
- /**
- * Update progress of message uploading/downloading
- */
- {
- NSInteger uploadProgress = [TUIMessageProgressManager.shareManager uploadProgressForMessage:message.msgID];
- NSInteger downloadProgress = [TUIMessageProgressManager.shareManager downloadProgressForMessage:message.msgID];
- if ([data conformsToProtocol:@protocol(TUIMessageCellDataFileUploadProtocol)]) {
- ((id<TUIMessageCellDataFileUploadProtocol>)data).uploadProgress = uploadProgress;
- }
- if ([data conformsToProtocol:@protocol(TUIMessageCellDataFileDownloadProtocol)]) {
- ((id<TUIMessageCellDataFileDownloadProtocol>)data).downladProgress = downloadProgress;
- ((id<TUIMessageCellDataFileDownloadProtocol>)data).isDownloading = (downloadProgress != 0) && (downloadProgress != 100);
- }
- }
- /**
- * Determine whether to include "replies-message"
- */
- if ([message isContainsCloudCustomOfDataType:TUICloudCustomDataType_MessageReplies]) {
- [message doThingsInContainsCloudCustomOfDataType:TUICloudCustomDataType_MessageReplies
- callback:^(BOOL isContains, id obj) {
- if (isContains) {
- if ([data isKindOfClass:TUISystemMessageCellData.class] ||
- [data isKindOfClass:TUIJoinGroupMessageCellData.class]) {
- data.showMessageModifyReplies = NO;
- } else {
- data.showMessageModifyReplies = YES;
- }
- if (obj && [obj isKindOfClass:NSDictionary.class]) {
- NSDictionary *dic = (NSDictionary *)obj;
- NSString *typeStr =
- [TUICloudCustomDataTypeCenter convertType2String:TUICloudCustomDataType_MessageReplies];
- NSDictionary *messageReplies = [dic valueForKey:typeStr];
- NSArray *repliesArr = [messageReplies valueForKey:@"replies"];
- if ([repliesArr isKindOfClass:NSArray.class]) {
- data.messageModifyReplies = repliesArr.copy;
- }
- }
- }
- }];
- }
- }
- + (nullable TUIMessageCellData *)getCustomMessageCellData:(V2TIMMessage *)message {
- // ************************************************************************************
- // ************************************************************************************
- // **The compatible processing logic of TUICallKit will be removed after***************
- // **TUICallKit is connected according to the standard process. ***********************
- // ************************************************************************************
- // ************************************************************************************
- TUIMessageCellData *data = nil;
- id<TUIChatCallingInfoProtocol> callingInfo = nil;
- if ([self.callingDataProvider isCallingMessage:message callingInfo:&callingInfo]) {
- // Voice-video-call message
- if (callingInfo) {
- // Supported voice-video-call message
- if (callingInfo.excludeFromHistory) {
- // This message will be ignore in chat page
- data = nil;
- } else {
- data = [self getCallingCellData:callingInfo];
- if (data == nil) {
- data = [self getUnsupportedCellData:message];
- }
- }
- } else {
- // Unsupported voice-video-call message
- data = [self getUnsupportedCellData:message];
- }
- return data;
- }
- // ************************************************************************************
- // ************************************************************************************
- // ************************************************************************************
- // ************************************************************************************
- NSString *businessID = nil;
- BOOL excludeFromHistory = NO;
- V2TIMSignalingInfo *signalingInfo = [V2TIMManager.sharedInstance getSignallingInfo:message];
- if (signalingInfo) {
- // This message is signaling message
- BOOL isOnlineOnly = NO;
- @try {
- isOnlineOnly = [[message valueForKeyPath:@"message.IsOnlineOnly"] boolValue];
- } @catch (NSException *exception) {
- isOnlineOnly = NO;
- }
- excludeFromHistory = isOnlineOnly || (message.isExcludedFromLastMessage && message.isExcludedFromUnreadCount);
- businessID = [self getSignalingBusinessID:signalingInfo];
- } else {
- // This message is normal custom message
- excludeFromHistory = NO;
- businessID = [self getCustomBusinessID:message];
- }
- if (excludeFromHistory) {
- // Return nil means not display in the chat page
- return nil;
- }
- if (businessID.length > 0) {
- Class cellDataClass = nil;
- if (gDataSourceClass && [gDataSourceClass respondsToSelector:@selector(onGetCustomMessageCellDataClass:)]) {
- cellDataClass = [gDataSourceClass onGetCustomMessageCellDataClass:businessID];
- }
- if (cellDataClass && [cellDataClass respondsToSelector:@selector(getCellData:)]) {
- TUIMessageCellData *data = [cellDataClass getCellData:message];
- if (data.shouldHide) {
- return nil;
- } else {
- data.reuseId = businessID;
- return data;
- }
- }
- // In CustomerService scenarios, unsupported messages are not displayed directly.
- if ([businessID tui_containsString:BussinessID_CustomerService]) {
- return nil;
- }
- return [self getUnsupportedCellData:message];
- } else {
- return [self getUnsupportedCellData:message];
- }
- }
- + (NSString *)getDisplayStringAboutCustom:(V2TIMMessage *)message {
- NSDictionary *param = [NSJSONSerialization JSONObjectWithData:message.customElem.data options:NSJSONReadingAllowFragments error:nil];
- if (param == nil) {
- return nil;
- }
-
- NSString *contentStr = [TUIMessageDataProvider objectOrNilForKey:@"content" fromDictionary:param];
- if(contentStr.length > 0){
- return contentStr;
- }
-
- return message.customElem.desc;
- }
- + (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict
- {
- id object = [dict objectForKey:aKey];
- return [object isEqual:[NSNull null]] ? nil : object;
- }
- + (TUIMessageCellData *)getUnsupportedCellData:(V2TIMMessage *)message {
- TUITextMessageCellData *cellData = [[TUITextMessageCellData alloc] initWithDirection:(message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming)];
- cellData.content = TIMCommonLocalizableString(TUIKitNotSupportThisMessage);
- cellData.reuseId = TTextMessageCell_ReuseId;
- return cellData;
- }
- + (nullable TUISystemMessageCellData *)getSystemCellData:(V2TIMMessage *)message {
- V2TIMGroupTipsElem *tip = message.groupTipsElem;
- NSString *opUserName = [self getOpUserName:tip.opMember];
- NSMutableArray<NSString *> *userNameList = [self getUserNameList:tip.memberList];
- NSMutableArray<NSString *> *userIDList = [self getUserIDList:tip.memberList];
- if (tip.type == V2TIM_GROUP_TIPS_TYPE_JOIN || tip.type == V2TIM_GROUP_TIPS_TYPE_INVITE || tip.type == V2TIM_GROUP_TIPS_TYPE_KICKED ||
- tip.type == V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE || tip.type == V2TIM_GROUP_TIPS_TYPE_QUIT ||
- tip.type == V2TIM_GROUP_TIPS_TYPE_PINNED_MESSAGE_ADDED || tip.type == V2TIM_GROUP_TIPS_TYPE_PINNED_MESSAGE_DELETED) {
- TUIJoinGroupMessageCellData *joinGroupData = [[TUIJoinGroupMessageCellData alloc] initWithDirection:MsgDirectionIncoming];
- joinGroupData.content = [self getDisplayString:message];
- joinGroupData.opUserName = opUserName;
- joinGroupData.opUserID = tip.opMember.userID;
- joinGroupData.userNameList = userNameList;
- joinGroupData.userIDList = userIDList;
- joinGroupData.reuseId = TJoinGroupMessageCell_ReuseId;
- return joinGroupData;
- } else {
- TUISystemMessageCellData *sysdata = [[TUISystemMessageCellData alloc] initWithDirection:MsgDirectionIncoming];
- sysdata.content = [self getDisplayString:message];
- sysdata.reuseId = TSystemMessageCell_ReuseId;
- if (sysdata.content.length) {
- return sysdata;
- }
- }
- return nil;
- }
- + (nullable TUISystemMessageCellData *)getRevokeCellData:(V2TIMMessage *)message {
- TUISystemMessageCellData *revoke = [[TUISystemMessageCellData alloc] initWithDirection:(message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming)];
- revoke.reuseId = TSystemMessageCell_ReuseId;
- revoke.content = [self getRevokeDispayString:message];
- revoke.innerMessage = message;
- V2TIMUserFullInfo *revokerInfo = message.revokerInfo;
- if (message.isSelf) {
- if (message.elemType == V2TIM_ELEM_TYPE_TEXT && fabs([[NSDate date] timeIntervalSinceDate:message.timestamp]) < MaxReEditMessageDelay) {
- if (revokerInfo && ![revokerInfo.userID isEqualToString:message.sender]) {
- // Super User revoke
- revoke.supportReEdit = NO;
- } else {
- revoke.supportReEdit = YES;
- }
- }
- } else if (message.groupID.length > 0) {
- /**
- * For the name display of group messages, the group business card is displayed first, the nickname has the second priority, and the user ID has the
- * lowest priority.
- */
- NSString *userName = [TUIMessageDataProvider getShowName:message];
- TUIJoinGroupMessageCellData *joinGroupData = [[TUIJoinGroupMessageCellData alloc] initWithDirection:MsgDirectionIncoming];
- joinGroupData.content = [self getRevokeDispayString:message];
- joinGroupData.opUserID = message.sender;
- joinGroupData.opUserName = userName;
- joinGroupData.reuseId = TJoinGroupMessageCell_ReuseId;
- return joinGroupData;
- }
- return revoke;
- }
- + (nullable TUISystemMessageCellData *)getSystemMsgFromDate:(NSDate *)date {
- TUISystemMessageCellData *system = [[TUISystemMessageCellData alloc] initWithDirection:MsgDirectionOutgoing];
- system.content = [TUITool convertDateToStr:date];
- system.reuseId = TSystemMessageCell_ReuseId;
- system.type = TUISystemMessageTypeDate;
- return system;
- }
- #pragma mark - Last message parser
- + (void)asyncGetDisplayString:(NSArray<V2TIMMessage *> *)messageList callback:(void (^)(NSDictionary<NSString *, NSString *> *))callback {
- if (!callback) {
- return;
- }
- NSMutableDictionary *originDisplayMap = [NSMutableDictionary dictionary];
- NSMutableArray *cellDataList = [NSMutableArray array];
- for (V2TIMMessage *message in messageList) {
- TUIMessageCellData *cellData = [self getCellData:message];
- if (cellData) {
- [cellDataList addObject:cellData];
- }
- NSString *displayString = [self getDisplayString:message];
- if (displayString && message.msgID) {
- originDisplayMap[message.msgID] = displayString;
- }
- }
- if (cellDataList.count == 0) {
- callback(@{});
- return;
- }
- TUIMessageDataProvider *provider = [[TUIMessageDataProvider alloc] init];
- NSArray *additionUserIDList = [provider getUserIDListForAdditionalUserInfo:cellDataList];
- if (additionUserIDList.count == 0) {
- callback(@{});
- return;
- }
- NSMutableDictionary *result = [NSMutableDictionary dictionary];
- [provider
- requestForAdditionalUserInfo:cellDataList
- callback:^{
- for (TUIMessageCellData *cellData in cellDataList) {
- [cellData.additionalUserInfoResult
- enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, TUIRelationUserModel *_Nonnull obj, BOOL *_Nonnull stop) {
- NSString *str = [NSString stringWithFormat:@"{%@}", key];
- NSString *showName = obj.userID;
- if (obj.nameCard.length > 0) {
- showName = obj.nameCard;
- } else if (obj.friendRemark.length > 0) {
- showName = obj.friendRemark;
- } else if (obj.nickName.length > 0) {
- showName = obj.nickName;
- }
- NSString *displayString = [originDisplayMap objectForKey:cellData.msgID];
- if (displayString && [displayString containsString:str]) {
- displayString = [displayString stringByReplacingOccurrencesOfString:str withString:showName];
- result[cellData.msgID] = displayString;
- }
- callback(result);
- }];
- }
- }];
- }
- + (nullable NSString *)getDisplayString:(V2TIMMessage *)message {
- BOOL hasRiskContent = message.hasRiskContent;
- BOOL isRevoked = (message.status == V2TIM_MSG_STATUS_LOCAL_REVOKED);
- if (hasRiskContent && !isRevoked) {
- return TIMCommonLocalizableString(TUIKitMessageDisplayRiskContent);
- }
- NSString *str = [self parseDisplayStringFromMessageStatus:message];
- if (str == nil) {
- str = [self parseDisplayStringFromMessageElement:message];
- }
- if (str == nil) {
- NSLog(@"current message will be ignored in chat page or conversation list page, msg:%@", message);
- }
- return str;
- }
- + (nullable NSString *)parseDisplayStringFromMessageStatus:(V2TIMMessage *)message {
- NSString *str = nil;
- if (message.status == V2TIM_MSG_STATUS_LOCAL_REVOKED) {
- str = [self getRevokeDispayString:message];
- }
- return str;
- }
- + (nullable NSString *)parseDisplayStringFromMessageElement:(V2TIMMessage *)message {
- NSString *str = nil;
- switch (message.elemType) {
- case V2TIM_ELEM_TYPE_TEXT: {
- str = [TUITextMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_IMAGE: {
- str = [TUIImageMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_SOUND: {
- str = [TUIVoiceMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_VIDEO: {
- str = [TUIVideoMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_FILE: {
- str = [TUIFileMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_FACE: {
- str = [TUIFaceMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_MERGER: {
- str = [TUIMergeMessageCellData getDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_GROUP_TIPS: {
- str = [self getGroupTipsDisplayString:message];
- } break;
- case V2TIM_ELEM_TYPE_CUSTOM: {
- str = [self getCustomDisplayString:message];
- } break;
- default:
- str = TIMCommonLocalizableString(TUIKitMessageTipsUnsupportCustomMessage);
- break;
- }
- return str;
- }
- + (nullable NSString *)getCustomDisplayString:(V2TIMMessage *)message {
- // ************************************************************************************
- // ************************************************************************************
- // ************** TUICallKit , TUICallKit *************
- // ************************************************************************************
- // ************************************************************************************
- NSString *str = nil;
- id<TUIChatCallingInfoProtocol> callingInfo = nil;
- if ([self.callingDataProvider isCallingMessage:message callingInfo:&callingInfo]) {
- // Voice-video-call message
- if (callingInfo) {
- // Supported voice-video-call message
- if (callingInfo.excludeFromHistory) {
- // This message will be ignore in chat page
- str = nil;
- } else {
- // Get display text
- str = callingInfo.content ?: TIMCommonLocalizableString(TUIKitMessageTipsUnsupportCustomMessage);
- }
- } else {
- // Unsupported voice-video-call message
- str = TIMCommonLocalizableString(TUIKitMessageTipsUnsupportCustomMessage);
- }
- return str;
- }
- // ************************************************************************************
- // ************************************************************************************
- // ************************************************************************************
- // ************************************************************************************
- NSString *businessID = nil;
- BOOL excludeFromHistory = NO;
- V2TIMSignalingInfo *signalingInfo = [V2TIMManager.sharedInstance getSignallingInfo:message];
- if (signalingInfo) {
- // This message is signaling message
- excludeFromHistory = message.isExcludedFromLastMessage && message.isExcludedFromUnreadCount;
- businessID = [self getSignalingBusinessID:signalingInfo];
- } else {
- // This message is normal custom message
- excludeFromHistory = NO;
- businessID = [self getCustomBusinessID:message];
- }
- if (excludeFromHistory) {
- // Return nil means not display int the chat page
- return nil;
- }
- if (businessID.length > 0) {
- Class cellDataClass = nil;
- if (gDataSourceClass && [gDataSourceClass respondsToSelector:@selector(onGetCustomMessageCellDataClass:)]) {
- cellDataClass = [gDataSourceClass onGetCustomMessageCellDataClass:businessID];
- }
- if (cellDataClass && [cellDataClass respondsToSelector:@selector(getDisplayString:)]) {
- return [cellDataClass getDisplayString:message];
- }
- // In CustomerService scenarios, unsupported messages are not displayed directly.
- if ([businessID tui_containsString:BussinessID_CustomerService]) {
- return nil;
- }
-
- NSString *tipStr = [self getDisplayStringAboutCustom:message];
- if(tipStr.length > 0){
- return tipStr;
- }
-
- return TIMCommonLocalizableString(TUIKitMessageTipsUnsupportCustomMessage);
- } else {
- return TIMCommonLocalizableString(TUIKitMessageTipsUnsupportCustomMessage);
- }
- }
- #pragma mark - Data source operate
- - (void)processQuoteMessage:(NSArray<TUIMessageCellData *> *)uiMsgs {
- if (uiMsgs.count == 0) {
- return;
- }
- @weakify(self);
- dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_group_t group = dispatch_group_create();
- dispatch_group_async(group, concurrentQueue, ^{
- for (TUIMessageCellData *cellData in uiMsgs) {
- if (![cellData isKindOfClass:TUIReplyMessageCellData.class]) {
- continue;
- }
- TUIReplyMessageCellData *myData = (TUIReplyMessageCellData *)cellData;
- __weak typeof(myData) weakMyData = myData;
- myData.onFinish = ^{
- dispatch_async(dispatch_get_main_queue(), ^{
- NSUInteger index = [self.uiMsgs indexOfObject:weakMyData];
- if (index != NSNotFound) {
- // if messageData exist In datasource, reload this data.
- [UIView performWithoutAnimation:^{
- @strongify(self);
- [self.dataSource dataProviderDataSourceWillChange:self];
- [self.dataSource dataProviderDataSourceChange:self
- withType:TUIMessageBaseDataProviderDataSourceChangeTypeReload
- atIndex:index
- animation:NO];
- [self.dataSource dataProviderDataSourceDidChange:self];
- }];
- }
- });
- };
- dispatch_group_enter(group);
- [self loadOriginMessageFromReplyData:myData
- dealCallback:^{
- dispatch_group_leave(group);
- dispatch_async(dispatch_get_main_queue(), ^{
- NSUInteger index = [self.uiMsgs indexOfObject:weakMyData];
- if (index != NSNotFound) {
- // if messageData exist In datasource, reload this data.
- [UIView performWithoutAnimation:^{
- @strongify(self);
- [self.dataSource dataProviderDataSourceWillChange:self];
- [self.dataSource dataProvider:self onRemoveHeightCache:weakMyData];
- [self.dataSource dataProviderDataSourceChange:self
- withType:TUIMessageBaseDataProviderDataSourceChangeTypeReload
- atIndex:index
- animation:NO];
- [self.dataSource dataProviderDataSourceDidChange:self];
- }];
- }
- });
- }];
- }
- });
- dispatch_group_notify(group, dispatch_get_main_queue(),
- ^{
- // complete
- });
- }
- - (void)deleteUIMsgs:(NSArray<TUIMessageCellData *> *)uiMsgs SuccBlock:(nullable V2TIMSucc)succ FailBlock:(nullable V2TIMFail)fail {
- NSMutableArray *uiMsgList = [NSMutableArray array];
- NSMutableArray *imMsgList = [NSMutableArray array];
- for (TUIMessageCellData *uiMsg in uiMsgs) {
- if ([self.uiMsgs containsObject:uiMsg]) {
- // Check content cell
- [uiMsgList addObject:uiMsg];
- [imMsgList addObject:uiMsg.innerMessage];
- // Check time cell which also need to be deleted
- NSInteger index = [self.uiMsgs indexOfObject:uiMsg];
- index--;
- if (index >= 0 && index < self.uiMsgs.count && [[self.uiMsgs objectAtIndex:index] isKindOfClass:TUISystemMessageCellData.class]) {
- TUISystemMessageCellData *systemCellData = (TUISystemMessageCellData *)[self.uiMsgs objectAtIndex:index];
- if (systemCellData.type == TUISystemMessageTypeDate) {
- [uiMsgList addObject:systemCellData];
- }
- }
- }
- }
- if (imMsgList.count == 0) {
- if (fail) {
- fail(ERR_INVALID_PARAMETERS, @"not found uiMsgs");
- }
- return;
- }
- @weakify(self);
- [self.class deleteMessages:imMsgList
- succ:^{
- @strongify(self);
- [self.dataSource dataProviderDataSourceWillChange:self];
- for (TUIMessageCellData *uiMsg in uiMsgList) {
- NSInteger index = [self.uiMsgs indexOfObject:uiMsg];
- [self.dataSource dataProviderDataSourceChange:self
- withType:TUIMessageBaseDataProviderDataSourceChangeTypeDelete
- atIndex:index
- animation:YES];
- }
- [self removeUIMsgList:uiMsgList];
- [self.dataSource dataProviderDataSourceDidChange:self];
- if (succ) {
- succ();
- }
- }
- fail:fail];
- }
- - (void)removeUIMsgList:(NSArray<TUIMessageCellData *> *)cellDatas {
- for (TUIMessageCellData *uiMsg in cellDatas) {
- [self removeUIMsg:uiMsg];
- }
- }
- #pragma mark - Utils
- + (nullable NSString *)getCustomBusinessID:(V2TIMMessage *)message {
- if (message == nil || message.customElem.data == nil) {
- return nil;
- }
- NSError *error = nil;
- NSDictionary *param = [NSJSONSerialization JSONObjectWithData:message.customElem.data options:NSJSONReadingAllowFragments error:&error];
- if (error) {
- NSLog(@"parse customElem data error: %@", error);
- return nil;
- }
- if (!param || ![param isKindOfClass:[NSDictionary class]]) {
- return nil;
- }
- NSString *businessID = param[BussinessID];
- if ([businessID isKindOfClass:[NSString class]] && businessID.length > 0) {
- return businessID;
- } else {
- if ([param.allKeys containsObject:BussinessID_CustomerService]) {
- NSString *src = param[BussinessID_Src_CustomerService];
- if (src.length > 0 && [src isKindOfClass:[NSString class]]) {
- return [NSString stringWithFormat:@"%@%@", BussinessID_CustomerService, src];
- }
- }
- return nil;
- }
- }
- + (nullable NSString *)getSignalingBusinessID:(V2TIMSignalingInfo *)signalInfo {
- if (signalInfo.data == nil) {
- return nil;
- }
- NSError *error = nil;
- NSDictionary *param = [NSJSONSerialization JSONObjectWithData:[signalInfo.data dataUsingEncoding:NSUTF8StringEncoding]
- options:NSJSONReadingAllowFragments
- error:&error];
- if (error) {
- NSLog(@"parse customElem data error: %@", error);
- return nil;
- }
- if (!param || ![param isKindOfClass:[NSDictionary class]]) {
- return nil;
- }
- NSString *businessID = param[BussinessID];
- if (!businessID || ![businessID isKindOfClass:[NSString class]]) {
- return nil;
- }
- return businessID;
- }
- #pragma mark - TUICallKit
- static TUIChatCallingDataProvider *gCallingDataProvider;
- + (TUIChatCallingDataProvider *)callingDataProvider {
- if (gCallingDataProvider == nil) {
- gCallingDataProvider = [[TUIChatCallingDataProvider alloc] init];
- }
- return gCallingDataProvider;
- }
- + (TUIMessageCellData *)getCallingCellData:(id<TUIChatCallingInfoProtocol>)callingInfo {
- TMsgDirection direction = MsgDirectionIncoming;
- if (callingInfo.direction == TUICallMessageDirectionIncoming) {
- direction = MsgDirectionIncoming;
- } else if (callingInfo.direction == TUICallMessageDirectionOutgoing) {
- direction = MsgDirectionOutgoing;
- }
- if (callingInfo.participantType == TUICallParticipantTypeC2C) {
- TUITextMessageCellData *cellData = [[TUITextMessageCellData alloc] initWithDirection:direction];
- if (callingInfo.streamMediaType == TUICallStreamMediaTypeVoice) {
- cellData.isAudioCall = YES;
- } else if (callingInfo.streamMediaType == TUICallStreamMediaTypeVideo) {
- cellData.isVideoCall = YES;
- } else {
- cellData.isAudioCall = NO;
- cellData.isVideoCall = NO;
- }
- cellData.content = callingInfo.content;
- cellData.isCaller = (callingInfo.participantRole == TUICallParticipantRoleCaller);
- cellData.showUnreadPoint = callingInfo.showUnreadPoint;
- cellData.isUseMsgReceiverAvatar = callingInfo.isUseReceiverAvatar;
- cellData.reuseId = TTextMessageCell_ReuseId;
- return cellData;
- } else if (callingInfo.participantType == TUICallParticipantTypeGroup) {
- TUISystemMessageCellData *cellData = [[TUISystemMessageCellData alloc] initWithDirection:direction];
- cellData.content = callingInfo.content;
- cellData.replacedUserIDList = callingInfo.participantIDList;
- cellData.reuseId = TSystemMessageCell_ReuseId;
- return cellData;
- } else {
- return nil;
- }
- }
- @end
|