WFCUMessageCell.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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.h"
  12. #define Portrait_Size 40
  13. #define Name_Label_Height 14
  14. #define Name_Label_Padding 6
  15. #define Name_Client_Padding 2
  16. #define Portrait_Padding_Left 4
  17. #define Portrait_Padding_Right 4
  18. #define Portrait_Padding_Buttom 4
  19. #define Client_Arad_Buttom_Padding 8
  20. #define Client_Bubble_Top_Padding 6
  21. #define Client_Bubble_Bottom_Padding 4
  22. #define Bubble_Padding_Arraw 16
  23. #define Bubble_Padding_Another_Side 8
  24. @interface WFCUMessageCell ()
  25. @property (nonatomic, strong)UIActivityIndicatorView *activityIndicatorView;
  26. @property (nonatomic, strong)UIImageView *failureView;
  27. @property (nonatomic, strong)UIImageView *maskView;
  28. @end
  29. @implementation WFCUMessageCell
  30. + (CGFloat)clientAreaWidth {
  31. return [WFCUMessageCell bubbleWidth] - Bubble_Padding_Arraw - Bubble_Padding_Another_Side;
  32. }
  33. + (CGFloat)bubbleWidth {
  34. return ([UIScreen mainScreen].bounds.size.width - Portrait_Size - Portrait_Padding_Left - Portrait_Padding_Right) * 0.7;
  35. }
  36. + (CGSize)sizeForCell:(WFCUMessageModel *)msgModel withViewWidth:(CGFloat)width {
  37. CGFloat height = [super hightForTimeLabel:msgModel];
  38. CGFloat portraitSize = Portrait_Size;
  39. CGFloat nameLabelHeight = Name_Label_Height + Name_Client_Padding;
  40. CGFloat clientAreaWidth = [self clientAreaWidth];
  41. CGSize clientArea = [self sizeForClientArea:msgModel withViewWidth:clientAreaWidth];
  42. CGFloat nameAndClientHeight = clientArea.height;
  43. if (msgModel.showNameLabel) {
  44. nameAndClientHeight += nameLabelHeight;
  45. }
  46. nameAndClientHeight += Client_Bubble_Top_Padding;
  47. nameAndClientHeight += Client_Bubble_Bottom_Padding;
  48. if (portraitSize + Portrait_Padding_Buttom > nameAndClientHeight) {
  49. height += portraitSize + Portrait_Padding_Buttom;
  50. } else {
  51. height += nameAndClientHeight;
  52. }
  53. height += Client_Arad_Buttom_Padding; //buttom padding
  54. return CGSizeMake(width, height);
  55. }
  56. + (CGSize)sizeForClientArea:(WFCUMessageModel *)msgModel withViewWidth:(CGFloat)width {
  57. return CGSizeZero;
  58. }
  59. - (void)updateStatus {
  60. if (self.model.message.direction == MessageDirection_Send) {
  61. if (self.model.message.status == Message_Status_Sending) {
  62. CGRect frame = self.bubbleView.frame;
  63. frame.origin.x -= 24;
  64. frame.origin.y = frame.origin.y + frame.size.height - 24;
  65. frame.size.width = 20;
  66. frame.size.height = 20;
  67. self.activityIndicatorView.hidden = NO;
  68. self.activityIndicatorView.frame = frame;
  69. [self.activityIndicatorView startAnimating];
  70. } else {
  71. [_activityIndicatorView stopAnimating];
  72. _activityIndicatorView.hidden = YES;
  73. }
  74. if (self.model.message.status == Message_Status_Send_Failure) {
  75. CGRect frame = self.bubbleView.frame;
  76. frame.origin.x -= 24;
  77. frame.origin.y = frame.origin.y + frame.size.height - 24;
  78. frame.size.width = 20;
  79. frame.size.height = 20;
  80. self.failureView.frame = frame;
  81. self.failureView.hidden = NO;
  82. } else {
  83. _failureView.hidden = YES;
  84. }
  85. } else {
  86. [_activityIndicatorView stopAnimating];
  87. _activityIndicatorView.hidden = YES;
  88. _failureView.hidden = YES;
  89. }
  90. }
  91. -(void)onStatusChanged:(NSNotification *)notification {
  92. WFCCMessageStatus newStatus = (WFCCMessageStatus)[[notification.userInfo objectForKey:@"status"] integerValue];
  93. self.model.message.status = newStatus;
  94. [self updateStatus];
  95. }
  96. - (void)onUserInfoUpdated:(NSNotification *)notification {
  97. WFCCUserInfo *userInfo = notification.userInfo[@"userInfo"];
  98. if([userInfo.userId isEqualToString:self.model.message.fromUser]) {
  99. [self updateUserInfo:userInfo];
  100. }
  101. }
  102. - (void)updateUserInfo:(WFCCUserInfo *)userInfo {
  103. if([userInfo.userId isEqualToString:self.model.message.fromUser]) {
  104. [self.portraitView sd_setImageWithURL:[NSURL URLWithString:userInfo.portrait] placeholderImage:[UIImage imageNamed:@"PersonalChat"]];
  105. if(self.model.showNameLabel) {
  106. if(self.model.message.conversation.type == Group_Type) {
  107. WFCCGroupMember *groupMember = [[WFCCIMService sharedWFCIMService] getGroupMember:self.model.message.conversation.target memberId:self.model.message.fromUser];
  108. if (groupMember != nil && groupMember.alias.length != 0) {
  109. if(userInfo.displayName.length > 0) {
  110. self.nameLabel.text = [groupMember.alias stringByAppendingFormat:@"(%@)", userInfo.displayName];
  111. } else {
  112. self.nameLabel.text = groupMember.alias;
  113. }
  114. return;
  115. }
  116. }
  117. if(userInfo.displayName.length > 0) {
  118. self.nameLabel.text = userInfo.displayName;
  119. } else {
  120. self.nameLabel.text = [NSString stringWithFormat:@"User<%@>", self.model.message.fromUser];
  121. }
  122. }
  123. }
  124. }
  125. - (void)setModel:(WFCUMessageModel *)model {
  126. [[NSNotificationCenter defaultCenter] removeObserver:self];
  127. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onStatusChanged:) name:kSendingMessageStatusUpdated object:
  128. @(model.message.messageId)];
  129. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUserInfoUpdated:) name:kUserInfoUpdated object:
  130. model.message.fromUser];
  131. [super setModel:model];
  132. if (model.message.direction == MessageDirection_Send) {
  133. CGFloat top = [WFCUMessageCellBase hightForTimeLabel:model];
  134. CGRect frame = self.frame;
  135. self.portraitView.frame = CGRectMake(frame.size.width - Portrait_Size - Portrait_Padding_Right, top, Portrait_Size, Portrait_Size);
  136. if (model.showNameLabel) {
  137. self.nameLabel.frame = CGRectMake(frame.size.width - Portrait_Size - Portrait_Padding_Right -Portrait_Padding_Left - Name_Label_Padding - 200, top, 200, Name_Label_Height);
  138. self.nameLabel.hidden = NO;
  139. self.nameLabel.textAlignment = NSTextAlignmentRight;
  140. } else {
  141. self.nameLabel.hidden = YES;
  142. }
  143. CGSize size = [self.class sizeForClientArea:model withViewWidth:[WFCUMessageCell clientAreaWidth]];
  144. self.bubbleView.image = [UIImage imageNamed:@"sent_msg_background"];
  145. self.bubbleView.frame = CGRectMake(frame.size.width - Portrait_Size - Portrait_Padding_Right -Portrait_Padding_Left - size.width - Bubble_Padding_Arraw - Bubble_Padding_Another_Side, top + Name_Client_Padding, size.width + Bubble_Padding_Arraw + Bubble_Padding_Another_Side, size.height + Client_Bubble_Top_Padding + Client_Bubble_Bottom_Padding);
  146. self.contentArea.frame = CGRectMake(Bubble_Padding_Another_Side, Client_Bubble_Top_Padding, size.width, size.height);
  147. UIImage *image = self.bubbleView.image;
  148. self.bubbleView.image = [self.bubbleView.image
  149. resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, image.size.width * 0.2,image.size.height * 0.2, image.size.width * 0.8)];
  150. } else {
  151. CGFloat top = [WFCUMessageCellBase hightForTimeLabel:model];
  152. self.portraitView.frame = CGRectMake(Portrait_Padding_Left, top, Portrait_Size, Portrait_Size);
  153. if (model.showNameLabel) {
  154. self.nameLabel.frame = CGRectMake(Portrait_Padding_Left + Portrait_Size + Portrait_Padding_Right + Name_Label_Padding, top, 200, Name_Label_Height);
  155. self.nameLabel.hidden = NO;
  156. self.nameLabel.textAlignment = NSTextAlignmentLeft;
  157. top += Name_Label_Height + Name_Client_Padding;
  158. } else {
  159. self.nameLabel.hidden = YES;
  160. }
  161. CGSize size = [self.class sizeForClientArea:model withViewWidth:[WFCUMessageCell clientAreaWidth]];
  162. self.bubbleView.image = [UIImage imageNamed:@"received_msg_background"];
  163. self.bubbleView.frame = CGRectMake(Portrait_Padding_Left + Portrait_Size + Portrait_Padding_Right, top, size.width + Bubble_Padding_Arraw + Bubble_Padding_Another_Side, size.height + Client_Bubble_Top_Padding + Client_Bubble_Bottom_Padding);
  164. self.contentArea.frame = CGRectMake(Bubble_Padding_Arraw, Client_Bubble_Top_Padding, size.width, size.height);
  165. UIImage *image = self.bubbleView.image;
  166. self.bubbleView.image = [self.bubbleView.image
  167. resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, image.size.width * 0.8,
  168. image.size.height * 0.2, image.size.width * 0.2)];
  169. }
  170. WFCCUserInfo *userInfo = [[WFCCIMService sharedWFCIMService] getUserInfo:model.message.fromUser refresh:NO];
  171. if(userInfo.userId.length == 0) {
  172. userInfo = [[WFCCUserInfo alloc] init];
  173. userInfo.userId = model.message.fromUser;
  174. }
  175. [self updateUserInfo:userInfo];
  176. [self setMaskImage:self.bubbleView.image];
  177. [self updateStatus];
  178. if (model.highlighted) {
  179. UIColor *bkColor = self.backgroundColor;
  180. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  181. self.backgroundColor = [UIColor grayColor];
  182. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  183. self.backgroundColor = bkColor;
  184. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  185. self.backgroundColor = [UIColor grayColor];
  186. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  187. self.backgroundColor = bkColor;
  188. });
  189. });
  190. });
  191. });
  192. model.highlighted = NO;
  193. }
  194. }
  195. - (void)setMaskImage:(UIImage *)maskImage{
  196. if (_maskView == nil) {
  197. _maskView = [[UIImageView alloc] initWithImage:maskImage];
  198. _maskView.frame = self.bubbleView.bounds;
  199. self.bubbleView.layer.mask = _maskView.layer;
  200. self.bubbleView.layer.masksToBounds = YES;
  201. } else {
  202. _maskView.image = maskImage;
  203. _maskView.frame = self.bubbleView.bounds;
  204. }
  205. }
  206. - (UIImageView *)portraitView {
  207. if (!_portraitView) {
  208. _portraitView = [[UIImageView alloc] init];
  209. _portraitView.clipsToBounds = YES;
  210. _portraitView.layer.cornerRadius = 3.f;
  211. [_portraitView setImage:[UIImage imageNamed:@"PersonalChat"]];
  212. [_portraitView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapPortrait:)]];
  213. [_portraitView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongPressPortrait:)]];
  214. _portraitView.userInteractionEnabled=YES;
  215. [self.contentView addSubview:_portraitView];
  216. }
  217. return _portraitView;
  218. }
  219. - (void)didTapPortrait:(id)sender {
  220. [self.delegate didTapMessagePortrait:self withModel:self.model];
  221. }
  222. - (void)didLongPressPortrait:(UILongPressGestureRecognizer *)recognizer {
  223. if (recognizer.state == UIGestureRecognizerStateBegan) {
  224. [self.delegate didLongPressMessagePortrait:self withModel:self.model];
  225. }
  226. }
  227. - (UILabel *)nameLabel {
  228. if (!_nameLabel) {
  229. _nameLabel = [[UILabel alloc] init];
  230. _nameLabel.font = [UIFont systemFontOfSize:Name_Label_Height-2];
  231. _nameLabel.textColor = [UIColor grayColor];
  232. [self.contentView addSubview:_nameLabel];
  233. }
  234. return _nameLabel;
  235. }
  236. - (UIView *)contentArea {
  237. if (!_contentArea) {
  238. _contentArea = [[UIView alloc] init];
  239. [self.bubbleView addSubview:_contentArea];
  240. }
  241. return _contentArea;
  242. }
  243. - (UIImageView *)bubbleView {
  244. if (!_bubbleView) {
  245. _bubbleView = [[UIImageView alloc] init];
  246. [self.contentView addSubview:_bubbleView];
  247. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTaped:)];
  248. [_bubbleView addGestureRecognizer:tap];
  249. [_bubbleView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressed:)]];
  250. tap.cancelsTouchesInView = NO;
  251. [_bubbleView setUserInteractionEnabled:YES];
  252. }
  253. return _bubbleView;
  254. }
  255. - (UIActivityIndicatorView *)activityIndicatorView {
  256. if (!_activityIndicatorView) {
  257. _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  258. [self.contentView addSubview:_activityIndicatorView];
  259. }
  260. return _activityIndicatorView;
  261. }
  262. - (UIImageView *)failureView {
  263. if (!_failureView) {
  264. _failureView = [[UIImageView alloc] init];
  265. _failureView.image = [UIImage imageNamed:@"failure"];
  266. [_failureView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResend:)]];
  267. [_failureView setUserInteractionEnabled:YES];
  268. [self.contentView addSubview:_failureView];
  269. }
  270. return _failureView;
  271. }
  272. - (void)onResend:(id)sender {
  273. [self.delegate didTapResendBtn:self.model];
  274. }
  275. - (void)dealloc {
  276. [[NSNotificationCenter defaultCenter] removeObserver:self];
  277. }
  278. @end