2
0

WFCUConversationTableViewCell.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. //
  2. // ConversationTableViewCell.m
  3. // WFChat UIKit
  4. //
  5. // Created by WF Chat on 2017/8/29.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #import "WFCUConversationTableViewCell.h"
  9. #import "WFCUUtilities.h"
  10. #import <WFChatClient/WFCChatClient.h>
  11. #import <SDWebImage/SDWebImage.h>
  12. #import "WFCUConfigManager.h"
  13. #import "UIColor+YH.h"
  14. #import <UIFont+YH.h>
  15. #import "WFCUImage.h"
  16. @implementation WFCUConversationTableViewCell
  17. - (void)awakeFromNib {
  18. [super awakeFromNib];
  19. // Initialization code
  20. }
  21. - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
  22. [super setSelected:selected animated:animated];
  23. }
  24. - (void)layoutSubviews {
  25. [super layoutSubviews];
  26. if (!self.isBig) {
  27. _potraitView.frame = CGRectMake(16, 10, 40, 40);
  28. _targetView.frame = CGRectMake(16 + 40 + 20, 11, [UIScreen mainScreen].bounds.size.width - (16 + 40 + 20 + 100), 16);
  29. _targetView.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:15];
  30. _digestView.frame = CGRectMake(16 + 40 + 20, 11 + 16 + 8, [UIScreen mainScreen].bounds.size.width - (16 + 40 + 20 + 20), 19);
  31. }
  32. }
  33. - (void)updateUserInfo:(WFCCUserInfo *)userInfo {
  34. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUserInfoUpdated:) name:kUserInfoUpdated object:nil];
  35. [self.potraitView sd_setImageWithURL:[NSURL URLWithString:[userInfo.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage: [WFCUImage imageNamed:@"PersonalChat"]];
  36. if (userInfo.friendAlias.length) {
  37. self.targetView.text = userInfo.friendAlias;
  38. } else if(userInfo.displayName.length > 0) {
  39. self.targetView.text = userInfo.displayName;
  40. } else {
  41. self.targetView.text = [NSString stringWithFormat:@"user<%@>", self.info.conversation.target];
  42. }
  43. [self updateExternalDomainInfo];
  44. }
  45. - (void)updateChannelInfo:(WFCCChannelInfo *)channelInfo {
  46. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onChannelInfoUpdated:) name:kChannelInfoUpdated object:nil];
  47. [self.potraitView sd_setImageWithURL:[NSURL URLWithString:[channelInfo.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[WFCUImage imageNamed:@"channel_default_portrait"]];
  48. if(channelInfo.name.length > 0) {
  49. self.targetView.text = channelInfo.name;
  50. } else {
  51. self.targetView.text = WFCString(@"Channel");
  52. }
  53. [self updateExternalDomainInfo];
  54. }
  55. - (void)updateGroupInfo:(WFCCGroupInfo *)groupInfo {
  56. [[NSNotificationCenter defaultCenter] removeObserver:self name:@"GroupPortraitChanged" object:nil];
  57. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onGroupInfoUpdated:) name:kGroupInfoUpdated object:nil];
  58. if(groupInfo.type == GroupType_Organization) {
  59. if(groupInfo.portrait.length) {
  60. [self.potraitView sd_setImageWithURL:[NSURL URLWithString:[groupInfo.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[WFCUImage imageNamed:@"organization_icon"]];
  61. } else {
  62. self.potraitView.image = [WFCUImage imageNamed:@"organization_icon"];
  63. }
  64. } else {
  65. if (groupInfo.portrait.length) {
  66. [self.potraitView sd_setImageWithURL:[NSURL URLWithString:[groupInfo.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[WFCUImage imageNamed:@"group_default_portrait"]];
  67. } else {
  68. __weak typeof(self)ws = self;
  69. NSString *groupId = groupInfo.target;
  70. [[NSNotificationCenter defaultCenter] addObserverForName:@"GroupPortraitChanged" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
  71. NSString *path = [note.userInfo objectForKey:@"path"];
  72. if ([groupId isEqualToString:note.object] && (
  73. (ws.info.conversation.type == Group_Type && [ws.info.conversation.target isEqualToString:groupId]) ||
  74. (ws.searchInfo.conversation.type == Group_Type && [ws.searchInfo.conversation.target isEqualToString:groupId]))) {
  75. [ws.potraitView sd_setImageWithURL:[NSURL fileURLWithPath:path] placeholderImage:[WFCUImage imageNamed:@"group_default_portrait"]];
  76. }
  77. }];
  78. NSString *path = [WFCCUtilities getGroupGridPortrait:groupInfo.target width:80 generateIfNotExist:YES defaultUserPortrait:^UIImage *(NSString *userId) {
  79. return [WFCUImage imageNamed:@"PersonalChat"];
  80. }];
  81. if (path) {
  82. [self.potraitView sd_setImageWithURL:[NSURL fileURLWithPath:path] placeholderImage:[WFCUImage imageNamed:@"group_default_portrait"]];
  83. } else {
  84. [self.potraitView setImage:[WFCUImage imageNamed:@"group_default_portrait"]];
  85. }
  86. }
  87. }
  88. if(groupInfo.displayName.length > 0) {
  89. self.targetView.text = groupInfo.displayName;
  90. } else {
  91. self.targetView.text = WFCString(@"GroupChat");
  92. }
  93. [self updateExternalDomainInfo];
  94. }
  95. - (void)updateExternalDomainInfo {
  96. if([WFCCUtilities isExternalTarget:self.info.conversation.target]) {
  97. NSString *domainId = [WFCCUtilities getExternalDomain:self.info.conversation.target];
  98. self.targetView.attributedText = [WFCCUtilities getExternal:domainId withName:self.targetView.text withColor:[WFCUConfigManager globalManager].externalNameColor withSize:12];
  99. }
  100. }
  101. - (void)setSearchInfo:(WFCCConversationSearchInfo *)searchInfo {
  102. _searchInfo = searchInfo;
  103. self.bubbleView.hidden = YES;
  104. self.timeView.hidden = YES;
  105. [self update:searchInfo.conversation];
  106. if (searchInfo.marchedCount > 1) {
  107. self.digestView.text = [NSString stringWithFormat:WFCString(@"NumberOfRecords"), searchInfo.marchedCount];
  108. } else {
  109. NSString *strContent = searchInfo.marchedMessage.digest;
  110. NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:strContent];
  111. NSRange range = [strContent rangeOfString:searchInfo.keyword options:NSCaseInsensitiveSearch];
  112. [attrStr addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:range];
  113. self.digestView.attributedText = attrStr;
  114. }
  115. }
  116. - (void)setInfo:(WFCCConversationInfo *)info {
  117. _info = info;
  118. if (info.unreadCount.unread == 0) {
  119. self.bubbleView.hidden = YES;
  120. } else {
  121. self.bubbleView.hidden = NO;
  122. if (info.isSilent) {
  123. self.bubbleView.isShowNotificationNumber = NO;
  124. } else {
  125. self.bubbleView.isShowNotificationNumber = YES;
  126. }
  127. [self.bubbleView setBubbleTipNumber:info.unreadCount.unread];
  128. }
  129. if (info.isSilent) {
  130. self.silentView.hidden = NO;
  131. } else {
  132. _silentView.hidden = YES;
  133. }
  134. [self update:info.conversation];
  135. self.timeView.hidden = NO;
  136. self.timeView.text = [WFCUUtilities formatTimeLabel:info.timestamp];
  137. BOOL darkMode = NO;
  138. if (@available(iOS 13.0, *)) {
  139. if(UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
  140. darkMode = YES;
  141. }
  142. }
  143. if (darkMode) {
  144. if (info.isTop) {
  145. [self.contentView setBackgroundColor:[UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.f]];
  146. } else {
  147. self.contentView.backgroundColor = [WFCUConfigManager globalManager].backgroudColor;
  148. }
  149. } else {
  150. if (info.isTop) {
  151. [self.contentView setBackgroundColor:[UIColor colorWithHexString:@"0xf7f7f7"]];
  152. } else {
  153. self.contentView.backgroundColor = [UIColor whiteColor];
  154. }
  155. }
  156. if (info.lastMessage && info.lastMessage.direction == MessageDirection_Send) {
  157. if (info.lastMessage.status == Message_Status_Sending) {
  158. self.statusView.image = [WFCUImage imageNamed:@"conversation_message_sending"];
  159. self.statusView.hidden = NO;
  160. } else if(info.lastMessage.status == Message_Status_Send_Failure) {
  161. self.statusView.image = [WFCUImage imageNamed:@"MessageSendError"];
  162. self.statusView.hidden = NO;
  163. } else {
  164. self.statusView.hidden = YES;
  165. }
  166. } else {
  167. self.statusView.hidden = YES;
  168. }
  169. [self updateDigestFrame:!self.statusView.hidden];
  170. }
  171. - (void)updateDigestFrame:(BOOL)isSending {
  172. if (isSending) {
  173. _digestView.frame = CGRectMake(16 + 48 + 12 + 18, 40, [UIScreen mainScreen].bounds.size.width - 76 - 16 - 16 - 18, 19);
  174. } else {
  175. _digestView.frame = CGRectMake(16 + 48 + 12, 40, [UIScreen mainScreen].bounds.size.width - 76 - 16 - 16, 19);
  176. }
  177. }
  178. - (void)update:(WFCCConversation *)conversation {
  179. [[NSNotificationCenter defaultCenter] removeObserver:self];
  180. self.targetView.textColor = [WFCUConfigManager globalManager].textColor;
  181. WFCCGroupInfo *groupInfo;
  182. if(conversation.type == Single_Type) {
  183. WFCCUserInfo *userInfo = [[WFCCIMService sharedWFCIMService] getUserInfo:conversation.target refresh:NO];
  184. if(userInfo.userId.length == 0) {
  185. userInfo = [[WFCCUserInfo alloc] init];
  186. userInfo.userId = conversation.target;
  187. }
  188. [self updateUserInfo:userInfo];
  189. } else if (conversation.type == Group_Type) {
  190. groupInfo = [[WFCCIMService sharedWFCIMService] getGroupInfo:conversation.target refresh:NO];
  191. if(groupInfo.target.length == 0) {
  192. groupInfo = [[WFCCGroupInfo alloc] init];
  193. groupInfo.target = conversation.target;
  194. }
  195. [self updateGroupInfo:groupInfo];
  196. } else if(conversation.type == Channel_Type) {
  197. WFCCChannelInfo *channelInfo = [[WFCCIMService sharedWFCIMService] getChannelInfo:conversation.target refresh:NO];
  198. if (channelInfo.channelId.length == 0) {
  199. channelInfo = [[WFCCChannelInfo alloc] init];
  200. channelInfo.channelId = conversation.target;
  201. }
  202. [self updateChannelInfo:channelInfo];
  203. } else if(conversation.type == SecretChat_Type){
  204. WFCCSecretChatInfo *secretInfo = [[WFCCIMService sharedWFCIMService] getSecretChatInfo:conversation.target];
  205. NSString *userId = [[WFCCIMService sharedWFCIMService] getSecretChatInfo:conversation.target].userId;
  206. WFCCUserInfo *userInfo = [[WFCCIMService sharedWFCIMService] getUserInfo:userId refresh:NO];
  207. [self updateUserInfo:userInfo];
  208. } else {
  209. self.targetView.text = WFCString(@"Chatroom");
  210. [self updateExternalDomainInfo];
  211. }
  212. CGSize size = [WFCUUtilities getTextDrawingSize:self.targetView.text font:self.targetView.font constrainedSize:CGSizeMake([UIScreen mainScreen].bounds.size.width - 76 - 68 - 24, 8000)];
  213. if(conversation.type == SecretChat_Type) {
  214. self.secretChatView.hidden = NO;
  215. self.targetView.frame = CGRectMake(16 + 48 + 12 + 24, 16, size.width, 20);
  216. } else {
  217. self.secretChatView.hidden = YES;
  218. self.targetView.frame = CGRectMake(16 + 48 + 12, 16, size.width, 20);
  219. }
  220. if(conversation.type == Group_Type && groupInfo.type == GroupType_Organization) {
  221. CGRect frame = self.offcialView.frame;
  222. CGRect targetFrame = self.targetView.frame;
  223. frame.origin.x = targetFrame.origin.x + targetFrame.size.width + 4;
  224. frame.origin.y = targetFrame.origin.y;
  225. self.offcialView.frame = frame;
  226. self.offcialView.hidden = NO;
  227. } else {
  228. _offcialView.hidden = YES;
  229. }
  230. self.potraitView.layer.cornerRadius = 4.f;
  231. self.digestView.attributedText = nil;
  232. NSString *secretChatStateText = nil;
  233. if(conversation.type == SecretChat_Type) {
  234. WFCCSecretChatState secretChatState = [[WFCCIMService sharedWFCIMService] getSecretChatInfo:conversation.target].state;
  235. if (secretChatState == SecretChatState_Starting) {
  236. secretChatStateText = @"密聊会话建立中,正在等待对方响应。";
  237. } else if(secretChatState == SecretChatState_Canceled) {
  238. secretChatStateText = @"密聊会话已取消!";
  239. }
  240. }
  241. if(secretChatStateText) {
  242. self.digestView.text = secretChatStateText;
  243. } else if (_info.draft.length) {
  244. NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:WFCString(@"[Draft]") attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}];
  245. NSError *__error = nil;
  246. NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:[_info.draft dataUsingEncoding:NSUTF8StringEncoding]
  247. options:kNilOptions
  248. error:&__error];
  249. NSString *text = _info.draft;
  250. if (!__error) {
  251. //兼容android/web端
  252. if([dictionary[@"content"] isKindOfClass:[NSString class]]) {
  253. text = dictionary[@"content"];
  254. } else if([dictionary[@"text"] isKindOfClass:[NSString class]]) {
  255. text = dictionary[@"text"];
  256. }
  257. }
  258. [attString appendAttributedString:[[NSAttributedString alloc] initWithString:text]];
  259. if (_info.conversation.type == Group_Type && _info.unreadCount.unreadMentionAll + _info.unreadCount.unreadMention > 0) {
  260. NSMutableAttributedString *tmp = [[NSMutableAttributedString alloc] initWithString:WFCString(@"[MentionYou]") attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}];
  261. [tmp appendAttributedString:attString];
  262. attString = tmp;
  263. }
  264. self.digestView.attributedText = attString;
  265. } else if (_info.lastMessage.direction == MessageDirection_Receive && _info.conversation.type == Group_Type) {
  266. NSString *groupId = nil;
  267. if (_info.conversation.type == Group_Type) {
  268. groupId = _info.conversation.target;
  269. }
  270. WFCCUserInfo *sender = [[WFCCIMService sharedWFCIMService] getUserInfo:_info.lastMessage.fromUser inGroup:groupId refresh:NO];
  271. if (sender.friendAlias.length && ![_info.lastMessage.content isKindOfClass:[WFCCNotificationMessageContent class]]) {
  272. self.digestView.text = [NSString stringWithFormat:@"%@:%@", sender.friendAlias, _info.lastMessage.digest];
  273. } else if (sender.groupAlias.length && ![_info.lastMessage.content isKindOfClass:[WFCCNotificationMessageContent class]]) {
  274. self.digestView.text = [NSString stringWithFormat:@"%@:%@", sender.groupAlias, _info.lastMessage.digest];
  275. } else if (sender.displayName.length && ![_info.lastMessage.content isKindOfClass:[WFCCNotificationMessageContent class]]) {
  276. self.digestView.text = [NSString stringWithFormat:@"%@:%@", sender.displayName, _info.lastMessage.digest];
  277. } else {
  278. self.digestView.text = _info.lastMessage.digest;
  279. }
  280. if (_info.unreadCount.unreadMentionAll + _info.unreadCount.unreadMention > 0) {
  281. NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:WFCString(@"[MentionYou]") attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}];
  282. if (self.digestView.text.length) {
  283. [attString appendAttributedString:[[NSAttributedString alloc] initWithString:self.digestView.text]];
  284. }
  285. self.digestView.attributedText = attString;
  286. }
  287. } else {
  288. self.digestView.text = _info.lastMessage.digest;
  289. }
  290. }
  291. - (void)reloadCell {
  292. [self setInfo:self.info];
  293. }
  294. - (void)onUserInfoUpdated:(NSNotification *)notification {
  295. NSArray<WFCCUserInfo *> *userInfoList = notification.userInfo[@"userInfoList"];
  296. WFCCConversationInfo *conv = self.info;
  297. for (WFCCUserInfo *userInfo in userInfoList) {
  298. if (conv.conversation.type == Single_Type || conv.conversation.type == SecretChat_Type) {
  299. if([userInfo.userId isEqualToString:conv.conversation.target]) {
  300. [self reloadCell];
  301. break;
  302. }
  303. }
  304. if ([conv.lastMessage.fromUser isEqualToString:userInfo.userId]) {
  305. [self reloadCell];
  306. break;
  307. }
  308. }
  309. }
  310. - (void)onGroupInfoUpdated:(NSNotification *)notification {
  311. NSArray<WFCCGroupInfo *> *groupInfoList = notification.userInfo[@"groupInfoList"];
  312. WFCCConversationInfo *conv = self.info;
  313. if(conv.conversation.type == Group_Type) {
  314. for (WFCCGroupInfo *groupInfo in groupInfoList) {
  315. if ([conv.conversation.target isEqualToString:groupInfo.target]) {
  316. [self reloadCell];
  317. break;
  318. }
  319. }
  320. }
  321. }
  322. - (void)onChannelInfoUpdated:(NSNotification *)notification {
  323. NSArray<WFCCChannelInfo *> *channelInfoList = notification.userInfo[@"channelInfoList"];
  324. WFCCConversationInfo *conv = self.info;
  325. if(conv.conversation.type == Channel_Type) {
  326. for (WFCCChannelInfo *channelInfo in channelInfoList) {
  327. if ([conv.conversation.target isEqualToString:channelInfo.channelId]) {
  328. [self reloadCell];
  329. break;
  330. }
  331. }
  332. }
  333. }
  334. - (UIImageView *)potraitView {
  335. if (!_potraitView) {
  336. _potraitView = [[UIImageView alloc] initWithFrame:CGRectMake(16, 12, 48, 48)];
  337. _potraitView.clipsToBounds = YES;
  338. _potraitView.layer.cornerRadius = 4.f;
  339. [self.contentView addSubview:_potraitView];
  340. }
  341. return _potraitView;
  342. }
  343. - (UIImageView *)statusView {
  344. if (!_statusView) {
  345. _statusView = [[UIImageView alloc] initWithFrame:CGRectMake(16 + 48 + 12, 42, 16, 16)];
  346. _statusView.image = [WFCUImage imageNamed:@"conversation_message_sending"];
  347. [self.contentView addSubview:_statusView];
  348. }
  349. return _statusView;
  350. }
  351. - (UILabel *)targetView {
  352. if (!_targetView) {
  353. _targetView = [[UILabel alloc] initWithFrame:CGRectMake(16 + 48 + 12, 16, [UIScreen mainScreen].bounds.size.width - 76 - 68, 20)];
  354. _targetView.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:17];
  355. _targetView.textColor = [WFCUConfigManager globalManager].textColor;
  356. _targetView.lineBreakMode = NSLineBreakByTruncatingMiddle;
  357. [self.contentView addSubview:_targetView];
  358. }
  359. return _targetView;
  360. }
  361. - (UILabel *)offcialView {
  362. if(!_offcialView) {
  363. _offcialView = [[UILabel alloc] initWithFrame:CGRectZero];
  364. _offcialView.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:10];
  365. _offcialView.layer.cornerRadius = 3;
  366. _offcialView.layer.masksToBounds = YES;
  367. _offcialView.textColor = [UIColor whiteColor];
  368. _offcialView.backgroundColor = [UIColor blueColor];
  369. _offcialView.textAlignment = NSTextAlignmentCenter;
  370. _offcialView.text = @"官方";
  371. CGSize size = [WFCUUtilities getTextDrawingSize:_offcialView.text font:_offcialView.font constrainedSize:CGSizeMake(200, 200)];
  372. _offcialView.frame = CGRectMake(0, 0, size.width+4, size.height);
  373. [self.contentView addSubview:_offcialView];
  374. }
  375. return _offcialView;
  376. }
  377. - (UIImageView *)secretChatView {
  378. if(!_secretChatView) {
  379. _secretChatView = [[UIImageView alloc] initWithFrame:CGRectMake(16 + 48 + 12, 16, 20, 20)];
  380. _secretChatView.image = [WFCUImage imageNamed:@"secret_chat_icon"];
  381. [self.contentView addSubview:_secretChatView];
  382. }
  383. return _secretChatView;
  384. }
  385. - (UILabel *)digestView {
  386. if (!_digestView) {
  387. _digestView = [[UILabel alloc] initWithFrame:CGRectMake(16 + 48 + 12, 42, [UIScreen mainScreen].bounds.size.width - 76 - 16 - 16, 19)];
  388. _digestView.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:14];
  389. _digestView.lineBreakMode = NSLineBreakByTruncatingTail;
  390. _digestView.textColor = [UIColor colorWithHexString:@"b3b3b3"];
  391. [self.contentView addSubview:_digestView];
  392. }
  393. return _digestView;
  394. }
  395. - (UIImageView *)silentView {
  396. if (!_silentView) {
  397. _silentView = [[UIImageView alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - 12 - 20, 45, 12, 12)];
  398. _silentView.image = [WFCUImage imageNamed:@"conversation_mute"];
  399. [self.contentView addSubview:_silentView];
  400. }
  401. return _silentView;
  402. }
  403. - (UILabel *)timeView {
  404. if (!_timeView) {
  405. _timeView = [[UILabel alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - 52 - 16, 20, 52, 12)];
  406. _timeView.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:12];
  407. _timeView.textAlignment = NSTextAlignmentRight;
  408. _timeView.textColor = [UIColor colorWithHexString:@"b3b3b3"];
  409. [self.contentView addSubview:_timeView];
  410. }
  411. return _timeView;
  412. }
  413. - (BubbleTipView *)bubbleView {
  414. if (!_bubbleView) {
  415. if(self.potraitView) {
  416. _bubbleView = [[BubbleTipView alloc] initWithSuperView:self.contentView];
  417. _bubbleView.hidden = YES;
  418. }
  419. }
  420. return _bubbleView;
  421. }
  422. - (void)dealloc {
  423. [[NSNotificationCenter defaultCenter] removeObserver:self];
  424. }
  425. @end