TUIConversationListDataProvider.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. //
  2. // V2TUIConversationListDataProvider.m
  3. // TUIConversation
  4. //
  5. // Created by harvy on 2022/7/14.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIConversationListDataProvider.h"
  9. #import <TIMCommon/NSString+TUIEmoji.h>
  10. #import <TIMCommon/TIMDefine.h>
  11. #import <TUICore/TUICore.h>
  12. #import "TUIConversationCellData.h"
  13. @implementation TUIConversationListDataProvider
  14. - (Class)getConversationCellClass {
  15. return [TUIConversationCellData class];
  16. }
  17. - (void)asnycGetLastMessageDisplay:(NSArray<TUIConversationCellData *> *)duplicateDataList addedDataList:(NSArray<TUIConversationCellData *> *)addedDataList {
  18. NSMutableArray *allConversationList = [NSMutableArray array];
  19. [allConversationList addObjectsFromArray:duplicateDataList];
  20. [allConversationList addObjectsFromArray:addedDataList];
  21. NSMutableArray *messageList = [NSMutableArray array];
  22. for (TUIConversationCellData *cellData in allConversationList) {
  23. if (cellData.lastMessage && cellData.lastMessage.msgID) {
  24. [messageList addObject:cellData.lastMessage];
  25. }
  26. }
  27. if (messageList.count == 0) {
  28. return;
  29. }
  30. __weak typeof(self) weakSelf = self;
  31. NSDictionary *param = @{TUICore_TUIChatService_AsyncGetDisplayStringMethod_MsgListKey : messageList};
  32. [TUICore callService:TUICore_TUIChatService
  33. method:TUICore_TUIChatService_AsyncGetDisplayStringMethod
  34. param:param
  35. resultCallback:^(NSInteger errorCode, NSString *_Nonnull errorMessage, NSDictionary *_Nonnull param) {
  36. if (0 != errorCode) {
  37. return;
  38. }
  39. // cache
  40. NSMutableDictionary *dictM = [NSMutableDictionary dictionaryWithDictionary:weakSelf.lastMessageDisplayMap];
  41. [param enumerateKeysAndObjectsUsingBlock:^(NSString *msgID, NSString *displayString, BOOL *_Nonnull stop) {
  42. [dictM setObject:displayString forKey:msgID];
  43. }];
  44. weakSelf.lastMessageDisplayMap = [NSDictionary dictionaryWithDictionary:dictM];
  45. // Refresh if needed
  46. NSMutableArray *needRefreshConvList = [NSMutableArray array];
  47. for (TUIConversationCellData *cellData in allConversationList) {
  48. if (cellData.lastMessage && cellData.lastMessage.msgID && [param.allKeys containsObject:cellData.lastMessage.msgID]) {
  49. cellData.subTitle = [self getLastDisplayString:cellData.innerConversation];
  50. cellData.foldSubTitle = [self getLastDisplayStringForFoldList:cellData.innerConversation];
  51. [needRefreshConvList addObject:cellData];
  52. }
  53. }
  54. NSMutableDictionary<NSString *, NSNumber *> *conversationMap = [NSMutableDictionary dictionary];
  55. for (TUIConversationCellData *item in weakSelf.conversationList) {
  56. if (item.conversationID) {
  57. [conversationMap setObject:@([weakSelf.conversationList indexOfObject:item]) forKey:item.conversationID];
  58. }
  59. }
  60. [weakSelf handleUpdateConversationList:needRefreshConvList positions:conversationMap];
  61. }];
  62. }
  63. - (NSString *)getDisplayStringFromService:(V2TIMMessage *)msg {
  64. // from cache
  65. NSString *displayString = [self.lastMessageDisplayMap objectForKey:msg.msgID];
  66. if (displayString.length > 0) {
  67. return displayString;
  68. }
  69. // from TUIChat
  70. NSDictionary *param = @{TUICore_TUIChatService_GetDisplayStringMethod_MsgKey : msg};
  71. return [TUICore callService:TUICore_TUIChatService method:TUICore_TUIChatService_GetDisplayStringMethod param:param];
  72. }
  73. - (NSMutableAttributedString *)getLastDisplayString:(V2TIMConversation *)conv {
  74. /**
  75. * If has group-at message, the group-at information will be displayed first
  76. */
  77. NSString *atStr = [self getGroupAtTipString:conv];
  78. NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:atStr];
  79. NSDictionary *attributeDict = @{NSForegroundColorAttributeName : [UIColor d_systemRedColor]};
  80. [attributeString setAttributes:attributeDict range:NSMakeRange(0, attributeString.length)];
  81. BOOL hasRiskContent = conv.lastMessage.hasRiskContent;
  82. BOOL isRevoked = (conv.lastMessage.status == V2TIM_MSG_STATUS_LOCAL_REVOKED);
  83. /**
  84. * If there is a draft box, the draft box information will be displayed first
  85. */
  86. if (conv.draftText.length > 0) {
  87. NSAttributedString *draft = [[NSAttributedString alloc] initWithString:TIMCommonLocalizableString(TUIKitMessageTypeDraftFormat)
  88. attributes:@{NSForegroundColorAttributeName : RGB(250, 81, 81)}];
  89. [attributeString appendAttributedString:draft];
  90. NSString *draftContentStr = [self getDraftContent:conv];
  91. draftContentStr = [draftContentStr getLocalizableStringWithFaceContent];
  92. NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:draftContentStr
  93. attributes:@{NSForegroundColorAttributeName : [UIColor d_systemGrayColor]}];
  94. [attributeString appendAttributedString:draftContent];
  95. } else {
  96. /**
  97. * No drafts, show conversation lastMsg information
  98. */
  99. NSString *lastMsgStr = @"";
  100. /**
  101. * Attempt to get externally customized display information
  102. */
  103. if (self.delegate && [self.delegate respondsToSelector:@selector(getConversationDisplayString:)]) {
  104. lastMsgStr = [self.delegate getConversationDisplayString:conv];
  105. }
  106. /**
  107. * If there is no external customization, get the lastMsg display information through the message module
  108. */
  109. if (lastMsgStr.length == 0 && conv.lastMessage) {
  110. lastMsgStr = [self getDisplayStringFromService:conv.lastMessage];
  111. }
  112. /**
  113. * If there is no lastMsg display information and no draft information, return nil directly
  114. */
  115. if (lastMsgStr.length == 0) {
  116. return nil;
  117. }
  118. if (hasRiskContent && !isRevoked) {
  119. [attributeString appendAttributedString:[[NSAttributedString alloc] initWithString:lastMsgStr
  120. attributes:@{NSForegroundColorAttributeName : RGB(233, 68, 68)}]];
  121. } else {
  122. [attributeString appendAttributedString:[[NSAttributedString alloc] initWithString:lastMsgStr]];
  123. }
  124. }
  125. /**
  126. * Meeting V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE ,UI
  127. *
  128. * If do-not-disturb is set, the message do-not-disturb state is displayed
  129. * The default state of the meeting type group is V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE, and the UI does not process it.
  130. */
  131. if ([self isConversationNotDisturb:conv] && conv.unreadCount > 0) {
  132. NSAttributedString *unreadString = [[NSAttributedString alloc]
  133. initWithString:[NSString stringWithFormat:@"[%d %@] ", conv.unreadCount, TIMCommonLocalizableString(TUIKitMessageTypeLastMsgCountFormat)]];
  134. [attributeString insertAttributedString:unreadString atIndex:0];
  135. }
  136. /**
  137. * If the status of the lastMsg of the conversation is sending or failed, display the sending status of the message (the draft box does not need to display
  138. * the sending status)
  139. */
  140. if (!conv.draftText && (V2TIM_MSG_STATUS_SENDING == conv.lastMessage.status || V2TIM_MSG_STATUS_SEND_FAIL == conv.lastMessage.status || hasRiskContent) &&
  141. !isRevoked) {
  142. UIFont *textFont = [UIFont systemFontOfSize:14];
  143. NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:@" " attributes:@{NSFontAttributeName : textFont}];
  144. NSTextAttachment *attchment = [[NSTextAttachment alloc] init];
  145. UIImage *image = nil;
  146. if (V2TIM_MSG_STATUS_SENDING == conv.lastMessage.status) {
  147. image = TUIConversationCommonBundleImage(@"msg_sending_for_conv");
  148. } else {
  149. image = TUIConversationCommonBundleImage(@"msg_error_for_conv");
  150. }
  151. attchment.image = image;
  152. attchment.bounds = CGRectMake(0, -(textFont.lineHeight - textFont.pointSize) / 2, textFont.pointSize, textFont.pointSize);
  153. NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:(NSTextAttachment *)(attchment)];
  154. [attributeString insertAttributedString:spaceString atIndex:0];
  155. [attributeString insertAttributedString:imageString atIndex:0];
  156. }
  157. return attributeString;
  158. }
  159. - (TUIConversationCellData *)cellDataForConversation:(V2TIMConversation *)conversation {
  160. Class cls = [self getConversationCellClass];
  161. if (cls) {
  162. TUIConversationCellData *data = (TUIConversationCellData *)[[cls alloc] init];
  163. data.conversationID = conversation.conversationID;
  164. data.groupID = conversation.groupID;
  165. data.groupType = conversation.groupType;
  166. data.userID = conversation.userID;
  167. data.title = conversation.showName;
  168. data.faceUrl = conversation.faceUrl;
  169. data.subTitle = [self getLastDisplayString:conversation];
  170. data.foldSubTitle = [self getLastDisplayStringForFoldList:conversation];
  171. data.atTipsStr = [self getGroupAtTipString:conversation];
  172. data.atMsgSeqs = [self getGroupatMsgSeqs:conversation];
  173. data.time = [self getLastDisplayDate:conversation];
  174. data.isOnTop = conversation.isPinned;
  175. data.unreadCount = conversation.unreadCount;
  176. data.draftText = conversation.draftText;
  177. data.isNotDisturb = [self isConversationNotDisturb:conversation];
  178. data.orderKey = conversation.orderKey;
  179. data.avatarImage = (conversation.type == V2TIM_C2C ? DefaultAvatarImage : DefaultGroupAvatarImageByGroupType(conversation.groupType));
  180. data.onlineStatus = TUIConversationOnlineStatusUnknown;
  181. data.isMarkAsUnread = [TUIConversationCellData isMarkedByUnReadType:conversation.markList];
  182. data.isMarkAsHide = [TUIConversationCellData isMarkedByHideType:conversation.markList];
  183. data.isMarkAsFolded = [TUIConversationCellData isMarkedByFoldType:conversation.markList];
  184. data.lastMessage = conversation.lastMessage;
  185. data.innerConversation = conversation;
  186. data.conversationGroupList = conversation.conversationGroupList;
  187. data.conversationMarkList = conversation.markList;
  188. if (self.delegateTwo && [self.delegateTwo respondsToSelector:@selector(cellDataForConversation_Two:)]) {
  189. TUIConversationCellData *tempData = [self.delegateTwo cellDataForConversation_Two:conversation];
  190. data.title = tempData.title;
  191. data.faceUrl = tempData.faceUrl;
  192. data.headgearType = tempData.headgearType;
  193. data.headdress = tempData.headdress;
  194. data.nameAttrString = tempData.nameAttrString;
  195. data.nameAttWidth = tempData.nameAttWidth;
  196. }
  197. return data;
  198. }
  199. return nil;
  200. }
  201. @end