2
0

WFCUMessageCell.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. //
  2. // MessageCell.m
  3. // WFChat UIKit
  4. //
  5. // Created by WF Chat on 2017/9/1.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #import "WFCUMessageCell.h"
  9. #import "WFCUUtilities.h"
  10. #import <WFChatClient/WFCChatClient.h>
  11. #import <SDWebImage/SDWebImage.h>
  12. #import "ZCCCircleProgressView.h"
  13. #define Portrait_Size 40
  14. #define SelectView_Size 20
  15. #define Name_Label_Height 14
  16. #define Name_Label_Padding 6
  17. #define Name_Client_Padding 2
  18. #define Portrait_Padding_Left 16
  19. #define Portrait_Padding_Right 16
  20. #define Portrait_Padding_Buttom 4
  21. #define Client_Arad_Buttom_Padding 8
  22. #define Client_Bubble_Top_Padding 6
  23. #define Client_Bubble_Bottom_Padding 4
  24. #define Bubble_Padding_Arraw 16
  25. #define Bubble_Padding_Another_Side 8
  26. #define MESSAGE_BASE_CELL_QUOTE_SIZE 14
  27. @interface WFCUMessageCell ()
  28. @property (nonatomic, strong)UIActivityIndicatorView *activityIndicatorView;
  29. @property (nonatomic, strong)UIImageView *failureView;
  30. @property (nonatomic, strong)UIImageView *maskView;
  31. @property (nonatomic, strong)ZCCCircleProgressView *receiptView;
  32. @property (nonatomic, strong)UIImageView *selectView;
  33. @end
  34. @implementation WFCUMessageCell
  35. + (CGFloat)clientAreaWidth {
  36. return [WFCUMessageCell bubbleWidth] - Bubble_Padding_Arraw - Bubble_Padding_Another_Side;
  37. }
  38. + (CGFloat)bubbleWidth {
  39. return ([UIScreen mainScreen].bounds.size.width - Portrait_Size - Portrait_Padding_Left - Portrait_Padding_Right) * 0.7;
  40. }
  41. + (CGSize)sizeForCell:(WFCUMessageModel *)msgModel withViewWidth:(CGFloat)width {
  42. CGFloat height = [super hightForHeaderArea:msgModel];
  43. CGFloat portraitSize = Portrait_Size;
  44. CGFloat nameLabelHeight = Name_Label_Height + Name_Client_Padding;
  45. CGFloat clientAreaWidth = [self clientAreaWidth];
  46. CGSize clientArea = [self sizeForClientArea:msgModel withViewWidth:clientAreaWidth];
  47. CGFloat nameAndClientHeight = clientArea.height;
  48. if (msgModel.showNameLabel) {
  49. nameAndClientHeight += nameLabelHeight;
  50. }
  51. nameAndClientHeight += Client_Bubble_Top_Padding;
  52. nameAndClientHeight += Client_Bubble_Bottom_Padding;
  53. if (portraitSize + Portrait_Padding_Buttom > nameAndClientHeight) {
  54. height += portraitSize + Portrait_Padding_Buttom;
  55. } else {
  56. height += nameAndClientHeight;
  57. }
  58. height += Client_Arad_Buttom_Padding; //buttom padding
  59. height += [self sizeForQuoteArea:msgModel withViewWidth:clientAreaWidth].height;
  60. return CGSizeMake(width, height);
  61. }
  62. + (CGSize)sizeForClientArea:(WFCUMessageModel *)msgModel withViewWidth:(CGFloat)width {
  63. return CGSizeZero;
  64. }
  65. + (CGSize)sizeForQuoteArea:(WFCUMessageModel *)msgModel withViewWidth:(CGFloat)width {
  66. if ([msgModel.message.content isKindOfClass:[WFCCTextMessageContent class]]) {
  67. WFCCTextMessageContent *txtContent = (WFCCTextMessageContent *)msgModel.message.content;
  68. if (txtContent.quoteInfo) {
  69. CGFloat quoteWidth = width - Portrait_Size - Portrait_Padding_Right - Portrait_Size - Portrait_Padding_Left;
  70. NSString *quoteTxt = [NSString stringWithFormat:@"%@:%@", txtContent.quoteInfo.userDisplayName, txtContent.quoteInfo.messageDigest];
  71. CGSize size = [WFCUUtilities getTextDrawingSize:quoteTxt font:[UIFont systemFontOfSize:MESSAGE_BASE_CELL_QUOTE_SIZE] constrainedSize:CGSizeMake(quoteWidth, 36)];
  72. size.height += 4;
  73. size.width = width;
  74. return size;
  75. }
  76. }
  77. return CGSizeZero;
  78. }
  79. - (void)updateStatus {
  80. if (self.model.message.direction == MessageDirection_Send) {
  81. if (self.model.message.status == Message_Status_Sending) {
  82. CGRect frame = self.bubbleView.frame;
  83. frame.origin.x -= 24;
  84. frame.origin.y = frame.origin.y + frame.size.height - 24;
  85. frame.size.width = 20;
  86. frame.size.height = 20;
  87. self.activityIndicatorView.hidden = NO;
  88. self.activityIndicatorView.frame = frame;
  89. [self.activityIndicatorView startAnimating];
  90. } else {
  91. [_activityIndicatorView stopAnimating];
  92. _activityIndicatorView.hidden = YES;
  93. }
  94. if (self.model.message.status == Message_Status_Send_Failure) {
  95. CGRect frame = self.bubbleView.frame;
  96. frame.origin.x -= 24;
  97. frame.origin.y = frame.origin.y + frame.size.height - 24;
  98. frame.size.width = 20;
  99. frame.size.height = 20;
  100. self.failureView.frame = frame;
  101. self.failureView.hidden = NO;
  102. } else {
  103. _failureView.hidden = YES;
  104. }
  105. } else {
  106. [_activityIndicatorView stopAnimating];
  107. _activityIndicatorView.hidden = YES;
  108. _failureView.hidden = YES;
  109. }
  110. }
  111. -(void)onStatusChanged:(NSNotification *)notification {
  112. WFCCMessageStatus newStatus = (WFCCMessageStatus)[[notification.userInfo objectForKey:@"status"] integerValue];
  113. self.model.message.status = newStatus;
  114. [self updateStatus];
  115. }
  116. - (void)onUserInfoUpdated:(NSNotification *)notification {
  117. WFCCUserInfo *userInfo = notification.userInfo[@"userInfo"];
  118. if([userInfo.userId isEqualToString:self.model.message.fromUser]) {
  119. if (self.model.message.conversation.type == Group_Type) {
  120. userInfo = [[WFCCIMService sharedWFCIMService] getUserInfo:userInfo.userId inGroup:self.model.message.conversation.target refresh:NO];
  121. }
  122. [self updateUserInfo:userInfo];
  123. }
  124. }
  125. - (void)updateUserInfo:(WFCCUserInfo *)userInfo {
  126. if([userInfo.userId isEqualToString:self.model.message.fromUser]) {
  127. [self.portraitView sd_setImageWithURL:[NSURL URLWithString:[userInfo.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[UIImage imageNamed:@"PersonalChat"]];
  128. if(self.model.showNameLabel) {
  129. NSString *nameStr = nil;
  130. if (userInfo.friendAlias.length) {
  131. nameStr = userInfo.friendAlias;
  132. } else if(userInfo.groupAlias.length) {
  133. if(userInfo.displayName.length > 0) {
  134. nameStr = [userInfo.groupAlias stringByAppendingFormat:@"(%@)", userInfo.displayName];
  135. } else {
  136. nameStr = userInfo.groupAlias;
  137. }
  138. } else if(userInfo.displayName.length > 0) {
  139. nameStr = userInfo.displayName;
  140. } else {
  141. nameStr = [NSString stringWithFormat:@"%@<%@>", WFCString(@"User"), self.model.message.fromUser];
  142. }
  143. self.nameLabel.text = nameStr;
  144. }
  145. }
  146. }
  147. - (void)setModel:(WFCUMessageModel *)model {
  148. [[NSNotificationCenter defaultCenter] removeObserver:self];
  149. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onStatusChanged:) name:kSendingMessageStatusUpdated object:
  150. @(model.message.messageId)];
  151. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUserInfoUpdated:) name:kUserInfoUpdated object:
  152. model.message.fromUser];
  153. [super setModel:model];
  154. CGFloat selectViewOffset = model.selecting ? SelectView_Size + Portrait_Padding_Right : 0;
  155. if (model.message.direction == MessageDirection_Send) {
  156. CGFloat top = [WFCUMessageCellBase hightForHeaderArea:model];
  157. CGRect frame = self.frame;
  158. self.portraitView.frame = CGRectMake(frame.size.width - Portrait_Size - Portrait_Padding_Right - selectViewOffset, top, Portrait_Size, Portrait_Size);
  159. if (model.showNameLabel) {
  160. self.nameLabel.frame = CGRectMake(frame.size.width - Portrait_Size - Portrait_Padding_Right - Name_Label_Padding - 200 - selectViewOffset, top, 200, Name_Label_Height);
  161. self.nameLabel.hidden = NO;
  162. self.nameLabel.textAlignment = NSTextAlignmentRight;
  163. } else {
  164. self.nameLabel.hidden = YES;
  165. }
  166. CGSize size = [self.class sizeForClientArea:model withViewWidth:[WFCUMessageCell clientAreaWidth]];
  167. self.bubbleView.image = [UIImage imageNamed:@"sent_msg_background"];
  168. self.bubbleView.frame = CGRectMake(frame.size.width - Portrait_Size - Portrait_Padding_Right - Name_Label_Padding - size.width - Bubble_Padding_Arraw - Bubble_Padding_Another_Side - selectViewOffset, top + Name_Client_Padding, size.width + Bubble_Padding_Arraw + Bubble_Padding_Another_Side, size.height + Client_Bubble_Top_Padding + Client_Bubble_Bottom_Padding);
  169. self.contentArea.frame = CGRectMake(Bubble_Padding_Another_Side, Client_Bubble_Top_Padding, size.width, size.height);
  170. UIImage *image = self.bubbleView.image;
  171. self.bubbleView.image = [self.bubbleView.image
  172. resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.95, image.size.width * 0.2,image.size.height * 0.1, image.size.width * 0.05)];
  173. if([model.message.content.class getContentFlags] == WFCCPersistFlag_PERSIST_AND_COUNT && (model.message.status == Message_Status_Sent || model.message.status == Message_Status_Readed) && [[WFCCIMService sharedWFCIMService] isReceiptEnabled] && [[WFCCIMService sharedWFCIMService] isUserEnableReceipt]) {
  174. if (model.message.conversation.type == Single_Type) {
  175. if (model.message.serverTime <= [[model.readDict objectForKey:model.message.conversation.target] longLongValue]) {
  176. [self.receiptView setProgress:1 subProgress:1];
  177. } else if (model.message.serverTime <= [[model.deliveryDict objectForKey:model.message.conversation.target] longLongValue]) {
  178. [self.receiptView setProgress:0 subProgress:1];
  179. } else {
  180. [self.receiptView setProgress:0 subProgress:0];
  181. }
  182. self.receiptView.hidden = NO;
  183. } else if(model.message.conversation.type == Group_Type) {
  184. long long messageTS = model.message.serverTime;
  185. WFCCGroupInfo *groupInfo = nil;
  186. if (model.deliveryRate == -1) {
  187. __block int delieveriedCount = 0;
  188. [model.deliveryDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
  189. if ([obj longLongValue] >= messageTS) {
  190. delieveriedCount++;
  191. }
  192. }];
  193. groupInfo = [[WFCCIMService sharedWFCIMService] getGroupInfo:model.message.conversation.target refresh:NO];
  194. model.deliveryRate = (float)delieveriedCount/(groupInfo.memberCount - 1);
  195. }
  196. if (model.readRate == -1) {
  197. __block int readedCount = 0;
  198. [model.readDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
  199. if ([obj longLongValue] >= messageTS) {
  200. readedCount++;
  201. }
  202. }];
  203. if (!groupInfo) {
  204. groupInfo = [[WFCCIMService sharedWFCIMService] getGroupInfo:model.message.conversation.target refresh:NO];
  205. }
  206. model.readRate = (float)readedCount/(groupInfo.memberCount - 1);
  207. }
  208. if (model.deliveryRate < model.readRate) {
  209. model.deliveryRate = model.readRate;
  210. }
  211. [self.receiptView setProgress:model.readRate subProgress:model.deliveryRate];
  212. self.receiptView.hidden = NO;
  213. } else {
  214. self.receiptView.hidden = YES;
  215. }
  216. } else {
  217. self.receiptView.hidden = YES;
  218. }
  219. if (self.receiptView.hidden == NO) {
  220. self.receiptView.frame = CGRectMake(self.bubbleView.frame.origin.x - 16, self.frame.size.height - 24 , 14, 14);
  221. }
  222. } else {
  223. CGFloat top = [WFCUMessageCellBase hightForHeaderArea:model];
  224. self.portraitView.frame = CGRectMake(Portrait_Padding_Left, top, Portrait_Size, Portrait_Size);
  225. if (model.showNameLabel) {
  226. self.nameLabel.frame = CGRectMake(Portrait_Padding_Left + Portrait_Size + Name_Label_Padding, top, 200, Name_Label_Height);
  227. self.nameLabel.hidden = NO;
  228. self.nameLabel.textAlignment = NSTextAlignmentLeft;
  229. top += Name_Label_Height + Name_Client_Padding;
  230. } else {
  231. self.nameLabel.hidden = YES;
  232. }
  233. NSString *bubbleImageName = @"received_msg_background";
  234. if (@available(iOS 13.0, *)) {
  235. if(UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
  236. bubbleImageName = @"chat_from_bg_normal_dark";
  237. }
  238. }
  239. CGSize size = [self.class sizeForClientArea:model withViewWidth:[WFCUMessageCell clientAreaWidth]];
  240. self.bubbleView.image = [UIImage imageNamed:bubbleImageName];
  241. self.bubbleView.frame = CGRectMake(Portrait_Padding_Left + Portrait_Size + Name_Label_Padding, top, size.width + Bubble_Padding_Arraw + Bubble_Padding_Another_Side, size.height + Client_Bubble_Top_Padding + Client_Bubble_Bottom_Padding);
  242. self.contentArea.frame = CGRectMake(Bubble_Padding_Arraw, Client_Bubble_Top_Padding, size.width, size.height);
  243. UIImage *image = self.bubbleView.image;
  244. CGFloat leftProtection = image.size.width * 0.8;
  245. CGFloat rightProtection = image.size.width * 0.2;
  246. if (self.bubbleView.frame.size.width < image.size.width) {
  247. leftProtection = 17;
  248. rightProtection = 12;
  249. }
  250. self.bubbleView.image = [self.bubbleView.image
  251. resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, leftProtection,
  252. image.size.height * 0.2, rightProtection)];
  253. self.receiptView.hidden = YES;
  254. }
  255. if (model.selecting) {
  256. self.selectView.hidden = NO;
  257. if (model.selected) {
  258. self.selectView.image = [UIImage imageNamed:@"multi_selected"];
  259. } else {
  260. self.selectView.image = [UIImage imageNamed:@"multi_unselected"];
  261. }
  262. CGFloat top = [WFCUMessageCellBase hightForHeaderArea:model];
  263. CGRect frame = self.selectView.frame;
  264. frame.origin.y = top;
  265. self.selectView.frame = frame;
  266. } else {
  267. self.selectView.hidden = YES;
  268. }
  269. NSString *groupId = nil;
  270. if (self.model.message.conversation.type == Group_Type) {
  271. groupId = self.model.message.conversation.target;
  272. }
  273. WFCCUserInfo *userInfo = [[WFCCIMService sharedWFCIMService] getUserInfo:model.message.fromUser inGroup:groupId refresh:NO];
  274. if(userInfo.userId.length == 0) {
  275. userInfo = [[WFCCUserInfo alloc] init];
  276. userInfo.userId = model.message.fromUser;
  277. }
  278. [self updateUserInfo:userInfo];
  279. [self setMaskImage:self.bubbleView.image];
  280. [self updateStatus];
  281. if (model.highlighted) {
  282. UIColor *bkColor = self.backgroundColor;
  283. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  284. self.backgroundColor = [UIColor grayColor];
  285. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  286. self.backgroundColor = bkColor;
  287. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  288. self.backgroundColor = [UIColor grayColor];
  289. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  290. self.backgroundColor = bkColor;
  291. });
  292. });
  293. });
  294. });
  295. model.highlighted = NO;
  296. }
  297. self.quoteLabel.hidden = YES;
  298. if ([model.message.content isKindOfClass:[WFCCTextMessageContent class]]) {
  299. WFCCTextMessageContent *txtContent = (WFCCTextMessageContent *)model.message.content;
  300. if (txtContent.quoteInfo) {
  301. if (!self.quoteLabel) {
  302. self.quoteLabel = [[UILabel alloc] initWithFrame:CGRectZero];
  303. self.quoteLabel.backgroundColor = [UIColor grayColor];
  304. self.quoteLabel.font = [UIFont systemFontOfSize:MESSAGE_BASE_CELL_QUOTE_SIZE];
  305. self.quoteLabel.numberOfLines = 0;
  306. self.quoteLabel.layer.cornerRadius = 3.f;
  307. self.quoteLabel.layer.masksToBounds = YES;
  308. self.quoteLabel.userInteractionEnabled = YES;
  309. [self.quoteLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onQuoteLabelTaped:)]];
  310. [self.contentView addSubview:self.quoteLabel];
  311. }
  312. CGSize size = [self.class sizeForQuoteArea:model withViewWidth:[WFCUMessageCell clientAreaWidth]];
  313. if (model.message.direction == MessageDirection_Send) {
  314. self.quoteLabel.frame = CGRectMake(self.frame.size.width - Portrait_Size - Portrait_Padding_Right - Name_Label_Padding - size.width - Bubble_Padding_Another_Side - selectViewOffset, self.bubbleView.frame.origin.y + self.bubbleView.frame.size.height + 4, size.width, size.height-4);
  315. } else {
  316. self.quoteLabel.frame = CGRectMake(Portrait_Padding_Left + Portrait_Size + Name_Label_Padding + Bubble_Padding_Arraw, self.bubbleView.frame.origin.y + self.bubbleView.frame.size.height + 4, size.width, size.height-4);
  317. }
  318. self.quoteLabel.hidden = NO;
  319. self.quoteLabel.text = [NSString stringWithFormat:@"%@:%@", txtContent.quoteInfo.userDisplayName, txtContent.quoteInfo.messageDigest];
  320. }
  321. }
  322. }
  323. - (void)onQuoteLabelTaped:(id)sender {
  324. if ([self.delegate respondsToSelector:@selector(didTapQuoteLabel:withModel:)]) {
  325. [self.delegate didTapQuoteLabel:self withModel:self.model];
  326. }
  327. }
  328. - (void)onTapReceiptView:(id)sender {
  329. if ([self.delegate respondsToSelector:@selector(didTapReceiptView:withModel:)] && self.model.message.conversation.type == Group_Type) {
  330. [self.delegate didTapReceiptView:self withModel:self.model];
  331. }
  332. }
  333. - (void)setMaskImage:(UIImage *)maskImage{
  334. if (_maskView == nil) {
  335. _maskView = [[UIImageView alloc] initWithImage:maskImage];
  336. _maskView.frame = self.bubbleView.bounds;
  337. self.bubbleView.layer.mask = _maskView.layer;
  338. self.bubbleView.layer.masksToBounds = YES;
  339. } else {
  340. _maskView.image = maskImage;
  341. _maskView.frame = self.bubbleView.bounds;
  342. }
  343. }
  344. - (ZCCCircleProgressView *)receiptView {
  345. if (!_receiptView) {
  346. _receiptView = [[ZCCCircleProgressView alloc] initWithFrame:CGRectMake(0, 0, 14, 14)];
  347. _receiptView.hidden = YES;
  348. _receiptView.userInteractionEnabled = YES;
  349. [_receiptView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapReceiptView:)]];
  350. [self.contentView addSubview:_receiptView];
  351. }
  352. return _receiptView;
  353. }
  354. - (UIImageView *)portraitView {
  355. if (!_portraitView) {
  356. _portraitView = [[UIImageView alloc] init];
  357. _portraitView.clipsToBounds = YES;
  358. _portraitView.layer.cornerRadius = 3.f;
  359. [_portraitView setImage:[UIImage imageNamed:@"PersonalChat"]];
  360. [_portraitView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapPortrait:)]];
  361. [_portraitView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongPressPortrait:)]];
  362. _portraitView.userInteractionEnabled=YES;
  363. [self.contentView addSubview:_portraitView];
  364. }
  365. return _portraitView;
  366. }
  367. - (void)didTapPortrait:(id)sender {
  368. [self.delegate didTapMessagePortrait:self withModel:self.model];
  369. }
  370. - (void)didLongPressPortrait:(UILongPressGestureRecognizer *)recognizer {
  371. if (recognizer.state == UIGestureRecognizerStateBegan) {
  372. [self.delegate didLongPressMessagePortrait:self withModel:self.model];
  373. }
  374. }
  375. - (UILabel *)nameLabel {
  376. if (!_nameLabel) {
  377. _nameLabel = [[UILabel alloc] init];
  378. _nameLabel.font = [UIFont systemFontOfSize:Name_Label_Height-2];
  379. _nameLabel.textColor = [UIColor grayColor];
  380. [self.contentView addSubview:_nameLabel];
  381. }
  382. return _nameLabel;
  383. }
  384. - (UIView *)contentArea {
  385. if (!_contentArea) {
  386. _contentArea = [[UIView alloc] init];
  387. [self.bubbleView addSubview:_contentArea];
  388. }
  389. return _contentArea;
  390. }
  391. - (UIImageView *)bubbleView {
  392. if (!_bubbleView) {
  393. _bubbleView = [[UIImageView alloc] init];
  394. [self.contentView addSubview:_bubbleView];
  395. [_bubbleView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressed:)]];
  396. UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onDoubleTaped:)];
  397. doubleTapGesture.numberOfTapsRequired = 2;
  398. doubleTapGesture.numberOfTouchesRequired = 1;
  399. [_bubbleView addGestureRecognizer:doubleTapGesture];
  400. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTaped:)];
  401. [_bubbleView addGestureRecognizer:tap];
  402. [tap requireGestureRecognizerToFail:doubleTapGesture];
  403. tap.cancelsTouchesInView = NO;
  404. [_bubbleView setUserInteractionEnabled:YES];
  405. }
  406. return _bubbleView;
  407. }
  408. - (UIActivityIndicatorView *)activityIndicatorView {
  409. if (!_activityIndicatorView) {
  410. _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  411. [self.contentView addSubview:_activityIndicatorView];
  412. }
  413. return _activityIndicatorView;
  414. }
  415. - (UIImageView *)failureView {
  416. if (!_failureView) {
  417. _failureView = [[UIImageView alloc] init];
  418. _failureView.image = [UIImage imageNamed:@"failure"];
  419. [_failureView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResend:)]];
  420. [_failureView setUserInteractionEnabled:YES];
  421. [self.contentView addSubview:_failureView];
  422. }
  423. return _failureView;
  424. }
  425. - (UIImageView *)selectView {
  426. if(!_selectView) {
  427. CGFloat top = [WFCUMessageCellBase hightForHeaderArea:self.model];
  428. CGRect frame = self.frame;
  429. frame = CGRectMake(frame.size.width - SelectView_Size - Portrait_Padding_Right, top, SelectView_Size, SelectView_Size);
  430. _selectView = [[UIImageView alloc] initWithFrame:frame];
  431. _selectView.image = [UIImage imageNamed:@"multi_unselected"];
  432. UIGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSelect:)];
  433. [_selectView addGestureRecognizer:tap];
  434. _selectView.userInteractionEnabled = YES;
  435. [self.contentView addSubview:_selectView];
  436. }
  437. return _selectView;
  438. }
  439. - (void)onSelect:(id)sender {
  440. self.model.selected = !self.model.selected;
  441. if (self.model.selected) {
  442. self.selectView.image = [UIImage imageNamed:@"multi_selected"];
  443. } else {
  444. self.selectView.image = [UIImage imageNamed:@"multi_unselected"];
  445. }
  446. }
  447. - (void)onResend:(id)sender {
  448. [self.delegate didTapResendBtn:self.model];
  449. }
  450. - (void)dealloc {
  451. [[NSNotificationCenter defaultCenter] removeObserver:self];
  452. }
  453. @end