| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- //
- // TUIMessageSearchDataProvider.m
- // TXIMSDK_TUIKit_iOS
- //
- // Created by kayev on 2021/7/8.
- // Copyright © 2023 Tencent. All rights reserved.
- //
- #import "TUIMessageSearchDataProvider.h"
- #import "TUIMessageBaseDataProvider+ProtectedAPI.h"
- #import "TUIChatMediaSendingManager.h"
- typedef void (^LoadSearchMsgSucceedBlock)(BOOL isOlderNoMoreMsg, BOOL isNewerNoMoreMsg, NSArray<TUIMessageCellData *> *newMsgs);
- typedef void (^LoadMsgSucceedBlock)(BOOL isOlderNoMoreMsg, BOOL isNewerNoMoreMsg, BOOL isFirstLoad, NSArray<TUIMessageCellData *> *newUIMsgs);
- @interface TUIMessageSearchDataProvider ()
- @property(nonatomic, copy) LoadSearchMsgSucceedBlock loadSearchMsgSucceedBlock;
- @property(nonatomic, copy) LoadMsgSucceedBlock loadMsgSucceedBlock;
- @end
- @implementation TUIMessageSearchDataProvider
- - (instancetype)init {
- self = [super init];
- if (self) {
- _isOlderNoMoreMsg = NO;
- _isNewerNoMoreMsg = NO;
- }
- return self;
- }
- - (void)loadMessageWithSearchMsg:(V2TIMMessage *)searchMsg
- SearchMsgSeq:(uint64_t)searchSeq
- ConversationInfo:(TUIChatConversationModel *)conversation
- SucceedBlock:(void (^)(BOOL isOlderNoMoreMsg, BOOL isNewerNoMoreMsg, NSArray<TUIMessageCellData *> *newMsgs))succeedBlock
- FailBlock:(V2TIMFail)failBlock {
- if (self.isLoadingData) {
- failBlock(ERR_SUCC, @"refreshing");
- return;
- }
- self.isLoadingData = YES;
- self.isOlderNoMoreMsg = NO;
- self.isNewerNoMoreMsg = NO;
- self.loadSearchMsgSucceedBlock = succeedBlock;
- dispatch_group_t group = dispatch_group_create();
- __block NSArray *olders = @[];
- __block NSArray *newers = @[];
- __block BOOL isOldLoadFail = NO;
- __block BOOL isNewLoadFail = NO;
- __block int failCode = 0;
- __block NSString *failDesc = nil;
- /**
- * Load the oldest pageCount messages starting from locating message
- */
- {
- dispatch_group_enter(group);
- V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
- option.getType = V2TIM_GET_CLOUD_OLDER_MSG;
- option.count = self.pageCount;
- option.groupID = conversation.groupID;
- option.userID = conversation.userID;
- if (searchMsg) {
- option.lastMsg = searchMsg;
- } else {
- option.lastMsgSeq = searchSeq;
- }
- [V2TIMManager.sharedInstance getHistoryMessageList:option
- succ:^(NSArray<V2TIMMessage *> *msgs) {
- msgs = msgs.reverseObjectEnumerator.allObjects;
- olders = msgs ?: @[];
- if (olders.count < self.pageCount) {
- self.isOlderNoMoreMsg = YES;
- }
- dispatch_group_leave(group);
- }
- fail:^(int code, NSString *desc) {
- isOldLoadFail = YES;
- failCode = code;
- failDesc = desc;
- dispatch_group_leave(group);
- }];
- }
- /**
- * Load the latest pageCount messages starting from the locating message
- */
- {
- dispatch_group_enter(group);
- V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
- option.getType = V2TIM_GET_CLOUD_NEWER_MSG;
- option.count = self.pageCount;
- option.groupID = conversation.groupID;
- option.userID = conversation.userID;
- if (searchMsg) {
- option.lastMsg = searchMsg;
- } else {
- option.lastMsgSeq = searchSeq;
- }
- [V2TIMManager.sharedInstance getHistoryMessageList:option
- succ:^(NSArray<V2TIMMessage *> *msgs) {
- newers = msgs ?: @[];
- if (newers.count < self.pageCount) {
- self.isNewerNoMoreMsg = YES;
- }
- dispatch_group_leave(group);
- }
- fail:^(int code, NSString *desc) {
- isNewLoadFail = YES;
- failCode = code;
- failDesc = desc;
- dispatch_group_leave(group);
- }];
- }
- @weakify(self);
- dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
- @strongify(self);
- self.isLoadingData = NO;
- if (isOldLoadFail || isNewLoadFail) {
- dispatch_async(dispatch_get_main_queue(), ^{
- failBlock(failCode, failDesc);
- });
- }
- self.isFirstLoad = NO;
- NSMutableArray *results = [NSMutableArray array];
- [results addObjectsFromArray:olders];
- if (searchMsg) {
- /**
- * Pulling messages through the msg will not return the msg object itself, here you need to actively add the msg to the results list
- */
- [results addObject:searchMsg];
- } else {
- /**
- * Pulling messages through the msg seq, pulling old messages and new messages will return the msg object itself, here you need to deduplicate the msg
- * object in results
- */
- [results removeLastObject];
- }
- [results addObjectsFromArray:newers];
- self.msgForOlderGet = results.firstObject;
- self.msgForNewerGet = results.lastObject;
- @weakify(self);
- dispatch_async(dispatch_get_main_queue(), ^{
- @strongify(self);
- [self.heightCache_ removeAllObjects];
- [self.uiMsgs_ removeAllObjects];
- NSArray *msgs = results.reverseObjectEnumerator.allObjects;
- NSMutableArray *uiMsgs = [self transUIMsgFromIMMsg:msgs];
- if (uiMsgs.count == 0) {
- return;
- }
- [self getGroupMessageReceipts:msgs
- uiMsgs:uiMsgs
- succ:^{
- [self preProcessMessage:uiMsgs];
- }
- fail:^{
- [self preProcessMessage:uiMsgs];
- }];
- });
- });
- }
- - (void)loadMessageWithIsRequestOlderMsg:(BOOL)orderType
- ConversationInfo:(TUIChatConversationModel *)conversation
- SucceedBlock:(void (^)(BOOL isOlderNoMoreMsg, BOOL isNewerNoMoreMsg, BOOL isFirstLoad,
- NSArray<TUIMessageCellData *> *newUIMsgs))succeedBlock
- FailBlock:(V2TIMFail)failBlock {
- self.isLoadingData = YES;
- self.loadMsgSucceedBlock = succeedBlock;
- int requestCount = self.pageCount;
- V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
- option.userID = conversation.userID;
- option.groupID = conversation.groupID;
- option.getType = orderType ? V2TIM_GET_CLOUD_OLDER_MSG : V2TIM_GET_CLOUD_NEWER_MSG;
- option.count = requestCount;
- option.lastMsg = orderType ? self.msgForOlderGet : self.msgForNewerGet;
- @weakify(self);
- [V2TIMManager.sharedInstance getHistoryMessageList:option
- succ:^(NSArray<V2TIMMessage *> *msgs) {
- @strongify(self);
- if (!orderType) {
- msgs = msgs.reverseObjectEnumerator.allObjects;
- }
- /**
- * Update the lastMsg flag
- * -- The current pull operation is to pull from the latest time point to the past
- */
- BOOL isLastest = (self.msgForNewerGet == nil) && (self.msgForOlderGet == nil) && orderType;
- if (msgs.count != 0) {
- if (orderType) {
- self.msgForOlderGet = msgs.lastObject;
- if (self.msgForNewerGet == nil) {
- self.msgForNewerGet = msgs.firstObject;
- }
- } else {
- if (self.msgForOlderGet == nil) {
- self.msgForOlderGet = msgs.lastObject;
- }
- self.msgForNewerGet = msgs.firstObject;
- }
- }
- /**
- * Update no data flag
- */
- if (msgs.count < requestCount) {
- if (orderType) {
- self.isOlderNoMoreMsg = YES;
- } else {
- self.isNewerNoMoreMsg = YES;
- }
- }
- if (isLastest) {
- /**
- * The current pull operation is to pull from the latest time point to the past
- */
- self.isNewerNoMoreMsg = YES;
- }
- NSMutableArray<TUIMessageCellData *> *uiMsgs = [self transUIMsgFromIMMsg:msgs];
- if (uiMsgs.count == 0) {
- if (self.loadMsgSucceedBlock) {
- self.loadMsgSucceedBlock(self.isOlderNoMoreMsg, self.isNewerNoMoreMsg, self.isFirstLoad, uiMsgs);
- }
- return;
- }
-
- //add media placeholder celldata
- if (self.conversationModel.conversationID.length > 0) {
- NSMutableArray<TUIChatMediaTask *> * tasks = [TUIChatMediaSendingManager.sharedInstance
- findPlaceHolderListByConversationID:self.conversationModel.conversationID];
- for (TUIChatMediaTask * task in tasks) {
- if (task.placeHolderCellData) {
- [uiMsgs addObject:task.placeHolderCellData];
- }
-
- }
- }
- [self getGroupMessageReceipts:msgs
- uiMsgs:uiMsgs
- succ:^{
- [self preProcessMessage:uiMsgs orderType:orderType];
- }
- fail:^{
- [self preProcessMessage:uiMsgs orderType:orderType];
- }];
- }
- fail:^(int code, NSString *desc) {
- self.isLoadingData = NO;
- }];
- }
- - (void)getGroupMessageReceipts:(NSArray *)msgs uiMsgs:(NSArray *)uiMsgs succ:(void (^)(void))succBlock fail:(void (^)(void))failBlock {
- [[V2TIMManager sharedInstance] getMessageReadReceipts:msgs
- succ:^(NSArray<V2TIMMessageReceipt *> *receiptList) {
- NSLog(@"getGroupMessageReceipts succeed, receiptList: %@", receiptList);
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
- for (V2TIMMessageReceipt *receipt in receiptList) {
- [dict setObject:receipt forKey:receipt.msgID];
- }
- for (TUIMessageCellData *data in uiMsgs) {
- V2TIMMessageReceipt *receipt = dict[data.msgID];
- data.messageReceipt = receipt;
- }
- if (succBlock) {
- succBlock();
- }
- }
- fail:^(int code, NSString *desc) {
- NSLog(@"getGroupMessageReceipts failed, code: %d, desc: %@", code, desc);
- if (failBlock) {
- failBlock();
- }
- }];
- }
- - (void)preProcessMessage:(NSArray *)uiMsgs {
- @weakify(self);
- [self preProcessMessage:uiMsgs
- callback:^{
- @strongify(self);
- [self addUIMsgs:uiMsgs];
- self.loadSearchMsgSucceedBlock(self.isOlderNoMoreMsg, self.isNewerNoMoreMsg, self.uiMsgs_);
- }];
- }
- - (void)preProcessMessage:(NSArray *)uiMsgs orderType:(BOOL)orderType {
- @weakify(self);
- [self preProcessMessage:uiMsgs
- callback:^{
- @strongify(self);
- if (orderType) {
- NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, uiMsgs.count)];
- [self insertUIMsgs:uiMsgs atIndexes:indexSet];
- } else {
- [self addUIMsgs:uiMsgs];
- }
- if (self.loadMsgSucceedBlock) {
- self.loadMsgSucceedBlock(self.isOlderNoMoreMsg, self.isNewerNoMoreMsg, self.isFirstLoad, uiMsgs);
- }
- self.isLoadingData = NO;
- self.isFirstLoad = NO;
- }];
- }
- - (void)removeAllSearchData {
- [self.uiMsgs_ removeAllObjects];
- self.isNewerNoMoreMsg = NO;
- self.isOlderNoMoreMsg = NO;
- self.isFirstLoad = YES;
- self.msgForNewerGet = nil;
- self.msgForOlderGet = nil;
- self.loadSearchMsgSucceedBlock = nil;
- }
- - (void)findMessages:(NSArray<NSString *> *)msgIDs callback:(void (^)(BOOL success, NSString *desc, NSArray<V2TIMMessage *> *messages))callback {
- [V2TIMManager.sharedInstance findMessages:msgIDs
- succ:^(NSArray<V2TIMMessage *> *msgs) {
- if (callback) {
- callback(YES, @"", msgs);
- }
- }
- fail:^(int code, NSString *desc) {
- if (callback) {
- callback(NO, desc, nil);
- }
- }];
- }
- #pragma mark - Override
- - (void)onRecvNewMessage:(V2TIMMessage *)msg {
- if (self.isNewerNoMoreMsg == NO) {
- /**
- * If the current message list has not pulled the last message, ignore the new message;
- * If it is processed at this time, it will cause new messages to be added to the history list, resulting in the problem of position confusion.
- */
- return;
- }
- if (self.dataSource.isDataSourceConsistent == NO ) {
- self.isNewerNoMoreMsg = NO;
- return;
- }
- [super onRecvNewMessage:msg];
- }
- @end
|