IMAConversation.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. //
  2. // IMAConversation.m
  3. // TIMAdapter
  4. //
  5. // Created by AlexiChen on 16/1/29.
  6. // Copyright © 2016年 AlexiChen. All rights reserved.
  7. //
  8. #import "IMAConversation.h"
  9. @interface IMAConversation ()
  10. @property (nonatomic, strong) TIMConversation *conversation;
  11. @end
  12. @implementation IMAConversation
  13. - (instancetype)initWith:(TIMConversation *)conv
  14. {
  15. if (self = [super init])
  16. {
  17. _conversation = conv;
  18. _msgList = [[CLSafeMutableArray alloc] init];
  19. }
  20. return self;
  21. }
  22. - (void)copyConversationInfo:(IMAConversation *)conv
  23. {
  24. _msgList = conv.msgList;
  25. _imaConType = [conv imaType];
  26. _lastMessage = [conv lastMessage];
  27. _receiveMsg = conv.receiveMsg;
  28. }
  29. - (void)asyncLoadLocalLastMsg:(CommonBlock)block
  30. {
  31. DebugLog(@"============>>>>>>>>> %@", self);
  32. NSArray *msgs = [_conversation getLastMsgs:20];
  33. for (TIMMessage *msg in msgs)
  34. {
  35. if (msg.status != TIM_MSG_STATUS_LOCAL_REVOKED)
  36. {
  37. IMAMsg *imamsg = [IMAMsg msgWith:msg];
  38. if (imamsg)
  39. {
  40. self.lastMessage = imamsg;
  41. if (block)
  42. {
  43. //block();
  44. }
  45. return;
  46. }
  47. }
  48. }
  49. // __weak IMAConversation *ws = self;
  50. // [_conversation getMessage:1 last:nil succ:^(NSArray *array) {
  51. // if (array.count > 0)
  52. // {
  53. // TIMMessage *msg = array[0];
  54. //
  55. // // TODO:此处有可能是已删掉的信息
  56. //
  57. // IMAMsg *imamsg = [IMAMsg msgWith:msg];
  58. // if (imamsg)
  59. // {
  60. // ws.lastMessage = imamsg;
  61. // }
  62. // }
  63. //
  64. // if (block)
  65. // {
  66. // block();
  67. // }
  68. // } fail:^(int code, NSString *err) {
  69. // DebugLog(@"未取到最后一条消息");
  70. // if (block)
  71. // {
  72. // block();
  73. // }
  74. // }];
  75. }
  76. - (void)releaseConversation
  77. {
  78. [_msgList removeAllObjects];
  79. _receiveMsg = nil;
  80. }
  81. - (void)setReadAllMsg
  82. {
  83. [IMAPlatform sharedInstance].conversationMgr.unReadMessageCount -= [_conversation getUnReadMessageNum];
  84. [_conversation setReadMessage:nil succ:nil fail:nil];
  85. }
  86. - (NSInteger)unReadCount
  87. {
  88. NSInteger count = [_conversation getUnReadMessageNum];
  89. return count;
  90. }
  91. - (IMAConType)imaType
  92. {
  93. _imaConType = (IMAConType)[self type];
  94. return _imaConType;
  95. }
  96. - (IMAMsg *)vailedTopMsg
  97. {
  98. NSInteger count = [_msgList count];
  99. if (count > 0)
  100. {
  101. NSInteger index = 0;
  102. do
  103. {
  104. IMAMsg *msg = [_msgList objectAtIndex:index];
  105. if ([msg isVailedType])
  106. {
  107. return msg;
  108. }
  109. index++;
  110. }
  111. while (index < count);
  112. }
  113. return nil;
  114. }
  115. // 切换到本会话前,先加载本地的最后10条聊天的的数据
  116. - (void)asyncLoadRecentMessage:(NSInteger)count completion:(HandleMsgBlock)block;
  117. {
  118. IMAMsg *top = [self vailedTopMsg];
  119. [self asyncLoadRecentMessage:count from:top completion:block];
  120. }
  121. - (NSArray *)onLoadRecentMessageSucc:(NSArray *)timmsgList
  122. {
  123. if (timmsgList.count > 0)
  124. {
  125. NSMutableArray *array = [NSMutableArray array];
  126. NSInteger idx = timmsgList.count - 1;
  127. TIMMessage *temp = nil;
  128. do
  129. {
  130. TIMMessage *msg = timmsgList[idx];
  131. // if (msg.status == TIM_MSG_STATUS_HAS_DELETED)
  132. // {
  133. // idx--;
  134. // continue;
  135. // }
  136. NSDate *date = [msg timestamp];
  137. if (idx == timmsgList.count - 1)
  138. {
  139. // 插入标签
  140. IMAMsg *timeTip = [IMAMsg msgWithDate:date];
  141. [array addObject:timeTip];
  142. }
  143. if (temp)
  144. {
  145. NSDate *lastDate = [temp timestamp];
  146. NSTimeInterval timeinterval = [date timeIntervalSinceDate:lastDate];
  147. if (timeinterval > 5 * 60)
  148. {
  149. // 大于五分钟
  150. IMAMsg *msg = [IMAMsg msgWithDate:date];
  151. [array addObject:msg];
  152. }
  153. }
  154. temp = msg;
  155. if (msg.status == TIM_MSG_STATUS_LOCAL_REVOKED) {//撤销
  156. IMAMsg *imamsg = [IMAMsg msgWithRevoked:msg.sender];
  157. if (imamsg)
  158. {
  159. [array addObject:imamsg];
  160. }
  161. }
  162. else {
  163. IMAMsg *imamsg = [IMAMsg msgWith:msg];
  164. if (imamsg)
  165. {
  166. [array addObject:imamsg];
  167. }
  168. }
  169. idx--;
  170. }
  171. while (idx >= 0);
  172. [_msgList insertObjectsFromArray:array atIndex:0];
  173. return array;
  174. }
  175. return nil;
  176. }
  177. // 用于顶部下拉加载更多历史消息
  178. - (void)asyncLoadRecentMessage:(NSInteger)count from:(IMAMsg *)msg completion:(HandleMsgBlock)block
  179. {
  180. __weak IMAConversation *ws = self;
  181. [_conversation getMessage:(int)count last:msg.msg succ:^(NSArray *array) {
  182. NSArray *recentIMAMsg = [ws onLoadRecentMessageSucc:array];
  183. if (block)
  184. {
  185. block(recentIMAMsg, recentIMAMsg.count != 0);
  186. }
  187. } fail:^(int code, NSString *err) {
  188. DebugLog(@"未取到最后一条消息");
  189. if (block)
  190. {
  191. block(nil, NO);
  192. }
  193. }];
  194. }
  195. - (TIMConversationType)type
  196. {
  197. return [_conversation getType];
  198. }
  199. - (NSString *)receiver;
  200. {
  201. return [_conversation getReceiver];
  202. }
  203. - (BOOL)isChatWith:(IMAUser *)user
  204. {
  205. return [[_conversation getReceiver] isEqualToString:[user userId]];
  206. }
  207. - (BOOL)isEqualTo:(IMAConversation *)conv
  208. {
  209. return ([self type] == [conv type]) && ([[self receiver] isEqualToString:[conv receiver]]);
  210. }
  211. - (BOOL)isEqual:(id)object
  212. {
  213. BOOL equal = [super isEqual:object];
  214. if (!equal)
  215. {
  216. if ([object isKindOfClass:[IMAConversation class]])
  217. {
  218. IMAConversation *conv = (IMAConversation *)object;
  219. equal = [self isEqualTo:conv];
  220. }
  221. }
  222. return equal;
  223. }
  224. - (NSArray *)sendMessage:(IMAMsg *)msg completion:(HandleMsgCodeBlock)block
  225. {
  226. if (msg)
  227. {
  228. NSMutableArray *array = [self addMsgToList:msg];
  229. [msg changeTo:EIMAMsg_Sending needRefresh:NO];
  230. [_conversation sendMessage:msg.msg succ:^{
  231. [msg changeTo:EIMAMsg_SendSucc needRefresh:YES];
  232. if (block)
  233. {
  234. block(array, YES, 0);
  235. }
  236. } fail:^(int code, NSString *err) {
  237. [msg changeTo:EIMAMsg_SendFail needRefresh:YES];
  238. DebugLog(@"发送消息失败");
  239. if (code != kSaftyWordsCode)
  240. {
  241. DebugLog(@"Fail:-->code=%d,msg=%@,fun=%s", code, err,__func__);
  242. [[BGHUDHelper sharedInstance] tipMessage:IMALocalizedError(code, err)];
  243. }
  244. if (block)
  245. {
  246. block(array, NO, code);
  247. }
  248. }];
  249. return array;
  250. }
  251. return nil;
  252. }
  253. - (void)sendOnlineMessage:(TIMMessage*)msg succ:(TIMSucc)succ fail:(TIMFail)fail
  254. {
  255. [_conversation sendOnlineMessage:msg succ:succ fail:fail];
  256. }
  257. - (NSMutableArray *)addMsgToList:(IMAMsg *)msg
  258. {
  259. if (msg)
  260. {
  261. NSMutableArray *array = [NSMutableArray array];
  262. IMAMsg *timeTip = [self timeTipOnNewMessage:msg];
  263. if (timeTip)
  264. {
  265. [array addObject:timeTip];
  266. }
  267. // 外部KVO lastmsg
  268. self.lastMessage = msg;
  269. [[IMAPlatform sharedInstance].conversationMgr updateOnLastMessageChanged:self];
  270. // 列表更新
  271. [array addObject:msg];
  272. [_msgList addObjectsFromArray:array];
  273. return array;
  274. }
  275. return nil;
  276. }
  277. - (NSArray *)appendWillSendMsg:(IMAMsg *)msg completion:(HandleMsgBlock)block
  278. {
  279. if (msg)
  280. {
  281. NSArray *array = [self addMsgToList:msg];
  282. [msg changeTo:EIMAMsg_WillSending needRefresh:YES];
  283. if (block)
  284. {
  285. block(array, YES);
  286. }
  287. return array;
  288. }
  289. return nil;
  290. }
  291. - (void)replaceWillSendMsg:(IMAMsg *)msg with:(IMAMsg *)newMsg completion:(HandleMsgBlock)block
  292. {
  293. if (msg && newMsg)
  294. {
  295. // 还未真正地删除,先只是同步到列表中
  296. NSInteger oldIdx = [_msgList indexOfObject:msg];
  297. NSInteger count = [_msgList count];
  298. if (oldIdx >= 0 && oldIdx < count)
  299. {
  300. [newMsg changeTo:EIMAMsg_Sending needRefresh:YES];
  301. [_msgList replaceObjectAtIndex:oldIdx withObject:newMsg];
  302. if (self.lastMessage == msg)
  303. {
  304. self.lastMessage = newMsg;
  305. }
  306. NSArray *reapceArray = @[[_msgList objectAtIndex:oldIdx]];
  307. if (block)
  308. {
  309. block(reapceArray, YES);
  310. }
  311. [_conversation sendMessage:newMsg.msg succ:^{
  312. [newMsg changeTo:EIMAMsg_SendSucc needRefresh:YES];
  313. } fail:^(int code, NSString *err) {
  314. [newMsg changeTo:EIMAMsg_SendFail needRefresh:YES];
  315. DebugLog(@"发送消息失败");
  316. }];
  317. }
  318. }
  319. }
  320. - (NSArray *)revokeMsg:(IMAMsg *)msg isRemote:(BOOL)isRemote completion:(RemoveMsgBlock)block
  321. {
  322. if (msg)
  323. {
  324. NSMutableArray *array = [NSMutableArray array];
  325. NSInteger idx = [_msgList indexOfObject:msg];
  326. if (idx >= 0 && idx < _msgList.count)
  327. {
  328. NSInteger preIdx = idx - 1;
  329. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  330. if (preIdx >= 0 && preIdx < _msgList.count)
  331. {
  332. IMAMsg *preMsg = [_msgList objectAtIndex:preIdx];
  333. if (preMsg.type == EIMAMSG_TimeTip)
  334. {
  335. if (idx == _msgList.count - 1)
  336. {
  337. // 最后两条消息
  338. [array addObject:preMsg];
  339. [array addObject:msgReal];
  340. }
  341. else
  342. {
  343. NSInteger nextIdx = idx + 1;
  344. if (nextIdx >= 0 && nextIdx < _msgList.count)
  345. {
  346. IMAMsg *nextMsg = [_msgList objectAtIndex:nextIdx];
  347. if (nextMsg.type == EIMAMSG_TimeTip)
  348. {
  349. [array addObject:nextMsg];
  350. [array addObject:msgReal];
  351. }
  352. else
  353. {
  354. [array addObject:msgReal];
  355. }
  356. }
  357. }
  358. }
  359. else
  360. {
  361. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  362. [array addObject:msgReal];
  363. }
  364. }
  365. else
  366. {
  367. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  368. [array addObject:msgReal];
  369. }
  370. }
  371. if (block)
  372. {
  373. __weak CLSafeMutableArray *wcl = _msgList;
  374. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  375. NSUInteger index = [wcl indexOfObject:msgReal];
  376. IMAMsg *imamsg = [IMAMsg msgWithRevoked:msgReal.msg.sender];
  377. [wcl replaceObjectAtIndex:index withObject:imamsg];
  378. for (IMAMsg *removemsg in array)
  379. {
  380. if (removemsg.type == EIMAMSG_TimeTip || removemsg.type == EIMAMSG_SaftyTip)
  381. {
  382. // 属于自定义的类型,不在IMSDK数据库里面,不能调remove接口
  383. continue;
  384. }
  385. if (isRemote)
  386. {
  387. block(array, YES, nil);
  388. }
  389. else
  390. {
  391. [_conversation revokeMessage:removemsg.msg succ:^{
  392. NSLog(@"revoke succ");
  393. block(array, YES, nil);
  394. } fail:^(int code, NSString *msg) {
  395. NSLog(@"revoke fail");
  396. NSString *info = [NSString stringWithFormat:ASLocalizedString(@"消息撤回失败,code=%d,msg=%@"),code,msg];
  397. [[BGHUDHelper sharedInstance] tipMessage:info delay:3];
  398. block(array, NO, nil);
  399. }];
  400. }
  401. break;
  402. }
  403. }
  404. return array;
  405. }
  406. return nil;
  407. }
  408. - (NSArray *)removeMsg:(IMAMsg *)msg completion:(RemoveMsgBlock)block
  409. {
  410. if (msg)
  411. {
  412. NSMutableArray *array = [NSMutableArray array];
  413. NSInteger idx = [_msgList indexOfObject:msg];
  414. if (idx >= 0 && idx < _msgList.count)
  415. {
  416. NSInteger preIdx = idx - 1;
  417. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  418. if (preIdx >= 0 && preIdx < _msgList.count)
  419. {
  420. IMAMsg *preMsg = [_msgList objectAtIndex:preIdx];
  421. if (preMsg.type == EIMAMSG_TimeTip)
  422. {
  423. if (idx == _msgList.count - 1)
  424. {
  425. // 最后两条消息
  426. [array addObject:preMsg];
  427. [array addObject:msgReal];
  428. }
  429. else
  430. {
  431. NSInteger nextIdx = idx + 1;
  432. if (nextIdx >= 0 && nextIdx < _msgList.count)
  433. {
  434. IMAMsg *nextMsg = [_msgList objectAtIndex:nextIdx];
  435. if (nextMsg.type == EIMAMSG_TimeTip)
  436. {
  437. [array addObject:nextMsg];
  438. [array addObject:msgReal];
  439. }
  440. else
  441. {
  442. [array addObject:msgReal];
  443. }
  444. }
  445. }
  446. }
  447. else
  448. {
  449. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  450. [array addObject:msgReal];
  451. }
  452. }
  453. else
  454. {
  455. IMAMsg *msgReal = [_msgList objectAtIndex:idx];
  456. [array addObject:msgReal];
  457. }
  458. }
  459. if (block)
  460. {
  461. __weak CLSafeMutableArray *wcl = _msgList;
  462. // CommonBlock action = ^{
  463. // for (IMAMsg *removemsg in array)
  464. // {
  465. // [removemsg remove];
  466. // }
  467. //
  468. // [wcl removeObjectsInArray:array];
  469. // };
  470. // block(array, YES, action);
  471. }
  472. return array;
  473. }
  474. return nil;
  475. }
  476. - (IMAMsg *)timeTipOnNewMessage:(IMAMsg *)msg
  477. {
  478. if (_lastMessage)
  479. {
  480. NSDate *lastDate = [_lastMessage.msg timestamp];
  481. NSDate *followDate = [msg.msg timestamp];
  482. NSTimeInterval timeinterval = [followDate timeIntervalSinceDate:lastDate];
  483. if (timeinterval > 5 * 60)
  484. {
  485. // 大于五分钟
  486. IMAMsg *msg = [IMAMsg msgWithDate:followDate];
  487. return msg;
  488. }
  489. }
  490. return nil;
  491. }
  492. - (void)onReceiveNewMessage:(IMAMsg *)msg
  493. {
  494. NSMutableArray *array = [NSMutableArray array];
  495. IMAMsg *timeTip = [self timeTipOnNewMessage:msg];
  496. if (timeTip)
  497. {
  498. [array addObject:timeTip];
  499. }
  500. [array addObject:msg];
  501. [_msgList addObjectsFromArray:array];
  502. if (_receiveMsg)
  503. {
  504. _receiveMsg(array, YES);
  505. }
  506. }
  507. - (void)setDraft:(TIMMessageDraft *)draft
  508. {
  509. [_conversation setDraft:draft];
  510. }
  511. - (TIMMessageDraft *)getDraft
  512. {
  513. return [_conversation getDraft];
  514. }
  515. @end