TUIConversationTableView.m 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. //
  2. // TUIConversationTableView.m
  3. // TUIConversation
  4. //
  5. // Created by xiangzhang on 2023/3/17.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIConversationTableView.h"
  9. #import <TIMCommon/TUISecondConfirm.h>
  10. #import <TUICore/TUICore.h>
  11. #import "TUIConversationCell.h"
  12. #import "TUIFoldListViewController.h"
  13. #import "TUIConversationConfig.h"
  14. #import "MOConversationEmptyCell.h"
  15. @interface TUIConversationTableView () <UITableViewDelegate, UITableViewDataSource, TUIConversationListDataProviderDelegate>
  16. @property(nonatomic, strong) UIImageView *tipsView;
  17. @property(nonatomic, strong) UILabel *tipsLabel;
  18. @property (nonatomic, assign) BOOL hideMarkReadAction;
  19. @property (nonatomic, assign) BOOL hideDeleteAction;
  20. @property (nonatomic, assign) BOOL hideHideAction;
  21. @property (nonatomic, strong) NSArray *customizedItems;
  22. @end
  23. @implementation TUIConversationTableView {
  24. TUIConversationListBaseDataProvider *_dataProvider;
  25. }
  26. - (instancetype)init {
  27. self = [super init];
  28. if (self) {
  29. [self setTableView];
  30. }
  31. return self;
  32. }
  33. - (instancetype)initWithFrame:(CGRect)frame {
  34. self = [super initWithFrame:frame];
  35. if (self) {
  36. [self setTableView];
  37. }
  38. return self;
  39. }
  40. - (void)setFrame:(CGRect)frame {
  41. [super setFrame:frame];
  42. [self setTipsViewFrame];
  43. }
  44. - (void)setTableView {
  45. self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  46. self.backgroundColor = TUIConversationDynamicColor(@"conversation_bg_color", @"#FFFFFF");
  47. self.tableFooterView = [[UIView alloc] init];
  48. self.contentInset = UIEdgeInsetsMake(0, 0, 120, 0);
  49. [self registerClass:[TUIConversationCell class] forCellReuseIdentifier:gConversationCell_ReuseId];
  50. [self registerClass:[MOConversationEmptyCell class] forCellReuseIdentifier:@"MOConversationEmptyCell"];
  51. self.estimatedRowHeight = TConversationCell_Height;
  52. self.rowHeight = TConversationCell_Height;
  53. self.delaysContentTouches = NO;
  54. // [self setSeparatorColor:TIMCommonDynamicColor(@"separator_color", @"#E1E2E8")];
  55. self.separatorStyle = UITableViewCellSeparatorStyleNone;
  56. self.delegate = self;
  57. self.dataSource = self;
  58. [self addSubview:self.tipsView];
  59. [self addSubview:self.tipsLabel];
  60. self.disableMoreActionExtension = NO;
  61. [self setTipsViewFrame];
  62. [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(onFriendInfoChanged:) name:@"FriendInfoChangedNotification" object:nil];
  63. }
  64. - (void)onFriendInfoChanged:(NSNotification *)notice {
  65. V2TIMFriendInfo *friendInfo = notice.object;
  66. if (friendInfo == nil) {
  67. return;
  68. }
  69. for (TUIConversationCellData *cellData in self.dataProvider.conversationList) {
  70. if ([cellData.userID isEqualToString:friendInfo.userID]) {
  71. NSString *title = friendInfo.friendRemark;
  72. if (title.length == 0) {
  73. title = friendInfo.userFullInfo.nickName;
  74. }
  75. if (title.length == 0) {
  76. title = friendInfo.userID;
  77. }
  78. cellData.title = title;
  79. [self reloadData];
  80. break;
  81. }
  82. }
  83. }
  84. - (UIImageView *)tipsView {
  85. if (!_tipsView) {
  86. _tipsView = [[UIImageView alloc] init];
  87. // _tipsView.image = TUIConversationDynamicImage(@"no_conversation_img", [UIImage imageNamed:TUIConversationImagePath(@"no_conversation")]);
  88. _tipsView.hidden = YES;
  89. }
  90. return _tipsView;
  91. }
  92. - (UILabel *)tipsLabel {
  93. if (!_tipsLabel) {
  94. _tipsLabel = [[UILabel alloc] init];
  95. _tipsLabel.textColor = TIMCommonDynamicColor(@"nodata_tips_color", @"#999999");
  96. _tipsLabel.font = [UIFont systemFontOfSize:14.0];
  97. _tipsLabel.textAlignment = NSTextAlignmentCenter;
  98. _tipsLabel.hidden = YES;
  99. }
  100. return _tipsLabel;
  101. }
  102. - (void)setTipsViewFrame {
  103. self.tipsView.mm_width(128).mm_height(109).mm__centerX(self.mm_centerX).mm_top(200.0);
  104. self.tipsLabel.mm_width(300).mm_height(20).mm__centerX(self.mm_centerX).mm_top(self.tipsView.mm_maxY + 18);
  105. }
  106. - (void)updateTipsViewStatus {
  107. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  108. if (0 == self.dataProvider.conversationList.count) {
  109. self.tipsView.hidden = NO;
  110. self.tipsLabel.hidden = NO;
  111. self.tipsLabel.text = self.tipsMsgWhenNoConversation;
  112. } else {
  113. self.tipsView.hidden = YES;
  114. self.tipsLabel.hidden = YES;
  115. }
  116. });
  117. }
  118. - (void)setDataProvider:(TUIConversationListBaseDataProvider *)dataProvider {
  119. _dataProvider = dataProvider;
  120. if (_dataProvider) {
  121. _dataProvider.delegate = self;
  122. [_dataProvider loadNexPageConversations];
  123. }
  124. }
  125. - (TUIConversationListBaseDataProvider *)dataProvider {
  126. return _dataProvider;
  127. ;
  128. }
  129. - (void)dealloc {
  130. [NSNotificationCenter.defaultCenter removeObserver:self];
  131. }
  132. #pragma mark TUIConversationListDataProviderDelegate
  133. - (void)insertConversationsAtIndexPaths:(NSArray *)indexPaths {
  134. if (!NSThread.isMainThread) {
  135. __weak typeof(self) weakSelf = self;
  136. dispatch_async(dispatch_get_main_queue(), ^{
  137. [weakSelf insertConversationsAtIndexPaths:indexPaths];
  138. });
  139. return;
  140. }
  141. [UIView performWithoutAnimation:^{
  142. [self insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
  143. }];
  144. }
  145. - (void)reloadConversationsAtIndexPaths:(NSArray *)indexPaths {
  146. if (!NSThread.isMainThread) {
  147. __weak typeof(self) weakSelf = self;
  148. dispatch_async(dispatch_get_main_queue(), ^{
  149. [weakSelf reloadConversationsAtIndexPaths:indexPaths];
  150. });
  151. return;
  152. }
  153. if (self.isEditing) {
  154. self.editing = NO;
  155. }
  156. [UIView performWithoutAnimation:^{
  157. [self reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
  158. }];
  159. }
  160. - (void)deleteConversationAtIndexPaths:(NSArray *)indexPaths {
  161. if (!NSThread.isMainThread) {
  162. __weak typeof(self) weakSelf = self;
  163. dispatch_async(dispatch_get_main_queue(), ^{
  164. [weakSelf deleteConversationAtIndexPaths:indexPaths];
  165. });
  166. return;
  167. }
  168. [self deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
  169. }
  170. - (void)reloadAllConversations {
  171. if (!NSThread.isMainThread) {
  172. __weak typeof(self) weakSelf = self;
  173. dispatch_async(dispatch_get_main_queue(), ^{
  174. [weakSelf reloadAllConversations];
  175. });
  176. return;
  177. }
  178. [self reloadData];
  179. }
  180. - (void)updateMarkUnreadCount:(NSInteger)markUnreadCount markHideUnreadCount:(NSInteger)markHideUnreadCount {
  181. if (self.unreadCountChanged) {
  182. self.unreadCountChanged(markUnreadCount, markHideUnreadCount);
  183. }
  184. }
  185. - (void)parseActionHiddenTagAndCustomizedItems:(TUIConversationCellData *)cellData {
  186. id<TUIConversationConfigDataSource> dataSource = [TUIConversationConfig sharedConfig].moreMenuDataSource;
  187. NSArray *customizedItems = @[];
  188. if (dataSource && [dataSource respondsToSelector:@selector(conversationShouldHideItemsInMoreMenu:)]) {
  189. NSInteger flag = [dataSource conversationShouldHideItemsInMoreMenu:cellData];
  190. self.hideDeleteAction = flag & TUIConversationItemInMoreMenu_Delete;
  191. self.hideMarkReadAction = flag & TUIConversationItemInMoreMenu_MarkRead;
  192. self.hideHideAction = flag & TUIConversationItemInMoreMenu_Hide;
  193. }
  194. if (dataSource && [dataSource respondsToSelector:@selector(conversationShouldAddNewItemsToMoreMenu:)]) {
  195. NSArray *items = [dataSource conversationShouldAddNewItemsToMoreMenu:cellData];
  196. if ([items isKindOfClass:NSArray.class] && items.count > 0) {
  197. self.customizedItems = items;
  198. }
  199. }
  200. }
  201. #pragma mark - Table view data source
  202. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
  203. [self.dataProvider loadNexPageConversations];
  204. }
  205. - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  206. CGFloat offsetY = scrollView.contentOffset.y;
  207. if (self.convDelegate && [self.convDelegate respondsToSelector:@selector(tableViewDidScroll:)]) {
  208. [self.convDelegate tableViewDidScroll:offsetY];
  209. }
  210. }
  211. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  212. [self updateTipsViewStatus];
  213. return self.dataProvider.conversationList.count;
  214. }
  215. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  216. TUIConversationCellData *cellData = self.dataProvider.conversationList[indexPath.row];
  217. if([cellData.conversationID isEqualToString:@"c2c_10000"] || [cellData.conversationID isEqualToString:@"c2c_10001"]) {
  218. return 0.1;
  219. }
  220. else{
  221. return TConversationCell_Height;
  222. }
  223. }
  224. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
  225. return YES;
  226. }
  227. - (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
  228. TUIConversationCellData *cellData = self.dataProvider.conversationList[indexPath.row];
  229. NSMutableArray *rowActions = [NSMutableArray array];
  230. [self parseActionHiddenTagAndCustomizedItems:cellData];
  231. @weakify(self);
  232. if (cellData.isLocalConversationFoldList) {
  233. UITableViewRowAction *markHideAction =
  234. [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault
  235. title:TIMCommonLocalizableString(MarkHide)
  236. handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull indexPath) {
  237. @strongify(self);
  238. [self.dataProvider markConversationHide:cellData];
  239. if (cellData.isLocalConversationFoldList) {
  240. [TUIConversationListDataProvider cacheConversationFoldListSettings_HideFoldItem:YES];
  241. }
  242. }];
  243. markHideAction.backgroundColor = RGB(242, 147, 64);
  244. if (!self.hideHideAction) {
  245. [rowActions addObject:markHideAction];
  246. }
  247. return rowActions;
  248. }
  249. // Delete action
  250. UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive
  251. title:TIMCommonLocalizableString(Delete)
  252. handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull indexPath) {
  253. @strongify(self);
  254. TUISecondConfirmBtnInfo *cancelBtnInfo = [[TUISecondConfirmBtnInfo alloc] init];
  255. cancelBtnInfo.tile = TIMCommonLocalizableString(Cancel);
  256. cancelBtnInfo.click = ^{
  257. self.editing = NO;
  258. };
  259. TUISecondConfirmBtnInfo *confirmBtnInfo = [[TUISecondConfirmBtnInfo alloc] init];
  260. confirmBtnInfo.tile = TIMCommonLocalizableString(Delete);
  261. confirmBtnInfo.click = ^{
  262. [self.dataProvider removeConversation:cellData];
  263. self.editing = NO;
  264. };
  265. [TUISecondConfirm show:TIMCommonLocalizableString(TUIKitConversationTipsDelete)
  266. cancelBtnInfo:cancelBtnInfo
  267. confirmBtnInfo:confirmBtnInfo];
  268. }];
  269. deleteAction.backgroundColor = RGB(242, 77, 76);
  270. if (!self.hideDeleteAction) {
  271. [rowActions addObject:deleteAction];
  272. }
  273. // MarkAsRead action
  274. UITableViewRowAction *markAsReadAction =
  275. [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault
  276. title:(cellData.isMarkAsUnread || cellData.unreadCount > 0) ? TIMCommonLocalizableString(MarkAsRead)
  277. : TIMCommonLocalizableString(MarkAsUnRead)
  278. handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull indexPath) {
  279. @strongify(self);
  280. if (cellData.isMarkAsUnread || cellData.unreadCount > 0) {
  281. [self.dataProvider markConversationAsRead:cellData];
  282. if (cellData.isLocalConversationFoldList) {
  283. [TUIConversationListDataProvider cacheConversationFoldListSettings_FoldItemIsUnread:NO];
  284. }
  285. } else {
  286. [self.dataProvider markConversationAsUnRead:cellData];
  287. if (cellData.isLocalConversationFoldList) {
  288. [TUIConversationListDataProvider cacheConversationFoldListSettings_FoldItemIsUnread:YES];
  289. }
  290. }
  291. }];
  292. markAsReadAction.backgroundColor = RGB(20, 122, 255);
  293. if (!self.hideMarkReadAction) {
  294. [rowActions addObject:markAsReadAction];
  295. }
  296. // More action
  297. NSArray *moreExtensionList =
  298. [TUICore getExtensionList:TUICore_TUIConversationExtension_ConversationCellMoreAction_ClassicExtensionID
  299. param:@{
  300. TUICore_TUIConversationExtension_ConversationCellAction_ConversationIDKey : cellData.conversationID,
  301. TUICore_TUIConversationExtension_ConversationCellAction_MarkListKey : cellData.conversationMarkList ?: @[],
  302. TUICore_TUIConversationExtension_ConversationCellAction_GroupListKey : cellData.conversationGroupList ?: @[]
  303. }];
  304. if (self.disableMoreActionExtension || 0 == moreExtensionList.count) {
  305. UITableViewRowAction *markAsHideAction =
  306. [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive
  307. title:TIMCommonLocalizableString(MarkHide)
  308. handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull indexPath) {
  309. @strongify(self);
  310. [self.dataProvider markConversationHide:cellData];
  311. if (cellData.isLocalConversationFoldList) {
  312. [TUIConversationListDataProvider cacheConversationFoldListSettings_HideFoldItem:YES];
  313. }
  314. }];
  315. markAsHideAction.backgroundColor = RGB(242, 147, 64);
  316. if (!self.hideHideAction) {
  317. [rowActions addObject:markAsHideAction];
  318. }
  319. } else {
  320. UITableViewRowAction *moreAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive
  321. title:TIMCommonLocalizableString(More)
  322. handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull indexPath) {
  323. @strongify(self);
  324. self.editing = NO;
  325. [self showMoreAction:cellData extensionList:moreExtensionList];
  326. }];
  327. moreAction.backgroundColor = RGB(242, 147, 64);
  328. [rowActions addObject:moreAction];
  329. }
  330. return rowActions;
  331. }
  332. // available ios 11 +
  333. - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView
  334. trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0)) {
  335. TUIConversationCellData *cellData = self.dataProvider.conversationList[indexPath.row];
  336. [self parseActionHiddenTagAndCustomizedItems:cellData];
  337. // config Actions
  338. @weakify(self);
  339. if (cellData.isLocalConversationFoldList && !self.hideHideAction) {
  340. UIContextualAction *markHideAction = [UIContextualAction
  341. contextualActionWithStyle:UIContextualActionStyleNormal
  342. title:TIMCommonLocalizableString(MarkHide)
  343. handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) {
  344. @strongify(self);
  345. [self.dataProvider markConversationHide:cellData];
  346. if (cellData.isLocalConversationFoldList) {
  347. [TUIConversationListDataProvider cacheConversationFoldListSettings_HideFoldItem:YES];
  348. }
  349. }];
  350. markHideAction.backgroundColor = RGB(242, 147, 64);
  351. UISwipeActionsConfiguration *configuration = [UISwipeActionsConfiguration configurationWithActions:@[ markHideAction ]];
  352. configuration.performsFirstActionWithFullSwipe = NO;
  353. return configuration;
  354. }
  355. NSMutableArray *arrayM = [NSMutableArray array];
  356. // Delete action
  357. UIContextualAction *deleteAction = [UIContextualAction
  358. contextualActionWithStyle:UIContextualActionStyleNormal
  359. title:TIMCommonLocalizableString(Delete)
  360. handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) {
  361. @strongify(self);
  362. TUISecondConfirmBtnInfo *cancelBtnInfo = [[TUISecondConfirmBtnInfo alloc] init];
  363. cancelBtnInfo.tile = TIMCommonLocalizableString(Cancel);
  364. cancelBtnInfo.click = ^{
  365. self.editing = NO;
  366. };
  367. TUISecondConfirmBtnInfo *confirmBtnInfo = [[TUISecondConfirmBtnInfo alloc] init];
  368. confirmBtnInfo.tile = TIMCommonLocalizableString(Delete);
  369. confirmBtnInfo.click = ^{
  370. [self.dataProvider removeConversation:cellData];
  371. self.editing = NO;
  372. };
  373. [TUISecondConfirm show:TIMCommonLocalizableString(TUIKitConversationTipsDelete)
  374. cancelBtnInfo:cancelBtnInfo
  375. confirmBtnInfo:confirmBtnInfo];
  376. }];
  377. deleteAction.backgroundColor = RGB(242, 77, 76);
  378. if (!self.hideDeleteAction) {
  379. [arrayM addObject:deleteAction];
  380. }
  381. // MarkAsRead action
  382. UIContextualAction *markAsReadAction = [UIContextualAction
  383. contextualActionWithStyle:UIContextualActionStyleNormal
  384. title:(cellData.isMarkAsUnread || cellData.unreadCount > 0) ? TIMCommonLocalizableString(MarkAsRead)
  385. : TIMCommonLocalizableString(MarkAsUnRead)
  386. handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) {
  387. @strongify(self);
  388. if (cellData.isMarkAsUnread || cellData.unreadCount > 0) {
  389. [self.dataProvider markConversationAsRead:cellData];
  390. if (cellData.isLocalConversationFoldList) {
  391. [TUIConversationListDataProvider cacheConversationFoldListSettings_FoldItemIsUnread:NO];
  392. }
  393. } else {
  394. [self.dataProvider markConversationAsUnRead:cellData];
  395. if (cellData.isLocalConversationFoldList) {
  396. [TUIConversationListDataProvider cacheConversationFoldListSettings_FoldItemIsUnread:YES];
  397. }
  398. }
  399. }];
  400. markAsReadAction.backgroundColor = RGB(20, 122, 255);
  401. if (!self.hideMarkReadAction) {
  402. [arrayM addObject:markAsReadAction];
  403. }
  404. // More action
  405. NSArray *moreExtensionList =
  406. [TUICore getExtensionList:TUICore_TUIConversationExtension_ConversationCellMoreAction_ClassicExtensionID
  407. param:@{
  408. TUICore_TUIConversationExtension_ConversationCellAction_ConversationIDKey : cellData.conversationID,
  409. TUICore_TUIConversationExtension_ConversationCellAction_MarkListKey : cellData.conversationMarkList ?: @[],
  410. TUICore_TUIConversationExtension_ConversationCellAction_GroupListKey : cellData.conversationGroupList ?: @[],
  411. }];
  412. if (self.disableMoreActionExtension || 0 == moreExtensionList.count) {
  413. UIContextualAction *markAsHideAction = [UIContextualAction
  414. contextualActionWithStyle:UIContextualActionStyleNormal
  415. title:TIMCommonLocalizableString(MarkHide)
  416. handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) {
  417. @strongify(self);
  418. [self.dataProvider markConversationHide:cellData];
  419. if (cellData.isLocalConversationFoldList) {
  420. [TUIConversationListDataProvider cacheConversationFoldListSettings_HideFoldItem:YES];
  421. }
  422. }];
  423. markAsHideAction.backgroundColor = RGB(242, 147, 64);
  424. if (!self.hideHideAction) {
  425. [arrayM addObject:markAsHideAction];
  426. }
  427. } else {
  428. UIContextualAction *moreAction = [UIContextualAction
  429. contextualActionWithStyle:UIContextualActionStyleNormal
  430. title:TIMCommonLocalizableString(More)
  431. handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) {
  432. @strongify(self);
  433. self.editing = NO;
  434. [self showMoreAction:cellData extensionList:moreExtensionList];
  435. }];
  436. moreAction.backgroundColor = RGB(242, 147, 64);
  437. [arrayM addObject:moreAction];
  438. }
  439. UISwipeActionsConfiguration *configuration = [UISwipeActionsConfiguration configurationWithActions:[NSArray arrayWithArray:arrayM]];
  440. configuration.performsFirstActionWithFullSwipe = NO;
  441. return configuration;
  442. }
  443. // MARK: action
  444. - (void)showMoreAction:(TUIConversationCellData *)cellData extensionList:(NSArray *)extensionList {
  445. UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
  446. __weak typeof(self) weakSelf = self;
  447. if (self.customizedItems.count > 0) {
  448. for (UIAlertAction *action in self.customizedItems) {
  449. [ac tuitheme_addAction:action];
  450. }
  451. }
  452. if (!self.hideHideAction) {
  453. [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(MarkHide)
  454. style:UIAlertActionStyleDefault
  455. handler:^(UIAlertAction *_Nonnull action) {
  456. __strong typeof(weakSelf) strongSelf = weakSelf;
  457. [strongSelf.dataProvider markConversationHide:cellData];
  458. if (cellData.isLocalConversationFoldList) {
  459. [TUIConversationListDataProvider cacheConversationFoldListSettings_HideFoldItem:YES];
  460. }
  461. }]];
  462. }
  463. [self addCustomAction:ac cellData:cellData];
  464. [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Cancel) style:UIAlertActionStyleCancel handler:nil]];
  465. if (self.convDelegate && [self.convDelegate respondsToSelector:@selector(tableViewDidShowAlert:)]) {
  466. [self.convDelegate tableViewDidShowAlert:ac];
  467. }
  468. }
  469. - (void)addCustomAction:(UIAlertController *)ac cellData:(TUIConversationCellData *)cellData {
  470. NSArray *extensionList =
  471. [TUICore getExtensionList:TUICore_TUIConversationExtension_ConversationCellMoreAction_ClassicExtensionID
  472. param:@{
  473. TUICore_TUIConversationExtension_ConversationCellAction_ConversationIDKey : cellData.conversationID,
  474. TUICore_TUIConversationExtension_ConversationCellAction_MarkListKey : cellData.conversationMarkList ?: @[],
  475. TUICore_TUIConversationExtension_ConversationCellAction_GroupListKey : cellData.conversationGroupList ?: @[]
  476. }];
  477. for (TUIExtensionInfo *info in extensionList) {
  478. UIAlertAction *action = [UIAlertAction actionWithTitle:info.text
  479. style:UIAlertActionStyleDefault
  480. handler:^(UIAlertAction *_Nonnull action) {
  481. info.onClicked(@{});
  482. }];
  483. [ac tuitheme_addAction:action];
  484. }
  485. }
  486. - (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
  487. return NO;
  488. }
  489. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  490. TUIConversationCellData *cellData = self.dataProvider.conversationList[indexPath.row];
  491. if([cellData.conversationID isEqualToString:@"c2c_10000"] || [cellData.conversationID isEqualToString:@"c2c_10001"]) {
  492. MOConversationEmptyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MOConversationEmptyCell" forIndexPath:indexPath];
  493. return cell;
  494. }
  495. TUIConversationCell *cell = [tableView dequeueReusableCellWithIdentifier:gConversationCell_ReuseId forIndexPath:indexPath];
  496. if (cell && indexPath.row < self.dataProvider.conversationList.count) {
  497. TUIConversationCellData *data = [self.dataProvider.conversationList objectAtIndex:indexPath.row];
  498. [self tableViewFillCell:cell withData:data];
  499. NSArray *extensionList =
  500. [TUICore getExtensionList:TUICore_TUIConversationExtension_ConversationCellUpperRightCorner_ClassicExtensionID
  501. param:@{
  502. TUICore_TUIConversationExtension_ConversationCellUpperRightCorner_GroupListKey : data.conversationGroupList ?: @[],
  503. TUICore_TUIConversationExtension_ConversationCellUpperRightCorner_MarkListKey : data.conversationMarkList ?: @[],
  504. }];
  505. if (extensionList.count > 0) {
  506. TUIExtensionInfo *info = extensionList.firstObject;
  507. if (info.text.length > 0) {
  508. cell.timeLabel.text = info.text;
  509. } else if (info.icon) {
  510. NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
  511. textAttachment.image = info.icon;
  512. NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];
  513. cell.timeLabel.attributedText = imageStr;
  514. }
  515. }
  516. }
  517. return cell;
  518. }
  519. - (void)tableViewFillCell:(TUIConversationCell *)cell withData:(TUIConversationCellData *)data {
  520. [cell fillWithData:data];
  521. }
  522. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  523. TUIConversationCellData *data = [self.dataProvider.conversationList objectAtIndex:indexPath.row];
  524. [self tableViewDidSelectCell:data];
  525. }
  526. - (void)tableViewDidSelectCell:(TUIConversationCellData *)data {
  527. if (self.convDelegate && [self.convDelegate respondsToSelector:@selector(tableViewDidSelectCell:)]) {
  528. [self.convDelegate tableViewDidSelectCell:data];
  529. }
  530. }
  531. - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
  532. // Turn on or off the length of the last line of dividers by controlling this switch
  533. BOOL needLastLineFromZeroToMax = NO;
  534. if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
  535. [cell setSeparatorInset:UIEdgeInsetsMake(0, 82, 0, 0)];
  536. if (needLastLineFromZeroToMax && indexPath.row == (self.dataProvider.conversationList.count - 1)) {
  537. [cell setSeparatorInset:UIEdgeInsetsZero];
  538. }
  539. }
  540. // Prevent the cell from inheriting the Table View's margin settings
  541. if (needLastLineFromZeroToMax && [cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
  542. [cell setPreservesSuperviewLayoutMargins:NO];
  543. }
  544. // Explictly set your cell's layout margins
  545. if (needLastLineFromZeroToMax && [cell respondsToSelector:@selector(setLayoutMargins:)]) {
  546. [cell setLayoutMargins:UIEdgeInsetsZero];
  547. }
  548. }
  549. @end