TUIBubbleMessageCell_Minimalist.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. //
  2. // TUIBubbleMessageCell_Minimalist.m
  3. // TXIMSDK_TUIKit_iOS
  4. //
  5. // Created by annidyfeng on 2019/5/22.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIBubbleMessageCell_Minimalist.h"
  9. #import <TIMCommon/TIMCommonModel.h>
  10. #import <TIMCommon/TIMDefine.h>
  11. @implementation TUIBubbleMessageCell_Minimalist
  12. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
  13. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  14. if (self) {
  15. _bubbleView = [[UIImageView alloc] initWithFrame:self.container.bounds];
  16. _bubbleView.userInteractionEnabled = YES;
  17. [self.container addSubview:_bubbleView];
  18. _bubbleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  19. }
  20. return self;
  21. }
  22. - (void)fillWithData:(TUIBubbleMessageCellData *)data {
  23. [super fillWithData:data];
  24. _bubbleData = data;
  25. if (self.bubbleData.sameToNextMsgSender) {
  26. self.bubbleView.image = self.getSameMessageBubble;
  27. self.bubbleView.highlightedImage = self.getHighlightSameMessageBubble;
  28. } else {
  29. self.bubbleView.image = self.getBubble;
  30. self.bubbleView.highlightedImage = self.getHighlightBubble;
  31. }
  32. // tell constraints they need updating
  33. [self setNeedsUpdateConstraints];
  34. // update constraints now so we can animate the change
  35. [self updateConstraintsIfNeeded];
  36. [self layoutIfNeeded];
  37. }
  38. + (BOOL)requiresConstraintBasedLayout {
  39. return YES;
  40. }
  41. // this is Apple's recommended place for adding/updating constraints
  42. - (void)updateConstraints {
  43. [super updateConstraints];
  44. [self.bubbleView mas_remakeConstraints:^(MASConstraintMaker *make) {
  45. make.leading.mas_equalTo(0);
  46. make.size.mas_equalTo(self.container);
  47. make.top.mas_equalTo(self.container);
  48. }];
  49. CGPoint center = self.retryView.center;
  50. center.y = self.bubbleView.center.y;
  51. self.retryView.center = center;
  52. }
  53. - (void)layoutSubviews {
  54. [super layoutSubviews];
  55. }
  56. - (void)highlightWhenMatchKeyword:(NSString *)keyword {
  57. /**
  58. * The parent class implements the default highlighting effect - flickering
  59. */
  60. if (keyword) {
  61. if (self.highlightAnimating) {
  62. return;
  63. }
  64. [self animate:3];
  65. }
  66. }
  67. - (void)animate:(int)times {
  68. times--;
  69. if (times < 0) {
  70. if (self.bubbleData.sameToNextMsgSender) {
  71. self.bubbleView.image = self.getSameMessageBubble;
  72. } else {
  73. self.bubbleView.image = self.getBubble;
  74. }
  75. self.bubbleView.layer.cornerRadius = 0;
  76. self.bubbleView.layer.masksToBounds = YES;
  77. self.highlightAnimating = NO;
  78. return;
  79. }
  80. self.bubbleView.image = self.getAnimateHighlightBubble_alpha50;
  81. self.bubbleView.layer.cornerRadius = 12;
  82. self.bubbleView.layer.masksToBounds = YES;
  83. self.highlightAnimating = YES;
  84. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  85. self.bubbleView.image = self.getAnimateHighlightBubble_alpha20;
  86. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  87. if (!self.bubbleData.highlightKeyword) {
  88. [self animate:0];
  89. return;
  90. }
  91. [self animate:times];
  92. });
  93. });
  94. }
  95. - (CGFloat)getBubbleTop {
  96. return [self.class getBubbleTop:self.bubbleData];
  97. }
  98. - (UIImage *)getBubble {
  99. if (!TIMConfig.defaultConfig.enableMessageBubble) {
  100. return nil;
  101. }
  102. if (self.bubbleData.direction == MsgDirectionIncoming) {
  103. return self.class.incommingBubble;
  104. } else {
  105. return self.class.outgoingBubble;
  106. }
  107. }
  108. - (UIImage *)getHighlightBubble {
  109. if (!TIMConfig.defaultConfig.enableMessageBubble) {
  110. return nil;
  111. }
  112. if (self.bubbleData.direction == MsgDirectionIncoming) {
  113. return self.class.incommingHighlightedBubble;
  114. } else {
  115. return self.class.outgoingHighlightedBubble;
  116. }
  117. }
  118. - (UIImage *)getAnimateHighlightBubble_alpha50 {
  119. if (!TIMConfig.defaultConfig.enableMessageBubble) {
  120. return nil;
  121. }
  122. if (self.bubbleData.direction == MsgDirectionIncoming) {
  123. return self.class.incommingAnimatedHighlightedAlpha50;
  124. } else {
  125. return self.class.outgoingAnimatedHighlightedAlpha50;
  126. }
  127. }
  128. - (UIImage *)getAnimateHighlightBubble_alpha20 {
  129. if (!TIMConfig.defaultConfig.enableMessageBubble) {
  130. return nil;
  131. }
  132. if (self.bubbleData.direction == MsgDirectionIncoming) {
  133. return self.class.incommingAnimatedHighlightedAlpha20;
  134. } else {
  135. return self.class.outgoingAnimatedHighlightedAlpha20;
  136. }
  137. }
  138. - (UIImage *)getSameMessageBubble {
  139. if (!TIMConfig.defaultConfig.enableMessageBubble) {
  140. return nil;
  141. }
  142. return self.bubbleData.direction == MsgDirectionIncoming ? self.class.incommingSameBubble : self.class.outgoingSameBubble;
  143. }
  144. - (UIImage *)getHighlightSameMessageBubble {
  145. if (!TIMConfig.defaultConfig.enableMessageBubble) {
  146. return nil;
  147. }
  148. return self.getSameMessageBubble;
  149. }
  150. + (CGFloat)getBubbleTop:(TUIBubbleMessageCellData *)data {
  151. if (data.direction == MsgDirectionIncoming) {
  152. return self.class.incommingBubbleTop;
  153. } else {
  154. return self.class.outgoingBubbleTop;
  155. }
  156. }
  157. @end
  158. @implementation TUIBubbleMessageCell_Minimalist (TUILayoutConfiguration)
  159. + (void)initialize {
  160. [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(onThemeChanged:) name:TUIDidApplyingThemeChangedNotfication object:nil];
  161. }
  162. #pragma mark - gOutgoingBubble
  163. static UIImage *gOutgoingBubble;
  164. + (UIImage *)outgoingBubble {
  165. if (!gOutgoingBubble) {
  166. UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"SenderTextNodeBkg")];
  167. [self setOutgoingBubble:defaultImage];
  168. }
  169. return gOutgoingBubble;
  170. }
  171. + (void)setOutgoingBubble:(UIImage *)outgoingBubble {
  172. gOutgoingBubble = [self stretchImage:outgoingBubble];
  173. }
  174. #pragma mark - gOutgoingSameBubble
  175. static UIImage *gOutgoingSameBubble;
  176. + (UIImage *)outgoingSameBubble {
  177. if (!gOutgoingSameBubble) {
  178. UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"SenderTextNodeBkg_Same")];
  179. [self setOutgoingSameBubble:defaultImage];
  180. }
  181. return gOutgoingSameBubble;
  182. }
  183. + (void)setOutgoingSameBubble:(UIImage *)outgoingSameBubble {
  184. gOutgoingSameBubble = [self stretchImage:outgoingSameBubble];
  185. }
  186. #pragma mark - gOutgoingHighlightedBubble
  187. static UIImage *gOutgoingHighlightedBubble;
  188. + (UIImage *)outgoingHighlightedBubble {
  189. if (!gOutgoingHighlightedBubble) {
  190. UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"SenderTextNodeBkg")];
  191. [self setOutgoingHighlightedBubble:defaultImage];
  192. }
  193. return gOutgoingHighlightedBubble;
  194. }
  195. + (void)setOutgoingHighlightedBubble:(UIImage *)outgoingHighlightedBubble {
  196. gOutgoingHighlightedBubble = [self stretchImage:outgoingHighlightedBubble];
  197. }
  198. #pragma mark - gOutgoingAnimatedHighlightedAlpha20
  199. static UIImage *gOutgoingAnimatedHighlightedAlpha20;
  200. + (UIImage *)outgoingAnimatedHighlightedAlpha20 {
  201. if (!gOutgoingAnimatedHighlightedAlpha20) {
  202. UIImage *alpha20 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg_alpha20")];
  203. [self setOutgoingAnimatedHighlightedAlpha20:TUIChatDynamicImage(@"chat_bubble_send_alpha20_img", alpha20)];
  204. }
  205. return gOutgoingAnimatedHighlightedAlpha20;
  206. }
  207. + (void)setOutgoingAnimatedHighlightedAlpha20:(UIImage *)outgoingAnimatedHighlightedAlpha20 {
  208. gOutgoingAnimatedHighlightedAlpha20 = [self stretchImage:outgoingAnimatedHighlightedAlpha20];
  209. }
  210. #pragma mark - gOutgoingAnimatedHighlightedAlpha50
  211. static UIImage *gOutgoingAnimatedHighlightedAlpha50;
  212. + (UIImage *)outgoingAnimatedHighlightedAlpha50 {
  213. if (!gOutgoingAnimatedHighlightedAlpha50) {
  214. UIImage *alpha50 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg_alpha50")];
  215. [self setOutgoingAnimatedHighlightedAlpha50:TUIChatDynamicImage(@"chat_bubble_send_alpha50_img", alpha50)];
  216. }
  217. return gOutgoingAnimatedHighlightedAlpha50;
  218. }
  219. + (void)setOutgoingAnimatedHighlightedAlpha50:(UIImage *)outgoingAnimatedHighlightedAlpha50 {
  220. gOutgoingAnimatedHighlightedAlpha50 = [self stretchImage:outgoingAnimatedHighlightedAlpha50];
  221. }
  222. #pragma mark - gIncommingBubble
  223. static UIImage *gIncommingBubble;
  224. + (UIImage *)incommingBubble {
  225. if (!gIncommingBubble) {
  226. UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ReceiverTextNodeBkg")];
  227. [self setIncommingBubble:defaultImage];
  228. }
  229. return gIncommingBubble;
  230. }
  231. + (void)setIncommingBubble:(UIImage *)incommingBubble {
  232. gIncommingBubble = [self stretchImage:incommingBubble];
  233. }
  234. #pragma mark - gIncommingSameBubble
  235. static UIImage *gIncommingSameBubble;
  236. + (UIImage *)incommingSameBubble {
  237. if (!gIncommingSameBubble) {
  238. UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ReceiverTextNodeBkg_Same")];
  239. [self setIncommingSameBubble:defaultImage];
  240. }
  241. return gIncommingSameBubble;
  242. }
  243. + (void)setIncommingSameBubble:(UIImage *)incommingSameBubble {
  244. gIncommingSameBubble = [self stretchImage:incommingSameBubble];
  245. }
  246. #pragma mark - gIncommingHighlightedBubble
  247. static UIImage *gIncommingHighlightedBubble;
  248. + (UIImage *)incommingHighlightedBubble {
  249. if (!gIncommingHighlightedBubble) {
  250. UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ReceiverTextNodeBkg")];
  251. [self setIncommingHighlightedBubble:defaultImage];
  252. }
  253. return gIncommingHighlightedBubble;
  254. }
  255. + (void)setIncommingHighlightedBubble:(UIImage *)incommingHighlightedBubble {
  256. gIncommingHighlightedBubble = [self stretchImage:incommingHighlightedBubble];
  257. }
  258. #pragma mark - gIncommingAnimatedHighlightedAlpha20
  259. static UIImage *gIncommingAnimatedHighlightedAlpha20;
  260. + (UIImage *)incommingAnimatedHighlightedAlpha20 {
  261. if (!gIncommingAnimatedHighlightedAlpha20) {
  262. UIImage *alpha20 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg_alpha20")];
  263. [self setIncommingAnimatedHighlightedAlpha20:TUIChatDynamicImage(@"chat_bubble_receive_alpha20_img", alpha20)];
  264. }
  265. return gIncommingAnimatedHighlightedAlpha20;
  266. }
  267. + (void)setIncommingAnimatedHighlightedAlpha20:(UIImage *)incommingAnimatedHighlightedAlpha20 {
  268. gIncommingAnimatedHighlightedAlpha20 = [self stretchImage:incommingAnimatedHighlightedAlpha20];
  269. }
  270. #pragma mark - gIncommingAnimatedHighlightedAlpha50
  271. static UIImage *gIncommingAnimatedHighlightedAlpha50;
  272. + (UIImage *)incommingAnimatedHighlightedAlpha50 {
  273. if (!gIncommingAnimatedHighlightedAlpha50) {
  274. UIImage *alpha50 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg_alpha50")];
  275. [self setIncommingAnimatedHighlightedAlpha50:TUIChatDynamicImage(@"chat_bubble_receive_alpha50_img", alpha50)];
  276. }
  277. return gIncommingAnimatedHighlightedAlpha50;
  278. }
  279. + (void)setIncommingAnimatedHighlightedAlpha50:(UIImage *)incommingAnimatedHighlightedAlpha50 {
  280. gIncommingAnimatedHighlightedAlpha50 = [self stretchImage:incommingAnimatedHighlightedAlpha50];
  281. }
  282. + (UIImage *)stretchImage:(UIImage *)oldImage {
  283. UIImage *image = [oldImage rtl_imageFlippedForRightToLeftLayoutDirection];
  284. UIEdgeInsets insets = rtlEdgeInsetsWithInsets(UIEdgeInsetsFromString(@"{12,12,12,12}"));
  285. return [image resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
  286. }
  287. static CGFloat gOutgoingBubbleTop = 0;
  288. + (CGFloat)outgoingBubbleTop {
  289. return gOutgoingBubbleTop;
  290. }
  291. + (void)setOutgoingBubbleTop:(CGFloat)outgoingBubble {
  292. gOutgoingBubbleTop = outgoingBubble;
  293. }
  294. static CGFloat gIncommingBubbleTop = 0;
  295. + (CGFloat)incommingBubbleTop {
  296. return gIncommingBubbleTop;
  297. }
  298. + (void)setIncommingBubbleTop:(CGFloat)incommingBubbleTop {
  299. gIncommingBubbleTop = incommingBubbleTop;
  300. }
  301. + (void)onThemeChanged:(NSNotification *)notice {
  302. gOutgoingBubble = nil;
  303. gOutgoingHighlightedBubble = nil;
  304. gOutgoingAnimatedHighlightedAlpha50 = nil;
  305. gOutgoingAnimatedHighlightedAlpha20 = nil;
  306. gIncommingBubble = nil;
  307. gIncommingHighlightedBubble = nil;
  308. gIncommingAnimatedHighlightedAlpha50 = nil;
  309. gIncommingAnimatedHighlightedAlpha20 = nil;
  310. }
  311. @end