TUIMessageReadViewController.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. //
  2. // TUIMessageReadViewController.m
  3. // TUIChat
  4. //
  5. // Created by xia on 2022/3/10.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIMessageReadViewController.h"
  9. #import <TUICore/TUICore.h>
  10. #import <TUICore/TUIThemeManager.h>
  11. #import <TUICore/TUITool.h>
  12. #import <TUICore/UIColor+TUIHexColor.h>
  13. #import "TUIImageMessageCellData.h"
  14. #import "TUIMemberCell.h"
  15. #import "TUIMemberCellData.h"
  16. #import "TUIMessageDataProvider.h"
  17. #import "TUIVideoMessageCellData.h"
  18. @interface TUIMessageReadSelectView ()
  19. @property(nonatomic, copy) NSString *title;
  20. @property(nonatomic, strong) UILabel *titleLabel;
  21. @property(nonatomic, strong) UIView *bottomLine;
  22. @end
  23. @implementation TUIMessageReadSelectView
  24. #pragma mark - Life cycle
  25. - (void)layoutSubviews {
  26. [super layoutSubviews];
  27. [self layoutViews];
  28. }
  29. #pragma mark - Public
  30. - (instancetype)initWithTitle:(NSString *)title viewTag:(TUIMessageReadViewTag)tag selected:(BOOL)selected {
  31. self = [super init];
  32. if (self) {
  33. self.title = title;
  34. self.tag = tag;
  35. [self setupViews];
  36. [self setupGesture];
  37. [self setupRAC];
  38. self.selected = selected;
  39. }
  40. return self;
  41. }
  42. #pragma mark - Private
  43. - (void)setupViews {
  44. self.backgroundColor = TUIChatDynamicColor(@"chat_controller_bg_color", @"#FFFFFF");
  45. self.titleLabel = [[UILabel alloc] init];
  46. self.titleLabel.text = self.title;
  47. self.titleLabel.font = [UIFont systemFontOfSize:16];
  48. self.titleLabel.textAlignment = NSTextAlignmentCenter;
  49. [self addSubview:self.titleLabel];
  50. self.bottomLine = [[UIView alloc] init];
  51. [self addSubview:self.bottomLine];
  52. }
  53. - (void)layoutViews {
  54. self.titleLabel.mm_sizeToFit().mm_height(24).mm__centerX(self.mm_w / 2.0).mm__centerY(self.mm_h / 2.0);
  55. self.bottomLine.mm_width(self.titleLabel.mm_w).mm_height(5 / 2.0).mm_top(self.titleLabel.mm_maxY + 8 / 2.0).mm__centerX(self.titleLabel.mm_centerX);
  56. }
  57. - (void)setupRAC {
  58. @weakify(self);
  59. [RACObserve(self, selected) subscribeNext:^(id _Nullable x) {
  60. @strongify(self);
  61. [self updateColorBySelected:self.selected];
  62. }];
  63. }
  64. - (void)updateColorBySelected:(BOOL)selected {
  65. UIColor *color = selected ? TUIChatDynamicColor(@"chat_message_read_status_tab_color", @"#147AFF")
  66. : TIMCommonDynamicColor(@"chat_message_read_status_tab_unselect_color", @"#444444");
  67. self.titleLabel.textColor = color;
  68. self.bottomLine.hidden = !selected;
  69. self.bottomLine.backgroundColor = color;
  70. }
  71. - (void)setupGesture {
  72. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapped:)];
  73. [self addGestureRecognizer:tap];
  74. }
  75. #pragma mark - Event
  76. - (void)onTapped:(UIGestureRecognizer *)gesture {
  77. if ([self.delegate respondsToSelector:@selector(messageReadSelectView:didSelectItemTag:)]) {
  78. [self.delegate messageReadSelectView:self didSelectItemTag:self.tag];
  79. }
  80. }
  81. @end
  82. @interface TUIMessageReadViewController () <UITableViewDelegate, UITableViewDataSource, TUIMessageReadSelectViewDelegate>
  83. @property(nonatomic, strong) TUIMessageCellData *cellData;
  84. @property(nonatomic, assign) BOOL showReadStatusDisable;
  85. @property(nonatomic, assign) TUIMessageReadViewTag selectedViewTag;
  86. @property(nonatomic, strong) TUIMessageDataProvider *dataProvider;
  87. @property(nonatomic, strong) UIView *messageBackView;
  88. @property(nonatomic, strong) UITableView *tableView;
  89. @property(nonatomic, strong) UIActivityIndicatorView *indicatorView;
  90. @property(nonatomic, strong) UILabel *contentLabel;
  91. @property(nonatomic, strong) NSMutableDictionary *selectViewsDict;
  92. @property(nonatomic, strong) NSMutableArray *readMembers;
  93. @property(nonatomic, strong) NSMutableArray *unreadMembers;
  94. @property(nonatomic, assign) NSUInteger readSeq;
  95. @property(nonatomic, assign) NSUInteger unreadSeq;
  96. @property(nonatomic, copy) NSString *c2cReceiverName;
  97. @property(nonatomic, copy) NSString *c2cReceiverAvatarUrl;
  98. @end
  99. @implementation TUIMessageReadViewController
  100. #pragma mark - Life cycle
  101. - (void)viewDidLoad {
  102. [super viewDidLoad];
  103. if ([self isGroupMessageRead]) {
  104. self.selectedViewTag = TUIMessageReadViewTagRead;
  105. [self loadMembers];
  106. } else {
  107. self.selectedViewTag = TUIMessageReadViewTagC2C;
  108. }
  109. [self setupViews];
  110. // Do any additional setup after loading the view.
  111. }
  112. - (void)viewWillLayoutSubviews {
  113. [super viewWillLayoutSubviews];
  114. [self layoutViews];
  115. }
  116. - (void)viewWillDisappear:(BOOL)animated {
  117. [super viewWillDisappear:animated];
  118. if (_viewWillDismissHandler) {
  119. _viewWillDismissHandler();
  120. }
  121. }
  122. - (void)dealloc {
  123. NSLog(@"%s dealloc", __FUNCTION__);
  124. }
  125. #pragma mark - Public
  126. - (instancetype)initWithCellData:(TUIMessageCellData *)data
  127. dataProvider:(TUIMessageDataProvider *)dataProvider
  128. showReadStatusDisable:(BOOL)showReadStatusDisable
  129. c2cReceiverName:(NSString *)name
  130. c2cReceiverAvatar:(NSString *)avatarUrl {
  131. self = [super init];
  132. if (self) {
  133. self.cellData = data;
  134. self.dataProvider = dataProvider;
  135. self.showReadStatusDisable = showReadStatusDisable;
  136. self.c2cReceiverName = name;
  137. self.c2cReceiverAvatarUrl = avatarUrl;
  138. }
  139. return self;
  140. }
  141. #pragma mark - Private
  142. - (void)setupViews {
  143. self.view.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5");
  144. [self setupTitleView];
  145. [self setupMessageView];
  146. if ([self isGroupMessageRead]) {
  147. [self setupSelectView];
  148. }
  149. [self setupTableView];
  150. }
  151. - (void)layoutViews {
  152. id content = [self content];
  153. CGFloat messageBackViewHeight = 69 ;
  154. if ([content isKindOfClass:UIImage.class]) {
  155. messageBackViewHeight = 87;
  156. }
  157. [self.messageBackView mas_makeConstraints:^(MASConstraintMaker *make) {
  158. make.top.mas_equalTo(self.view.mas_safeAreaLayoutGuideTop);
  159. make.leading.mas_equalTo(0);
  160. make.height.mas_equalTo(messageBackViewHeight);
  161. make.width.mas_equalTo(self.view);
  162. }];
  163. // content label may not exist when content is not text
  164. if (self.contentLabel) {
  165. [self.contentLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
  166. make.leading.mas_equalTo(16);
  167. make.top.mas_equalTo(33);
  168. make.height.mas_equalTo(24);
  169. make.trailing.mas_equalTo(-16);
  170. }];
  171. }
  172. UIView *readView = [self layoutSelectView:self.selectViewsDict[@(TUIMessageReadViewTagRead)] leftView:nil];
  173. UIView *unreadView = [self layoutSelectView:self.selectViewsDict[@(TUIMessageReadViewTagUnread)] leftView:readView];
  174. if (self.showReadStatusDisable) {
  175. [self layoutSelectView:self.selectViewsDict[@(TUIMessageReadViewTagReadDisable)] leftView:unreadView];
  176. }
  177. self.tableView.mm_top(self.messageBackView.mm_maxY + 10 + (self.selectViewsDict.count > 0 ? 48 : 0))
  178. .mm_left(0)
  179. .mm_width(self.view.mm_w)
  180. .mm_height(self.view.mm_h - _tableView.mm_y);
  181. }
  182. - (UIView *)layoutSelectView:(UIView *)view leftView:(UIView *)leftView {
  183. NSInteger count = self.selectViewsDict.count;
  184. if (count == 0) {
  185. return nil;
  186. }
  187. [view mas_remakeConstraints:^(MASConstraintMaker *make) {
  188. make.width.mas_equalTo(self.view).multipliedBy(1.0/count);
  189. make.height.mas_equalTo(48);
  190. if (leftView) {
  191. make.leading.mas_equalTo(leftView.mas_trailing);
  192. }
  193. else {
  194. make.leading.mas_equalTo(0);
  195. }
  196. make.top.mas_equalTo(self.messageBackView.mas_bottom).mas_offset(10);
  197. }];
  198. return view;
  199. }
  200. - (void)setupTitleView {
  201. UILabel *titleLabel = [[UILabel alloc] init];
  202. titleLabel.text = TIMCommonLocalizableString(TUIKitMessageReadDetail);
  203. titleLabel.font = [UIFont systemFontOfSize:18.0];
  204. titleLabel.textColor = TIMCommonDynamicColor(@"nav_title_text_color", @"#000000");
  205. [titleLabel sizeToFit];
  206. self.navigationItem.titleView = titleLabel;
  207. }
  208. - (void)setupMessageView {
  209. UIView *messageBackView = [[UIView alloc] init];
  210. messageBackView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
  211. [self.view addSubview:messageBackView];
  212. self.messageBackView = messageBackView;
  213. UILabel *nameLabel = [[UILabel alloc] init];
  214. nameLabel.text = self.cellData.senderName;
  215. nameLabel.font = [UIFont systemFontOfSize:12.0];
  216. nameLabel.textColor = TUIChatDynamicColor(@"chat_message_read_name_date_text_color", @"#999999");
  217. nameLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft;
  218. [messageBackView addSubview:nameLabel];
  219. [nameLabel sizeToFit];
  220. [nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  221. make.top.mas_equalTo(12);
  222. make.leading.mas_equalTo(16);
  223. make.width.mas_equalTo(nameLabel.frame.size.width);
  224. make.height.mas_equalTo(nameLabel.frame.size.height);
  225. }];
  226. UILabel *dateLabel = [[UILabel alloc] init];
  227. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  228. [formatter setDateFormat:@"MM-dd HH:mm"];
  229. NSString *dateString = [formatter stringFromDate:self.cellData.innerMessage.timestamp];
  230. dateLabel.text = dateString;
  231. dateLabel.font = [UIFont systemFontOfSize:12];
  232. dateLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft;
  233. dateLabel.textColor = TUIChatDynamicColor(@"chat_message_read_name_date_text_color", @"#999999");
  234. [messageBackView addSubview:dateLabel];
  235. [dateLabel sizeToFit];
  236. [dateLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  237. make.centerY.mas_equalTo(nameLabel);
  238. make.leading.mas_equalTo(nameLabel.mas_trailing).mas_offset(12);
  239. make.width.mas_equalTo(dateLabel.frame.size.width);
  240. make.height.mas_equalTo(dateLabel.frame.size.height);
  241. }];
  242. id content = [self content];
  243. if ([content isKindOfClass:NSString.class]) {
  244. UILabel *contentLabel = [[UILabel alloc] init];
  245. contentLabel.text = content;
  246. contentLabel.font = [UIFont systemFontOfSize:16];
  247. contentLabel.textColor = TUIChatDynamicColor(@"chat_input_text_color", @"#111111");
  248. contentLabel.lineBreakMode = NSLineBreakByTruncatingTail;
  249. contentLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft;
  250. self.contentLabel = contentLabel;
  251. [messageBackView addSubview:contentLabel];
  252. } else if ([content isKindOfClass:UIImage.class]) {
  253. UIImageView *imageView = [[UIImageView alloc] init];
  254. imageView.image = content;
  255. [messageBackView addSubview:imageView];
  256. [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
  257. make.top.mas_equalTo(33);
  258. make.leading.mas_equalTo(16);
  259. make.width.mas_equalTo([self scaledSizeOfImage:content].width);
  260. make.height.mas_equalTo([self scaledSizeOfImage:content].height);
  261. }];
  262. }
  263. }
  264. - (void)setupSelectView {
  265. NSMutableDictionary *dataDict = [self selectViewsData];
  266. NSInteger count = dataDict.count;
  267. NSMutableArray * selectViewsArray = [NSMutableArray arrayWithCapacity:2];
  268. UIView *tmp = nil;
  269. for (NSNumber *tag in dataDict) {
  270. NSDictionary *data = dataDict[tag];
  271. TUIMessageReadSelectView *selectView = [[TUIMessageReadSelectView alloc] initWithTitle:data[@"title"]
  272. viewTag:[data[@"tag"] integerValue]
  273. selected:[data[@"selected"] boolValue]];
  274. selectView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF");
  275. selectView.delegate = self;
  276. [self.view addSubview:selectView];
  277. [selectViewsArray addObject:selectView];
  278. [self.selectViewsDict setObject:selectView forKey:data[@"tag"]];
  279. selectView.mm_width(self.view.mm_w / count)
  280. .mm_height(48)
  281. .mm_left(tmp == nil ? 0 : tmp.mm_x + tmp.mm_w)
  282. .mm_top(self.messageBackView.mm_y + self.messageBackView.mm_h + 10);
  283. tmp = selectView;
  284. }
  285. }
  286. - (void)setupTableView {
  287. _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
  288. _tableView.delegate = self;
  289. _tableView.dataSource = self;
  290. _tableView.contentInset = UIEdgeInsetsMake(0, 0, 8, 0);
  291. _tableView.rowHeight = 56;
  292. [_tableView setBackgroundColor:TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF")];
  293. [self.view addSubview:_tableView];
  294. UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
  295. [_tableView setTableFooterView:view];
  296. _tableView.separatorStyle = [self isGroupMessageRead] ? UITableViewCellSeparatorStyleSingleLine : UITableViewCellSeparatorStyleNone;
  297. _tableView.separatorInset = UIEdgeInsetsMake(0, 58, 0, 0);
  298. [_tableView registerClass:[TUIMemberCell class] forCellReuseIdentifier:kMemberCellReuseId];
  299. self.indicatorView.frame = CGRectMake(0, 0, self.view.bounds.size.width, TMessageController_Header_Height);
  300. self.tableView.tableFooterView = self.indicatorView;
  301. }
  302. - (void)loadMembers {
  303. [self getReadMembersWithCompletion:^(int code, NSString *desc, NSArray *members, BOOL isFinished) {
  304. if (code != 0) {
  305. [TUITool makeToast:TIMCommonLocalizableString(TUIKitMessageReadGetReadMembersFail)];
  306. NSLog(@"get read members failed, code: %d, desc: %@", code, desc);
  307. return;
  308. }
  309. [self.tableView reloadData];
  310. }];
  311. [self getUnreadMembersWithCompletion:^(int code, NSString *desc, NSArray *members, BOOL isFinished) {
  312. if (code != 0) {
  313. [TUITool makeToast:TIMCommonLocalizableString(TUIKitMessageReadGetUnreadMembersFail)];
  314. NSLog(@"get unread members failed, code: %d, desc: %@", code, desc);
  315. return;
  316. }
  317. [self.tableView reloadData];
  318. }];
  319. }
  320. - (void)getReadMembersWithCompletion:(void (^)(int code, NSString *desc, NSArray *members, BOOL isFinished))completion {
  321. @weakify(self);
  322. [TUIMessageDataProvider getReadMembersOfMessage:self.cellData.innerMessage
  323. filter:V2TIM_GROUP_MESSAGE_READ_MEMBERS_FILTER_READ
  324. nextSeq:self.readSeq
  325. completion:^(int code, NSString *_Nonnull desc, NSArray *_Nonnull members, NSUInteger nextSeq, BOOL isFinished) {
  326. @strongify(self);
  327. if (code != 0) {
  328. if (completion) {
  329. completion(code, desc, nil, NO);
  330. }
  331. return;
  332. }
  333. [self.readMembers addObjectsFromArray:members];
  334. self.readSeq = isFinished ? -1 : nextSeq;
  335. if (completion) {
  336. completion(code, desc, members, isFinished);
  337. }
  338. }];
  339. }
  340. - (void)getUnreadMembersWithCompletion:(void (^)(int code, NSString *desc, NSArray *members, BOOL isFinished))completion {
  341. @weakify(self);
  342. [TUIMessageDataProvider getReadMembersOfMessage:self.cellData.innerMessage
  343. filter:V2TIM_GROUP_MESSAGE_READ_MEMBERS_FILTER_UNREAD
  344. nextSeq:self.unreadSeq
  345. completion:^(int code, NSString *_Nonnull desc, NSArray *_Nonnull members, NSUInteger nextSeq, BOOL isFinished) {
  346. @strongify(self);
  347. if (code != 0) {
  348. if (completion) {
  349. completion(code, desc, nil, NO);
  350. }
  351. return;
  352. }
  353. [self.unreadMembers addObjectsFromArray:members];
  354. self.unreadSeq = isFinished ? -1 : nextSeq;
  355. if (completion) {
  356. completion(code, desc, members, isFinished);
  357. }
  358. }];
  359. }
  360. - (void)getUserOrFriendProfileVCWithUserID:(NSString *)userID SuccBlock:(void (^)(UIViewController *vc))succ failBlock:(nullable V2TIMFail)fail {
  361. NSDictionary *param = @{
  362. TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_UserIDKey: userID ? : @"",
  363. TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_SuccKey: succ ? : ^(UIViewController *vc){},
  364. TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_FailKey: fail ? : ^(int code, NSString * desc){}
  365. };
  366. [TUICore createObject:TUICore_TUIContactObjectFactory key:TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod param:param];
  367. }
  368. #pragma mark - UITableViewDataSource & UITableViewDelegate
  369. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  370. if ([self isGroupMessageRead]) {
  371. if (indexPath.row >= [self members].count) {
  372. return;
  373. }
  374. V2TIMGroupMemberInfo *member = [self members][indexPath.row];
  375. [self getUserOrFriendProfileVCWithUserID:member.userID
  376. SuccBlock:^(UIViewController *vc) {
  377. [self.navigationController pushViewController:vc animated:YES];
  378. }
  379. failBlock:nil];
  380. } else {
  381. [self getUserOrFriendProfileVCWithUserID:self.cellData.innerMessage.userID
  382. SuccBlock:^(UIViewController *vc) {
  383. [self.navigationController pushViewController:vc animated:YES];
  384. }
  385. failBlock:nil];
  386. }
  387. }
  388. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  389. return 1;
  390. }
  391. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  392. return [self isGroupMessageRead] ? [self members].count : 1;
  393. }
  394. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  395. TUIMemberCell *cell = [tableView dequeueReusableCellWithIdentifier:kMemberCellReuseId forIndexPath:indexPath];
  396. cell.changeColorWhenTouched = YES;
  397. TUIMemberCellData *data;
  398. if ([self isGroupMessageRead]) {
  399. if (indexPath.row >= [self members].count) {
  400. return nil;
  401. }
  402. V2TIMGroupMemberInfo *member = [self members][indexPath.row];
  403. data = [[TUIMemberCellData alloc] initWithUserID:member.userID
  404. nickName:member.nickName
  405. friendRemark:member.friendRemark
  406. nameCard:member.nameCard
  407. avatarUrl:member.faceURL
  408. detail:nil];
  409. } else {
  410. NSString *detail = nil;
  411. BOOL isPeerRead = self.cellData.messageReceipt.isPeerRead;
  412. detail = isPeerRead ? TIMCommonLocalizableString(TUIKitMessageReadC2CRead) : TIMCommonLocalizableString(TUIKitMessageReadC2CUnReadDetail);
  413. data = [[TUIMemberCellData alloc] initWithUserID:self.cellData.innerMessage.userID
  414. nickName:nil
  415. friendRemark:self.c2cReceiverName
  416. nameCard:nil
  417. avatarUrl:self.c2cReceiverAvatarUrl
  418. detail:detail];
  419. }
  420. [cell fillWithData:data];
  421. return cell;
  422. }
  423. #pragma mark - UIScrollView
  424. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
  425. if (scrollView.contentOffset.y <= 0 || scrollView.contentOffset.y < scrollView.bounds.origin.y) {
  426. return;
  427. }
  428. if (self.indicatorView.isAnimating) {
  429. return;
  430. }
  431. [self.indicatorView startAnimating];
  432. @weakify(self);
  433. switch (self.selectedViewTag) {
  434. case TUIMessageReadViewTagRead: {
  435. [self getReadMembersWithCompletion:^(int code, NSString *desc, NSArray *members, BOOL isFinished) {
  436. @strongify(self);
  437. [self.indicatorView stopAnimating];
  438. [self refreshTableView];
  439. if (members != nil && members.count == 0) {
  440. [TUITool makeToast:TIMCommonLocalizableString(TUIKitMessageReadNoMoreData)];
  441. [self.tableView setContentOffset:CGPointMake(0, scrollView.contentOffset.y - TMessageController_Header_Height) animated:YES];
  442. }
  443. }];
  444. break;
  445. }
  446. case TUIMessageReadViewTagUnread: {
  447. [self getUnreadMembersWithCompletion:^(int code, NSString *desc, NSArray *members, BOOL isFinished) {
  448. @strongify(self);
  449. [self.indicatorView stopAnimating];
  450. [self refreshTableView];
  451. if (members != nil && members.count == 0) {
  452. [TUITool makeToast:TIMCommonLocalizableString(TUIKitMessageReadNoMoreData)];
  453. [self.tableView setContentOffset:CGPointMake(0, scrollView.contentOffset.y - TMessageController_Header_Height) animated:YES];
  454. }
  455. }];
  456. break;
  457. }
  458. case TUIMessageReadViewTagReadDisable: {
  459. break;
  460. }
  461. default: {
  462. break;
  463. }
  464. }
  465. }
  466. - (void)refreshTableView {
  467. [self.tableView reloadData];
  468. [self.tableView layoutIfNeeded];
  469. }
  470. #pragma mark - TUIMessageReadSelectViewDelegate
  471. - (void)messageReadSelectView:(TUIMessageReadSelectView *)view didSelectItemTag:(TUIMessageReadViewTag)tag {
  472. for (TUIMessageReadSelectView *view in self.selectViewsDict.allValues) {
  473. view.selected = view.tag == tag;
  474. }
  475. self.selectedViewTag = tag;
  476. [self.tableView reloadData];
  477. }
  478. #pragma mark - Getter
  479. - (id)content {
  480. V2TIMMessage *msg = self.cellData.innerMessage;
  481. NSMutableString *content = [NSMutableString stringWithString:[TUIMessageDataProvider getDisplayString:msg]];
  482. switch (msg.elemType) {
  483. case V2TIM_ELEM_TYPE_IMAGE: {
  484. TUIImageMessageCellData *data = (TUIImageMessageCellData *)self.cellData;
  485. return data.thumbImage;
  486. }
  487. case V2TIM_ELEM_TYPE_VIDEO: {
  488. TUIVideoMessageCellData *data = (TUIVideoMessageCellData *)self.cellData;
  489. return data.thumbImage;
  490. }
  491. case V2TIM_ELEM_TYPE_FILE: {
  492. [content appendString:msg.fileElem.filename];
  493. break;
  494. }
  495. case V2TIM_ELEM_TYPE_CUSTOM: {
  496. break;
  497. }
  498. default: {
  499. break;
  500. }
  501. }
  502. return content;
  503. }
  504. - (CGSize)scaledSizeOfImage:(UIImage *)image {
  505. NSSet *portraitOrientations =
  506. [NSSet setWithArray:@[ @(UIImageOrientationLeft), @(UIImageOrientationRight), @(UIImageOrientationLeftMirrored), @(UIImageOrientationRightMirrored) ]];
  507. UIImageOrientation orientation = image.imageOrientation;
  508. CGFloat width = CGImageGetWidth(image.CGImage);
  509. CGFloat height = CGImageGetHeight(image.CGImage);
  510. // Height is fixed at 42.0, and width is proportionally scaled.
  511. if ([portraitOrientations containsObject:@(orientation)]) {
  512. // UIImage is stored in memory in a fixed size, like 1280 * 720.
  513. // So we should adapt its size manually according to the direction.
  514. return CGSizeMake(42.0 * height / width, 42.0);
  515. } else {
  516. return CGSizeMake(42.0 * width / height, 42.0);
  517. }
  518. }
  519. - (NSMutableDictionary *)selectViewsData {
  520. NSMutableDictionary *readViews = [NSMutableDictionary dictionaryWithDictionary:@{
  521. @(TUIMessageReadViewTagRead) : @{
  522. @"tag" : @(TUIMessageReadViewTagRead),
  523. @"title" :
  524. [NSString stringWithFormat:@"%ld %@", (long)self.cellData.messageReceipt.readCount, TIMCommonLocalizableString(TUIKitMessageReadPartRead)],
  525. @"selected" : @(YES)
  526. },
  527. @(TUIMessageReadViewTagUnread) : @{
  528. @"tag" : @(TUIMessageReadViewTagUnread),
  529. @"title" :
  530. [NSString stringWithFormat:@"%ld %@", (long)self.cellData.messageReceipt.unreadCount, TIMCommonLocalizableString(TUIKitMessageReadPartUnread)],
  531. @"selected" : @(NO)
  532. },
  533. }];
  534. if (self.showReadStatusDisable) {
  535. [readViews
  536. setObject:@{@"tag" : @(TUIMessageReadViewTagReadDisable), @"title" : TIMCommonLocalizableString(TUIKitMessageReadPartDisable), @"selected" : @(NO)}
  537. forKey:@(TUIMessageReadViewTagReadDisable)];
  538. }
  539. return readViews;
  540. }
  541. - (NSArray *)members {
  542. switch (self.selectedViewTag) {
  543. case TUIMessageReadViewTagRead: {
  544. return self.readMembers;
  545. }
  546. case TUIMessageReadViewTagUnread: {
  547. return self.unreadMembers;
  548. }
  549. case TUIMessageReadViewTagReadDisable: {
  550. return @[];
  551. }
  552. default: {
  553. return @[];
  554. }
  555. }
  556. }
  557. - (NSMutableDictionary *)selectViewsDict {
  558. if (!_selectViewsDict) {
  559. _selectViewsDict = [[NSMutableDictionary alloc] init];
  560. }
  561. return _selectViewsDict;
  562. }
  563. - (NSMutableArray *)readMembers {
  564. if (!_readMembers) {
  565. _readMembers = [[NSMutableArray alloc] init];
  566. }
  567. return _readMembers;
  568. }
  569. - (NSMutableArray *)unreadMembers {
  570. if (!_unreadMembers) {
  571. _unreadMembers = [[NSMutableArray alloc] init];
  572. }
  573. return _unreadMembers;
  574. }
  575. - (UIActivityIndicatorView *)indicatorView {
  576. if (_indicatorView == nil) {
  577. _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  578. _indicatorView.hidesWhenStopped = YES;
  579. }
  580. return _indicatorView;
  581. }
  582. - (BOOL)isGroupMessageRead {
  583. return self.cellData.innerMessage.groupID.length > 0;
  584. }
  585. @end