NIMSessionListViewController.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. //
  2. // NIMSessionListViewController.m
  3. // NIMKit
  4. //
  5. // Created by NetEase.
  6. // Copyright (c) 2015年 NetEase. All rights reserved.
  7. //
  8. #import "NIMSessionListViewController.h"
  9. #import "NIMSessionViewController.h"
  10. #import "NIMSessionListCell.h"
  11. #import "UIView+NIM.h"
  12. #import "NIMAvatarImageView.h"
  13. #import "NIMKitUtil.h"
  14. #import "NIMKit.h"
  15. #import "NTESSessionUtil.h"
  16. @interface NIMSessionListViewController ()
  17. @end
  18. @implementation NIMSessionListViewController
  19. - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
  20. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  21. if (self) {
  22. }
  23. return self;
  24. }
  25. - (void)dealloc{
  26. [[NIMSDK sharedSDK].conversationManager removeDelegate:self];
  27. [[NIMSDK sharedSDK].loginManager removeDelegate:self];
  28. [[NSNotificationCenter defaultCenter] removeObserver:self];
  29. }
  30. - (void)viewDidLoad {
  31. [super viewDidLoad];
  32. self.view.backgroundColor = [UIColor whiteColor];
  33. self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
  34. [self.view addSubview:self.tableView];
  35. self.tableView.delegate = self;
  36. self.tableView.dataSource = self;
  37. self.tableView.tableFooterView = [[UIView alloc] init];
  38. self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  39. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  40. self.tableView.estimatedSectionHeaderHeight = 0.0f;
  41. self.tableView.estimatedSectionFooterHeight = 0.0f;
  42. if (@available(iOS 15.0, *)) {
  43. self.tableView.sectionHeaderTopPadding = 0;
  44. }
  45. _recentSessions = [[NIMSDK sharedSDK].conversationManager.allRecentSessions mutableCopy];
  46. if (!self.recentSessions.count)
  47. {
  48. _recentSessions = [NSMutableArray array];
  49. }
  50. else
  51. {
  52. _recentSessions = [self customSortRecents:_recentSessions];
  53. }
  54. [[NIMSDK sharedSDK].conversationManager addDelegate:self];
  55. [[NIMSDK sharedSDK].loginManager addDelegate:self];
  56. extern NSString *const NIMKitTeamInfoHasUpdatedNotification;
  57. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTeamInfoHasUpdatedNotification:) name:NIMKitTeamInfoHasUpdatedNotification object:nil];
  58. extern NSString *const NIMKitTeamMembersHasUpdatedNotification;
  59. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTeamMembersHasUpdatedNotification:) name:NIMKitTeamMembersHasUpdatedNotification object:nil];
  60. extern NSString *const NIMKitUserInfoHasUpdatedNotification;
  61. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUserInfoHasUpdatedNotification:) name:NIMKitUserInfoHasUpdatedNotification object:nil];
  62. }
  63. - (void)refresh{
  64. // if (self.recentSessions.count == 0) {
  65. // self.tableView.hidden = YES;
  66. // }else{
  67. // self.tableView.hidden = NO;
  68. // }
  69. [self.tableView reloadData];
  70. if (![self isNotDataSource]) {
  71. [self.tableView lz_hideEmptyView];
  72. }else{
  73. [self showEmptyView];
  74. }
  75. }
  76. - (BOOL)isNotDataSource{
  77. NSInteger sections = self.tableView.numberOfSections;
  78. for (int section = 0; section < sections; section++) {
  79. NSInteger rows = [self.tableView numberOfRowsInSection:section];
  80. if (rows != 0) {
  81. return NO;
  82. }
  83. }
  84. return YES;
  85. }
  86. - (void)showEmptyView{
  87. }
  88. #pragma mark - UITableViewDelegate
  89. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
  90. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  91. NIMRecentSession *recentSession = self.recentSessions[indexPath.section];
  92. [self onSelectedRecent:recentSession atIndexPath:indexPath];
  93. }
  94. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  95. return 74.f;
  96. }
  97. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
  98. return YES;
  99. }
  100. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
  101. return CGFLOAT_MIN;
  102. }
  103. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
  104. return CGFLOAT_MIN;
  105. }
  106. #pragma mark - UITableViewDataSource
  107. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  108. return self.recentSessions.count;
  109. }
  110. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  111. NIMRecentSession *recent = self.recentSessions[section];
  112. NSDictionary *dict = [[YOUPAILZIntimateManager shareManager].intimateDict objectForKey:recent.session.sessionId];
  113. NSInteger grade = [[dict objectForKey:@"grade"] integerValue];
  114. if (self.isIntimateList && grade < 1) {
  115. return 0;
  116. }
  117. return 1;
  118. }
  119. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  120. static NSString * cellId = @"cellId";
  121. NIMSessionListCell * cell = [tableView dequeueReusableCellWithIdentifier:cellId];
  122. if (!cell) {
  123. cell = [[NIMSessionListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
  124. }
  125. [cell.avatarImageView addTarget:self action:@selector(onTouchAvatar:) forControlEvents:UIControlEventTouchUpInside];
  126. NIMRecentSession *recent = self.recentSessions[indexPath.section];
  127. cell.nameLabel.text = [self nameForRecentSession:recent];
  128. [cell.avatarImageView setAvatarBySession:recent.session];
  129. [cell.nameLabel sizeToFit];
  130. if ([[self contentForRecentSession:recent] isEqualToAttributedString:[[NSAttributedString alloc] initWithString:@"[缘分牵线]"]]) {
  131. NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc]initWithString:@"[缘分牵线]"];
  132. [attStr addAttribute:NSForegroundColorAttributeName value:HexColorFromRGB(0xFE66A4) range:NSMakeRange(0, 6)];//字体颜色
  133. [attStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:12] range:NSMakeRange(0, 6)];//字体大小
  134. NSTextAttachment *attchment = [[NSTextAttachment alloc]init];
  135. attchment.bounds = CGRectMake(0, -3,15,15);//设置frame
  136. attchment.image = [UIImage imageNamed:@"vqu_images_fate_heart"];//设置图片
  137.  NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:(NSTextAttachment *)(attchment)];
  138. [attStr insertAttributedString:string atIndex:5];//插入到第几个下标
  139. cell.messageLabel.attributedText = attStr;
  140. }else{
  141. cell.messageLabel.attributedText = [self contentForRecentSession:recent];
  142. }
  143. [cell.messageLabel sizeToFit];
  144. cell.timeLabel.text = [self timestampDescriptionForRecentSession:recent];
  145. [cell.timeLabel sizeToFit];
  146. [cell refresh:recent];
  147. cell.intimateBtn.hidden = YES;
  148. NSDictionary *dict = [[YOUPAILZIntimateManager shareManager].intimateDict objectForKey:recent.session.sessionId];
  149. NSString *score = [dict objectForKey:@"score"];
  150. if (score.length != 0) {
  151. cell.intimateBtn.hidden = NO;
  152. [cell.intimateBtn setTitle:[NSString stringWithFormat:@"%@",score] forState:UIControlStateNormal];
  153. }
  154. NSString *ext = [self getExtBySession:recent.session];
  155. cell.vipV.hidden = YES;
  156. cell.anchorTagImgV.hidden = YES;
  157. if (ext.length != 0) {
  158. NSData *data = [ext dataUsingEncoding:NSUTF8StringEncoding];
  159. NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
  160. if ([dict.allKeys containsObject:@"vip"]) {
  161. NSInteger vip = [[dict valueForKey:@"vip"] integerValue];
  162. NSDictionary *vipInfo = [LCSaveData getNobleInfo];
  163. NSDictionary *vipItemInfo = [vipInfo objectForKey:[NSString stringWithFormat:@"%@",@(vip)]];
  164. if (vipItemInfo != nil) {
  165. cell.vipV.hidden = NO;
  166. [cell.vipV sd_setImageWithURL:[LCTools getImageUrlWithAddress:[vipItemInfo objectForKey:@"mini_icon"]]];
  167. [cell.vipV mas_remakeConstraints:^(MASConstraintMaker *make) {
  168. make.left.equalTo(cell.nameLabel.mas_right).offset(5.0f);
  169. make.centerY.equalTo(cell.nameLabel);
  170. make.size.mas_offset(CGSizeMake(30.0f, 19.0f));
  171. }];
  172. }
  173. }
  174. if ([dict.allKeys containsObject:@"is_live"]) {
  175. NSInteger is_live = [[dict valueForKey:@"is_live"] integerValue];
  176. if (is_live == 1) {
  177. cell.anchorTagImgV.hidden = NO;
  178. }
  179. }
  180. }
  181. [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
  182. //v1.5.6 暗黑模式
  183. // [cell.contentView setBackgroundColor:LCWhiteColor];
  184. cell.avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
  185. return cell;
  186. }
  187. #pragma mark - NIMConversationManagerDelegate
  188. - (void)didAddRecentSession:(NIMRecentSession *)recentSession
  189. totalUnreadCount:(NSInteger)totalUnreadCount{
  190. [self.recentSessions addObject:recentSession];
  191. [self sort];
  192. _recentSessions = [self customSortRecents:_recentSessions];
  193. [self refresh];
  194. }
  195. - (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
  196. totalUnreadCount:(NSInteger)totalUnreadCount{
  197. for (NIMRecentSession *recent in self.recentSessions)
  198. {
  199. if ([recentSession.session.sessionId isEqualToString:recent.session.sessionId])
  200. {
  201. [self.recentSessions removeObject:recent];
  202. break;
  203. }
  204. }
  205. NSInteger insert = [self findInsertPlace:recentSession];
  206. [self.recentSessions insertObject:recentSession atIndex:insert];
  207. _recentSessions = [self customSortRecents:_recentSessions];
  208. [self refresh];
  209. }
  210. - (void)didRemoveRecentSession:(NIMRecentSession *)recentSession
  211. totalUnreadCount:(NSInteger)totalUnreadCount
  212. {
  213. //清理本地数据
  214. NSInteger index = [self.recentSessions indexOfObject:recentSession];
  215. [self.recentSessions removeObjectAtIndex:index];
  216. //如果删除本地会话后就不允许漫游当前会话,则需要进行一次删除服务器会话的操作
  217. if (self.autoRemoveRemoteSession)
  218. {
  219. [[NIMSDK sharedSDK].conversationManager deleteRemoteSessions:@[recentSession.session]
  220. completion:nil];
  221. }
  222. _recentSessions = [self customSortRecents:_recentSessions];
  223. [self refresh];
  224. }
  225. - (void)messagesDeletedInSession:(NIMSession *)session{
  226. _recentSessions = [[NIMSDK sharedSDK].conversationManager.allRecentSessions mutableCopy];
  227. _recentSessions = [self customSortRecents:_recentSessions];
  228. [self refresh];
  229. }
  230. - (void)allMessagesDeleted{
  231. _recentSessions = [[NIMSDK sharedSDK].conversationManager.allRecentSessions mutableCopy];
  232. _recentSessions = [self customSortRecents:_recentSessions];
  233. [self refresh];
  234. }
  235. - (void)allMessagesRead
  236. {
  237. _recentSessions = [[NIMSDK sharedSDK].conversationManager.allRecentSessions mutableCopy];
  238. _recentSessions = [self customSortRecents:_recentSessions];
  239. [self refresh];
  240. }
  241. - (NSMutableArray *)customSortRecents:(NSMutableArray *)recentSessions
  242. {
  243. return self.recentSessions;
  244. }
  245. #pragma mark - NIMLoginManagerDelegate
  246. - (void)onLogin:(NIMLoginStep)step
  247. {
  248. if (step == NIMLoginStepSyncOK) {
  249. [self refresh];
  250. }
  251. }
  252. #pragma mark - Override
  253. - (void)onSelectedAvatar:(NSString *)userId
  254. atIndexPath:(NSIndexPath *)indexPath{};
  255. - (void)onSelectedRecent:(NIMRecentSession *)recentSession atIndexPath:(NSIndexPath *)indexPath{
  256. NIMSessionViewController *vc = [[NIMSessionViewController alloc] initWithSession:recentSession.session];
  257. [self.navigationController pushViewController:vc animated:YES];
  258. }
  259. - (NSString *)getExtBySession:(NIMSession *)session{
  260. NIMUser *nimUser = [[[NIMSDK sharedSDK] userManager] userInfo:session.sessionId];
  261. return nimUser.userInfo.ext;
  262. }
  263. - (NSString *)nameForRecentSession:(NIMRecentSession *)recent{
  264. if (recent.session.sessionType == NIMSessionTypeP2P) {
  265. return [NIMKitUtil showNick:recent.session.sessionId inSession:recent.session];
  266. }else{
  267. NIMTeam *team = [[NIMSDK sharedSDK].teamManager teamById:recent.session.sessionId];
  268. return team.teamName;
  269. }
  270. }
  271. - (NSAttributedString *)contentForRecentSession:(NIMRecentSession *)recent{
  272. NSString *content = [self messageContent:recent.lastMessage];
  273. return [[NSAttributedString alloc] initWithString:content ?: @""];
  274. }
  275. - (NSString *)timestampDescriptionForRecentSession:(NIMRecentSession *)recent{
  276. return [NIMKitUtil showTime:recent.lastMessage.timestamp showDetail:NO];
  277. }
  278. #pragma mark - Misc
  279. - (NSInteger)findInsertPlace:(NIMRecentSession *)recentSession{
  280. __block NSUInteger matchIdx = 0;
  281. __block BOOL find = NO;
  282. [self.recentSessions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  283. NIMRecentSession *item = obj;
  284. if (item.lastMessage.timestamp <= recentSession.lastMessage.timestamp) {
  285. *stop = YES;
  286. find = YES;
  287. matchIdx = idx;
  288. }
  289. }];
  290. if (find) {
  291. return matchIdx;
  292. }else{
  293. return self.recentSessions.count;
  294. }
  295. }
  296. - (void)sort{
  297. [self.recentSessions sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
  298. NIMRecentSession *item1 = obj1;
  299. NIMRecentSession *item2 = obj2;
  300. if (item1.lastMessage.timestamp < item2.lastMessage.timestamp) {
  301. return NSOrderedDescending;
  302. }
  303. if (item1.lastMessage.timestamp > item2.lastMessage.timestamp) {
  304. return NSOrderedAscending;
  305. }
  306. return NSOrderedSame;
  307. }];
  308. }
  309. - (void)onTouchAvatar:(id)sender{
  310. UIView *view = [sender superview];
  311. while (![view isKindOfClass:[UITableViewCell class]]) {
  312. view = view.superview;
  313. }
  314. UITableViewCell *cell = (UITableViewCell *)view;
  315. NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
  316. NIMRecentSession *recent = self.recentSessions[indexPath.section];
  317. [self onSelectedAvatar:recent atIndexPath:indexPath];
  318. }
  319. #pragma mark - Private
  320. - (NSString *)messageContent:(NIMMessage*)lastMessage{
  321. NSString *text = @"";
  322. switch (lastMessage.messageType) {
  323. case NIMMessageTypeText:
  324. text = lastMessage.text;
  325. break;
  326. case NIMMessageTypeAudio:
  327. text = @"[语音]";
  328. break;
  329. case NIMMessageTypeImage:
  330. text = @"[图片]";
  331. break;
  332. case NIMMessageTypeVideo:
  333. text = @"[视频]";
  334. break;
  335. case NIMMessageTypeLocation:
  336. text = @"[位置]";
  337. break;
  338. case NIMMessageTypeNotification:{
  339. return [self notificationMessageContent:lastMessage];
  340. }
  341. case NIMMessageTypeFile:
  342. text = @"[文件]";
  343. break;
  344. case NIMMessageTypeTip:
  345. text = lastMessage.text;
  346. break;
  347. case NIMMessageTypeRobot:
  348. text = [self robotMessageContent:lastMessage];
  349. break;
  350. default:
  351. text = @"[未知消息]";
  352. }
  353. if (lastMessage.session.sessionType == NIMSessionTypeP2P || lastMessage.messageType == NIMMessageTypeTip)
  354. {
  355. return text;
  356. }
  357. else
  358. {
  359. NSString *from = lastMessage.from;
  360. if (lastMessage.messageType == NIMMessageTypeRobot)
  361. {
  362. NIMRobotObject *object = (NIMRobotObject *)lastMessage.messageObject;
  363. if (object.isFromRobot)
  364. {
  365. from = object.robotId;
  366. }
  367. }
  368. NSString *nickName = [NIMKitUtil showNick:from inSession:lastMessage.session];
  369. return nickName.length ? [nickName stringByAppendingFormat:@" : %@",text] : @"";
  370. }
  371. }
  372. - (NSString *)notificationMessageContent:(NIMMessage *)lastMessage{
  373. NIMNotificationObject *object = lastMessage.messageObject;
  374. if (object.notificationType == NIMNotificationTypeNetCall) {
  375. NIMNetCallNotificationContent *content = (NIMNetCallNotificationContent *)object.content;
  376. if (content.callType == NIMNetCallTypeAudio) {
  377. return @"[网络通话]";
  378. }
  379. return @"[视频聊天]";
  380. }
  381. if (object.notificationType == NIMNotificationTypeTeam) {
  382. NIMTeam *team = [[NIMSDK sharedSDK].teamManager teamById:lastMessage.session.sessionId];
  383. if (team.type == NIMTeamTypeNormal) {
  384. return @"[讨论组信息更新]";
  385. }else{
  386. return @"[群信息更新]";
  387. }
  388. }
  389. return @"[未知消息]";
  390. }
  391. - (NSString *)robotMessageContent:(NIMMessage *)lastMessage{
  392. NIMRobotObject *object = lastMessage.messageObject;
  393. if (object.isFromRobot)
  394. {
  395. return @"[机器人消息]";
  396. }
  397. else
  398. {
  399. return lastMessage.text;
  400. }
  401. }
  402. #pragma mark - Notification
  403. - (void)onUserInfoHasUpdatedNotification:(NSNotification *)notification{
  404. [self refresh];
  405. }
  406. - (void)onTeamInfoHasUpdatedNotification:(NSNotification *)notification{
  407. [self refresh];
  408. }
  409. - (void)onTeamMembersHasUpdatedNotification:(NSNotification *)notification{
  410. [self refresh];
  411. }
  412. @end