NIMMessageCell.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. //
  2. // NIMMessageCell.m
  3. // NIMKit
  4. //
  5. // Created by chris.
  6. // Copyright (c) 2015年 NetEase. All rights reserved.
  7. //
  8. #import "NIMMessageCell.h"
  9. #import "NIMMessageModel.h"
  10. #import "NIMAvatarImageView.h"
  11. #import "NIMBadgeView.h"
  12. #import "NIMSessionMessageContentView.h"
  13. #import "NIMKitUtil.h"
  14. #import "NIMSessionAudioContentView.h"
  15. #import "UIView+NIM.h"
  16. #import "NIMKitDependency.h"
  17. #import "M80AttributedLabel.h"
  18. #import "UIImage+NIMKit.h"
  19. #import "NIMSessionUnknowContentView.h"
  20. #import "NIMKitConfig.h"
  21. #import "NIMKit.h"
  22. @interface NIMMessageCell()<NIMPlayAudioUIDelegate,NIMMessageContentViewDelegate>
  23. {
  24. UILongPressGestureRecognizer *_longPressGesture;
  25. UIMenuController *_menuController;
  26. }
  27. @property (nonatomic,strong) NIMMessageModel *model;
  28. @property (nonatomic,copy) NSArray *customViews;
  29. @end
  30. @implementation NIMMessageCell
  31. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  32. {
  33. if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]) {
  34. self.selectionStyle = UITableViewCellSelectionStyleNone;
  35. [self makeComponents];
  36. [self makeGesture];
  37. }
  38. return self;
  39. }
  40. - (void)dealloc
  41. {
  42. [self removeGestureRecognizer:_longPressGesture];
  43. }
  44. - (void)makeComponents
  45. {
  46. // static UIImage *NIMRetryButtonImage;
  47. // static dispatch_once_t onceToken;
  48. // dispatch_once(&onceToken, ^{
  49. // NIMRetryButtonImage = [UIImage nim_imageInKit:@"icon_message_cell_error"];
  50. // });
  51. //retyrBtn
  52. // _retryButton = [UIButton buttonWithType:UIButtonTypeCustom];
  53. // [_retryButton setImage:NIMRetryButtonImage forState:UIControlStateNormal];
  54. // [_retryButton setImage:NIMRetryButtonImage forState:UIControlStateHighlighted];
  55. // [_retryButton setFrame:CGRectMake(0, 0, 20, 20)];
  56. // [_retryButton addTarget:self action:@selector(onRetryMessage:) forControlEvents:UIControlEventTouchUpInside];
  57. // [self.contentView addSubview:_retryButton];
  58. _retryButton = [UIButton buttonWithType:UIButtonTypeCustom];
  59. _retryButton.opaque = YES;
  60. _retryButton.titleLabel.font = [NIMKit sharedKit].config.sendFailFont;
  61. [_retryButton setTitleColor:[NIMKit sharedKit].config.sendFailColor forState:UIControlStateNormal];
  62. [_retryButton setTitleColor:[NIMKit sharedKit].config.sendFailColor forState:UIControlStateHighlighted];
  63. [_retryButton setTitle:@"重试" forState:UIControlStateNormal];
  64. [_retryButton setHidden:YES];
  65. [_retryButton addTarget:self action:@selector(onRetryMessage:) forControlEvents:UIControlEventTouchUpInside];
  66. [self.contentView addSubview:_retryButton];
  67. [_retryButton sizeToFit];
  68. _priBtnButton = [UIButton buttonWithType:UIButtonTypeCustom];
  69. _priBtnButton.adjustsImageWhenHighlighted = NO;
  70. // [_priBtnButton setFrame:CGRectMake(0, 0, 20, 20)];
  71. [_priBtnButton setImage:[UIImage imageNamed:@"vqu_images_im_coin"] forState:UIControlStateNormal];
  72. _priBtnButton.titleLabel.font = LCFont12;
  73. [_priBtnButton setTitleColor:LZA3AABEColor forState:UIControlStateNormal];
  74. [_priBtnButton addTarget:self action:@selector(onPriBtnButtonMessage:) forControlEvents:UIControlEventTouchUpInside];
  75. // _priBtnButton.backgroundColor = LCOrangeColor;
  76. // _priBtnButton.layer.cornerRadius = 10;
  77. [_priBtnButton setEnlargeEdge:30];
  78. // _priBtnButton.layer.masksToBounds = YES;
  79. [self.contentView addSubview:_priBtnButton];
  80. //audioPlayedIcon
  81. _audioPlayedIcon = [NIMBadgeView viewWithBadgeTip:@""];
  82. [self.contentView addSubview:_audioPlayedIcon];
  83. //traningActivityIndicator
  84. _traningActivityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0,0,20,20)];
  85. [self.contentView addSubview:_traningActivityIndicator];
  86. //headerView
  87. _headImageView = [[NIMAvatarImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
  88. [_headImageView addTarget:self action:@selector(onTapAvatar:) forControlEvents:UIControlEventTouchUpInside];
  89. UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressAvatar:)];
  90. [_headImageView addGestureRecognizer:gesture];
  91. [self.contentView addSubview:_headImageView];
  92. //nicknamel
  93. _nameLabel = [[UILabel alloc] init];
  94. _nameLabel.backgroundColor = [UIColor clearColor];
  95. _nameLabel.opaque = YES;
  96. _nameLabel.font = [NIMKit sharedKit].config.nickFont;
  97. _nameLabel.textColor = [NIMKit sharedKit].config.nickColor;
  98. [_nameLabel setHidden:YES];
  99. [self.contentView addSubview:_nameLabel];
  100. //readlabel
  101. _readButton = [UIButton buttonWithType:UIButtonTypeCustom];
  102. _readButton.opaque = YES;
  103. _readButton.titleLabel.font = [NIMKit sharedKit].config.receiptFont;
  104. [_readButton setTitleColor:[NIMKit sharedKit].config.receiptColor forState:UIControlStateNormal];
  105. [_readButton setTitleColor:[NIMKit sharedKit].config.receiptColor forState:UIControlStateHighlighted];
  106. [_readButton setHidden:YES];
  107. [_readButton addTarget:self action:@selector(onPressReadButton:) forControlEvents:UIControlEventTouchUpInside];
  108. [self.contentView addSubview:_readButton];
  109. _sendSuccessBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  110. _sendSuccessBtn.opaque = YES;
  111. _sendSuccessBtn.titleLabel.font = [NIMKit sharedKit].config.sendSuccessFont;
  112. [_sendSuccessBtn setTitleColor:[NIMKit sharedKit].config.sendSuccessColor forState:UIControlStateNormal];
  113. [_sendSuccessBtn setTitleColor:[NIMKit sharedKit].config.sendSuccessColor forState:UIControlStateHighlighted];
  114. [_sendSuccessBtn setHidden:YES];
  115. // [_sendSuccessBtn addTarget:self action:@selector(onPressReadButton:) forControlEvents:UIControlEventTouchUpInside];
  116. [self.contentView addSubview:_sendSuccessBtn];
  117. }
  118. - (void)makeGesture{
  119. _longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGesturePress:)];
  120. [self addGestureRecognizer:_longPressGesture];
  121. }
  122. - (void)refreshData:(NIMMessageModel *)data
  123. {
  124. self.model = data;
  125. if ([self checkData])
  126. {
  127. [self refresh];
  128. }
  129. }
  130. - (BOOL)checkData{
  131. return [self.model isKindOfClass:[NIMMessageModel class]];
  132. }
  133. - (void)refresh
  134. {
  135. [self addContentViewIfNotExist];
  136. [self addUserCustomViews];
  137. self.backgroundColor = [NIMKit sharedKit].config.cellBackgroundColor;
  138. if ([self needShowAvatar])
  139. {
  140. [_headImageView setAvatarByMessage:self.model.message];
  141. }
  142. if([self needShowNickName])
  143. {
  144. NSString *nick = [NIMKitUtil showNick:self.model.message.from inMessage:self.model.message];
  145. [self.nameLabel setText:nick];
  146. }
  147. [_nameLabel setHidden:![self needShowNickName]];
  148. [_bubbleView refresh:self.model];
  149. [_bubbleView setNeedsLayout];
  150. BOOL isActivityIndicatorHidden = [self activityIndicatorHidden];
  151. if (isActivityIndicatorHidden)
  152. {
  153. [_traningActivityIndicator stopAnimating];
  154. }
  155. else
  156. {
  157. [_traningActivityIndicator startAnimating];
  158. }
  159. [_traningActivityIndicator setHidden:isActivityIndicatorHidden];
  160. [_retryButton setHidden:[self retryButtonHidden]];
  161. [_priBtnButton setHidden:[self priBtnButtonHidden]];
  162. [_audioPlayedIcon setHidden:[self unreadHidden]];
  163. [self refreshReadButton];
  164. [self refreshSendSuccessBtn];
  165. [self setNeedsLayout];
  166. }
  167. - (void)refreshReadButton
  168. {
  169. BOOL hidden = [self readLabelHidden];
  170. [_readButton setHidden:hidden];
  171. if (!hidden)
  172. {
  173. if (self.model.message.session.sessionType == NIMSessionTypeP2P)
  174. {
  175. [_readButton setTitle:@"已读" forState:UIControlStateNormal];
  176. [_readButton sizeToFit];
  177. }
  178. else if(self.model.message.session.sessionType == NIMSessionTypeTeam)
  179. {
  180. [_readButton setTitle:[NSString stringWithFormat:@"%zd人未读",self.model.message.teamReceiptInfo.unreadCount] forState:UIControlStateNormal];
  181. [_readButton sizeToFit];
  182. }
  183. }
  184. }
  185. - (void)refreshSendSuccessBtn
  186. {
  187. BOOL hidden = [self sendSuccessLabelHidden];
  188. [_sendSuccessBtn setHidden:hidden];
  189. if (!hidden)
  190. {
  191. [_sendSuccessBtn setTitle:@"送达" forState:UIControlStateNormal];
  192. [_sendSuccessBtn sizeToFit];
  193. }
  194. }
  195. - (void)addContentViewIfNotExist
  196. {
  197. if (_bubbleView == nil)
  198. {
  199. id<NIMCellLayoutConfig> layoutConfig = [[NIMKit sharedKit] layoutConfig];
  200. NSString *contentStr = [layoutConfig cellContent:self.model];
  201. NSAssert([contentStr length] > 0, @"should offer cell content class name");
  202. Class clazz = NSClassFromString(contentStr);
  203. NIMSessionMessageContentView *contentView = [[clazz alloc] initSessionMessageContentView];
  204. NSAssert(contentView, @"can not init content view");
  205. _bubbleView = contentView;
  206. _bubbleView.delegate = self;
  207. NIMMessageType messageType = self.model.message.messageType;
  208. if (messageType == NIMMessageTypeAudio) {
  209. ((NIMSessionAudioContentView *)_bubbleView).audioUIDelegate = self;
  210. }
  211. [self.contentView addSubview:_bubbleView];
  212. }
  213. }
  214. - (void)addUserCustomViews
  215. {
  216. for (UIView *view in self.customViews) {
  217. [view removeFromSuperview];
  218. }
  219. id<NIMCellLayoutConfig> layoutConfig = [[NIMKit sharedKit] layoutConfig];
  220. self.customViews = [layoutConfig customViews:self.model];
  221. for (UIView *view in self.customViews) {
  222. [self.contentView addSubview:view];
  223. }
  224. }
  225. - (void)layoutSubviews
  226. {
  227. [super layoutSubviews];
  228. [self layoutAvatar];
  229. [self layoutNameLabel];
  230. [self layoutBubbleView];
  231. [self layoutRetryButton];
  232. [self layoutPriBtnButton];
  233. [self layoutAudioPlayedIcon];
  234. [self layoutActivityIndicator];
  235. [self layoutReadButton];
  236. [self layoutSendSuccessButton];
  237. }
  238. - (void)layoutAvatar
  239. {
  240. BOOL needShow = [self needShowAvatar];
  241. _headImageView.hidden = !needShow;
  242. if (needShow) {
  243. _headImageView.frame = [self avatarViewRect];
  244. }
  245. }
  246. - (void)layoutNameLabel
  247. {
  248. if ([self needShowNickName]) {
  249. CGFloat otherBubbleOriginX = self.cellPaddingToNick.x;
  250. CGFloat otherBubbleOriginy = self.cellPaddingToNick.y;
  251. CGFloat otherNickNameWidth = 200.f;
  252. CGFloat otherNickNameHeight = 20.f;
  253. CGFloat cellPaddingToProtrait = self.cellPaddingToAvatar.x;
  254. CGFloat avatarWidth = self.headImageView.nim_width;
  255. CGFloat myBubbleOriginX = self.nim_width - cellPaddingToProtrait - avatarWidth - self.cellPaddingToNick.x;
  256. _nameLabel.frame = self.model.shouldShowLeft ? CGRectMake(otherBubbleOriginX,otherBubbleOriginy,
  257. otherNickNameWidth, otherNickNameHeight) : CGRectMake(myBubbleOriginX,otherBubbleOriginy, otherNickNameWidth,otherNickNameHeight) ;
  258. }
  259. }
  260. - (void)layoutBubbleView
  261. {
  262. CGSize size = [self.model contentSize:self.nim_width];
  263. UIEdgeInsets insets = self.model.contentViewInsets;
  264. size.width = size.width + insets.left + insets.right;
  265. size.height = size.height + insets.top + insets.bottom;
  266. _bubbleView.nim_size = size;
  267. UIEdgeInsets contentInsets = self.model.bubbleViewInsets;
  268. if (!self.model.shouldShowLeft)
  269. {
  270. CGFloat protraitRightToBubble = 5.f;
  271. CGFloat right = self.model.shouldShowAvatar? CGRectGetMinX(self.headImageView.frame) - protraitRightToBubble : self.nim_width;
  272. contentInsets.left = right - CGRectGetWidth(self.bubbleView.bounds);
  273. }
  274. _bubbleView.nim_left = contentInsets.left;
  275. _bubbleView.nim_top = contentInsets.top;
  276. }
  277. - (void)layoutActivityIndicator
  278. {
  279. if (_traningActivityIndicator.isAnimating) {
  280. CGFloat centerX = 0;
  281. if (!self.model.shouldShowLeft)
  282. {
  283. centerX = CGRectGetMinX(_bubbleView.frame) - [self retryButtonBubblePadding] - CGRectGetWidth(_traningActivityIndicator.bounds)/2;;
  284. }
  285. else
  286. {
  287. centerX = CGRectGetMaxX(_bubbleView.frame) + [self retryButtonBubblePadding] + CGRectGetWidth(_traningActivityIndicator.bounds)/2;
  288. }
  289. self.traningActivityIndicator.center = CGPointMake(centerX,
  290. _bubbleView.center.y);
  291. }
  292. }
  293. - (void)layoutRetryButton
  294. {
  295. if (!_retryButton.isHidden) {
  296. CGFloat centerX = 0;
  297. if (self.model.shouldShowLeft)
  298. {
  299. centerX = CGRectGetMaxX(_bubbleView.frame) + [self retryButtonBubblePadding] +CGRectGetWidth(_retryButton.bounds)/2;
  300. }
  301. else
  302. {
  303. centerX = CGRectGetMinX(_bubbleView.frame) - [self retryButtonBubblePadding] - CGRectGetWidth(_retryButton.bounds)/2;
  304. }
  305. _retryButton.center = CGPointMake(centerX, _bubbleView.center.y);
  306. }
  307. }
  308. - (void)layoutPriBtnButton{
  309. if (!_priBtnButton.isHidden) {
  310. // CGFloat centerX = 0;
  311. // if (!self.model.message.isOutgoingMsg)
  312. // {
  313. // centerX = CGRectGetMaxX(_bubbleView.frame) + 5 +CGRectGetWidth(_retryButton.bounds)/2;
  314. // }
  315. // else
  316. // {
  317. // centerX = CGRectGetMinX(_bubbleView.frame) - 5 - CGRectGetWidth(_retryButton.bounds)/2;
  318. // }
  319. _priBtnButton.mj_y = CGRectGetMaxY(_bubbleView.frame) + 6.0f;
  320. _priBtnButton.mj_x = _bubbleView.mj_x;
  321. // _priBtnButton.center = CGPointMake(CGRectGetMaxX(_bubbleView.frame) + 6, CGRectGetMaxY(_bubbleView.frame)-15);
  322. }
  323. }
  324. - (void)layoutAudioPlayedIcon{
  325. if (!_audioPlayedIcon.hidden) {
  326. CGFloat padding = [self audioPlayedIconBubblePadding];
  327. if (self.model.shouldShowLeft)
  328. {
  329. _audioPlayedIcon.nim_left = _bubbleView.nim_right + padding;
  330. }
  331. else
  332. {
  333. _audioPlayedIcon.nim_right = _bubbleView.nim_left - padding;
  334. }
  335. _audioPlayedIcon.nim_top = _bubbleView.nim_top;
  336. }
  337. }
  338. - (void)layoutReadButton{
  339. if (!_readButton.isHidden) {
  340. CGFloat left = _bubbleView.nim_left;
  341. // CGFloat bottom = _bubbleView.nim_bottom;
  342. _readButton.nim_left = left - CGRectGetWidth(_readButton.bounds) - [self readButtonBubblePadding];
  343. _readButton.nim_centerY = _bubbleView.nim_centerY;
  344. }
  345. }
  346. - (void)layoutSendSuccessButton{
  347. if (!_sendSuccessBtn.isHidden) {
  348. CGFloat left = _bubbleView.nim_left;
  349. _sendSuccessBtn.nim_left = left - CGRectGetWidth(_sendSuccessBtn.bounds) - [self sendSuccessButtonBubblePadding];
  350. _sendSuccessBtn.nim_centerY = _bubbleView.nim_centerY;
  351. }
  352. }
  353. #pragma mark - NIMMessageContentViewDelegate
  354. - (void)onCatchEvent:(NIMKitEvent *)event{
  355. if ([self.delegate respondsToSelector:@selector(onTapCell:)]) {
  356. [self.delegate onTapCell:event];
  357. }
  358. }
  359. #pragma mark - Action
  360. - (void)onPriBtnButtonMessage:(id)sender{
  361. if (self.delegate && [self.delegate respondsToSelector:@selector(onPriBtnButtonMessage:)]) {
  362. [self.delegate onPriBtnButtonMessage:self.model.message];
  363. }
  364. }
  365. - (void)onRetryMessage:(id)sender
  366. {
  367. if (self.delegate && [self.delegate respondsToSelector:@selector(onRetryMessage:)]) {
  368. [self.delegate onRetryMessage:self.model.message];
  369. }
  370. }
  371. - (void)longGesturePress:(UIGestureRecognizer *)gestureRecognizer
  372. {
  373. if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] &&
  374. gestureRecognizer.state == UIGestureRecognizerStateBegan) {
  375. if (self.delegate && [self.delegate respondsToSelector:@selector(onLongPressCell:inView:)]) {
  376. [self.delegate onLongPressCell:self.model.message
  377. inView:_bubbleView];
  378. }
  379. }
  380. }
  381. #pragma mark - NIMPlayAudioUIDelegate
  382. - (void)startPlayingAudioUI
  383. {
  384. [self refreshData:self.model];
  385. }
  386. - (void)retryDownloadMsg
  387. {
  388. [self onRetryMessage:nil];
  389. }
  390. #pragma mark - Private
  391. - (CGRect)avatarViewRect
  392. {
  393. CGFloat cellWidth = self.bounds.size.width;
  394. CGFloat cellHeight = self.bounds.size.height;
  395. CGFloat protraitImageWidth = [self avatarSize].width;
  396. CGFloat protraitImageHeight = [self avatarSize].height;
  397. CGFloat selfProtraitOriginX = (cellWidth - self.cellPaddingToAvatar.x - protraitImageWidth);
  398. CGFloat avatarY = self.cellPaddingToAvatar.y;
  399. if ([self.bubbleView isKindOfClass:NSClassFromString(@"YOUPAILCGiftContentView")]) {
  400. avatarY = (cellHeight - protraitImageHeight) / 2;
  401. }
  402. return self.model.shouldShowLeft ? CGRectMake(self.cellPaddingToAvatar.x, avatarY,protraitImageWidth, protraitImageHeight) : CGRectMake(selfProtraitOriginX, avatarY,protraitImageWidth,protraitImageHeight);
  403. }
  404. - (BOOL)needShowAvatar
  405. {
  406. return self.model.shouldShowAvatar;
  407. }
  408. - (BOOL)needShowNickName
  409. {
  410. return self.model.shouldShowNickName;
  411. }
  412. - (BOOL)retryButtonHidden
  413. {
  414. id<NIMCellLayoutConfig> layoutConfig = [[NIMKit sharedKit] layoutConfig];
  415. BOOL disable = NO;
  416. if ([layoutConfig respondsToSelector:@selector(disableRetryButton:)])
  417. {
  418. disable = [layoutConfig disableRetryButton:self.model];
  419. }
  420. return disable;
  421. }
  422. - (BOOL)priBtnButtonHidden{
  423. BOOL messageType = (self.model.message.messageType != NIMMessageTypeText &&
  424. self.model.message.messageType != NIMMessageTypeImage &&
  425. self.model.message.messageType != NIMMessageTypeAudio &&
  426. self.model.message.messageType != NIMMessageTypeVideo);
  427. BOOL isspecial = [LCSaveData getIsspecial];
  428. BOOL is_cut = [[self.model.message.remoteExt objectForKey:@"is_cut"]integerValue] != 1;
  429. BOOL isWhite= [LCSaveData getWhiteVersion];
  430. if (messageType ||
  431. isspecial ||
  432. is_cut ||
  433. isWhite) {
  434. return YES;
  435. }
  436. if (!self.model.message.isOutgoingMsg) {
  437. NSInteger cut = [[self.model.message.remoteExt objectForKey:@"is_cut"]integerValue];
  438. NSString *money = [self.model.message.remoteExt objectForKey:@"money"];
  439. if (cut==1) {
  440. [_priBtnButton setTitle:[NSString stringWithFormat:@"+%@元",money] forState:(UIControlStateNormal)];
  441. [_priBtnButton sizeToFit];
  442. _priBtnButton.mj_h = 16.0f;
  443. [_priBtnButton setTitleColor:LZA3AABEColor forState:(UIControlStateNormal)];
  444. return NO;
  445. }else{
  446. return YES;
  447. }
  448. }else{
  449. return YES;
  450. }
  451. }
  452. - (CGFloat)retryButtonBubblePadding {
  453. BOOL isFromMe = !self.model.shouldShowLeft;
  454. if (self.model.message.messageType == NIMMessageTypeAudio) {
  455. return isFromMe ? 11 : 9;
  456. }
  457. return isFromMe ? 4 : 6;
  458. }
  459. - (BOOL)activityIndicatorHidden
  460. {
  461. if (!self.model.message.isReceivedMsg)
  462. {
  463. return self.model.message.deliveryState != NIMMessageDeliveryStateDelivering;
  464. }
  465. else
  466. {
  467. return self.model.message.attachmentDownloadState != NIMMessageAttachmentDownloadStateDownloading;
  468. }
  469. }
  470. - (BOOL)unreadHidden {
  471. if (self.model.message.messageType == NIMMessageTypeAudio)
  472. { //音频
  473. BOOL disable = NO;
  474. if ([self.delegate respondsToSelector:@selector(disableAudioPlayedStatusIcon:)]) {
  475. disable = [self.delegate disableAudioPlayedStatusIcon:self.model.message];
  476. }
  477. BOOL hideIcon = self.model.message.attachmentDownloadState != NIMMessageAttachmentDownloadStateDownloaded || disable;
  478. return (hideIcon || self.model.message.isOutgoingMsg || [self.model.message isPlayed]);
  479. }
  480. return YES;
  481. }
  482. - (BOOL)readLabelHidden
  483. {
  484. if (self.model.shouldShowReadLabel &&
  485. [self activityIndicatorHidden] &&
  486. [self retryButtonHidden] &&
  487. [self unreadHidden])
  488. {
  489. return NO;
  490. }
  491. return YES;
  492. }
  493. - (BOOL)sendSuccessLabelHidden
  494. {
  495. if ([self readLabelHidden] &&
  496. [self activityIndicatorHidden] &&
  497. [self retryButtonHidden] &&
  498. self.model.message.deliveryState == NIMMessageDeliveryStateDeliveried &&
  499. !self.model.shouldShowLeft)
  500. {
  501. return NO;
  502. }
  503. return YES;
  504. }
  505. - (CGFloat)audioPlayedIconBubblePadding{
  506. return 10.0;
  507. }
  508. - (CGFloat)readButtonBubblePadding{
  509. return 2.0;
  510. }
  511. - (CGFloat)sendSuccessButtonBubblePadding{
  512. return 2.0;
  513. }
  514. - (CGPoint)cellPaddingToAvatar
  515. {
  516. return self.model.avatarMargin;
  517. }
  518. - (CGPoint)cellPaddingToNick
  519. {
  520. return self.model.nickNameMargin;
  521. }
  522. - (CGSize)avatarSize {
  523. return self.model.avatarSize;
  524. }
  525. - (void)onTapAvatar:(id)sender{
  526. if ([self.delegate respondsToSelector:@selector(onTapAvatar:)])
  527. {
  528. [self.delegate onTapAvatar:self.model.message];
  529. }
  530. }
  531. - (void)onLongPressAvatar:(UIGestureRecognizer *)gestureRecognizer
  532. {
  533. if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] &&
  534. gestureRecognizer.state == UIGestureRecognizerStateBegan)
  535. {
  536. if ([self.delegate respondsToSelector:@selector(onLongPressAvatar:)])
  537. {
  538. [self.delegate onLongPressAvatar:self.model.message];
  539. }
  540. }
  541. }
  542. - (void)onPressReadButton:(id)sender
  543. {
  544. if ([self.delegate respondsToSelector:@selector(onPressReadLabel:)])
  545. {
  546. [self.delegate onPressReadLabel:self.model.message];
  547. }
  548. }
  549. @end