TUIImageMessageCellData.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. //
  2. // TUIImageMessageCellData.m
  3. // TXIMSDK_TUIKit_iOS
  4. //
  5. // Created by annidyfeng on 2019/5/21.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIImageMessageCellData.h"
  9. #import <TIMCommon/TIMDefine.h>
  10. #import <TUICore/NSString+TUIUtil.h>
  11. @interface TUIImageMessageCellData ()
  12. @property(nonatomic, assign) BOOL isDownloading;
  13. @property(nonatomic, copy) TUIImageMessageDownloadCallback onFinish;
  14. @end
  15. @implementation TUIImageMessageCellData
  16. + (TUIMessageCellData *)getCellData:(V2TIMMessage *)message {
  17. V2TIMImageElem *elem = message.imageElem;
  18. TUIImageMessageCellData *imageData = [[TUIImageMessageCellData alloc] initWithDirection:(message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming)];
  19. imageData.path = [elem.path safePathString];
  20. imageData.items = [NSMutableArray array];
  21. for (V2TIMImage *item in elem.imageList) {
  22. TUIImageItem *itemData = [[TUIImageItem alloc] init];
  23. itemData.uuid = item.uuid;
  24. itemData.size = CGSizeMake(item.width, item.height);
  25. // itemData.url = item.url;
  26. if (item.type == V2TIM_IMAGE_TYPE_THUMB) {
  27. itemData.type = TImage_Type_Thumb;
  28. } else if (item.type == V2TIM_IMAGE_TYPE_LARGE) {
  29. itemData.type = TImage_Type_Large;
  30. } else if (item.type == V2TIM_IMAGE_TYPE_ORIGIN) {
  31. itemData.type = TImage_Type_Origin;
  32. }
  33. [imageData.items addObject:itemData];
  34. }
  35. imageData.reuseId = TImageMessageCell_ReuseId;
  36. return imageData;
  37. }
  38. + (NSString *)getDisplayString:(V2TIMMessage *)message {
  39. return TIMCommonLocalizableString(TUIkitMessageTypeImage); // @"[Image]";
  40. }
  41. - (Class)getReplyQuoteViewDataClass {
  42. return NSClassFromString(@"TUIImageReplyQuoteViewData");
  43. }
  44. - (Class)getReplyQuoteViewClass {
  45. return NSClassFromString(@"TUIImageReplyQuoteView");
  46. }
  47. - (instancetype)initWithDirection:(TMsgDirection)direction {
  48. self = [super initWithDirection:direction];
  49. if (self) {
  50. _uploadProgress = 100;
  51. if (direction == MsgDirectionIncoming) {
  52. self.cellLayout = [TUIMessageCellLayout incommingImageMessageLayout];
  53. } else {
  54. self.cellLayout = [TUIMessageCellLayout outgoingImageMessageLayout];
  55. }
  56. }
  57. return self;
  58. }
  59. - (NSString *)getImagePath:(TUIImageType)type isExist:(BOOL *)isExist {
  60. NSString *path = nil;
  61. BOOL isDir = NO;
  62. *isExist = NO;
  63. if (self.direction == MsgDirectionOutgoing) {
  64. path = [NSString stringWithFormat:@"%@%@", TUIKit_Image_Path, _path.lastPathComponent];
  65. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  66. if (!isDir) {
  67. *isExist = YES;
  68. }
  69. }
  70. }
  71. if (!*isExist) {
  72. TUIImageItem *tImageItem = [self getTImageItem:type];
  73. path = [NSString stringWithFormat:@"%@%@_%ld", TUIKit_Image_Path, tImageItem.uuid, (long)tImageItem.type];
  74. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  75. if (!isDir) {
  76. *isExist = YES;
  77. }
  78. }
  79. }
  80. return path;
  81. }
  82. - (void)downloadImage:(TUIImageType)type finish:(TUIImageMessageDownloadCallback)finish {
  83. self.onFinish = finish;
  84. [self downloadImage:type];
  85. }
  86. - (void)downloadImage:(TUIImageType)type {
  87. BOOL isExist = NO;
  88. NSString *path = [self getImagePath:type isExist:&isExist];
  89. if (isExist) {
  90. [self decodeImage:type];
  91. return;
  92. }
  93. if (self.isDownloading) {
  94. return;
  95. }
  96. self.isDownloading = YES;
  97. V2TIMImage *imImage = [self getIMImage:type];
  98. @weakify(self);
  99. [imImage downloadImage:path
  100. progress:^(NSInteger curSize, NSInteger totalSize) {
  101. @strongify(self);
  102. NSInteger progress = curSize * 100 / totalSize;
  103. [self updateProgress:MIN(progress, 99) withType:type];
  104. }
  105. succ:^{
  106. @strongify(self);
  107. self.isDownloading = NO;
  108. [self updateProgress:100 withType:type];
  109. [self decodeImage:type];
  110. }
  111. fail:^(int code, NSString *msg) {
  112. @strongify(self);
  113. self.isDownloading = NO;
  114. /**
  115. * If the uuid of the picture is the same (the same user sends
  116. * the same picture continuously), the same path may trigger multiple download operations. Except for the first time, subsequent downloads will report
  117. * an error. At this time, it is necessary to judge whether the local file exists.
  118. */
  119. [self decodeImage:type];
  120. }];
  121. }
  122. - (void)updateProgress:(NSUInteger)progress withType:(TUIImageType)type {
  123. dispatch_async(dispatch_get_main_queue(), ^{
  124. if (type == TImage_Type_Thumb) self.thumbProgress = progress;
  125. if (type == TImage_Type_Large) self.largeProgress = progress;
  126. if (type == TImage_Type_Origin) self.originProgress = progress;
  127. });
  128. }
  129. - (void)decodeImage:(TUIImageType)type {
  130. BOOL isExist = NO;
  131. NSString *path = [self getImagePath:type isExist:&isExist];
  132. if (!isExist) {
  133. return;
  134. }
  135. __weak typeof(self) weakSelf = self;
  136. void (^finishBlock)(UIImage *) = ^(UIImage *image) {
  137. if (type == TImage_Type_Thumb) {
  138. weakSelf.thumbImage = image;
  139. weakSelf.thumbProgress = 100;
  140. weakSelf.uploadProgress = 100;
  141. }
  142. if (type == TImage_Type_Large) {
  143. weakSelf.largeImage = image;
  144. weakSelf.largeProgress = 100;
  145. }
  146. if (type == TImage_Type_Origin) {
  147. weakSelf.originImage = image;
  148. weakSelf.originProgress = 100;
  149. }
  150. if (weakSelf.onFinish) {
  151. weakSelf.onFinish();
  152. }
  153. };
  154. NSString *cacheKey = [path substringFromIndex:TUIKit_Image_Path.length];
  155. UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromCacheForKey:cacheKey];
  156. if (cacheImage) {
  157. finishBlock(cacheImage);
  158. } else {
  159. [TUITool asyncDecodeImage:path
  160. complete:^(NSString *path, UIImage *image) {
  161. dispatch_async(dispatch_get_main_queue(), ^{
  162. NSLog(@"image.sd_imageFormat: %ld path:%@ image.sd_imageData.length :%lu",(long)image.sd_imageFormat,path,(unsigned long)image.sd_imageData.length);
  163. if (![path tui_containsString:@".gif"] || (image.sd_imageFormat != SDImageFormatGIF) ) {
  164. [[SDImageCache sharedImageCache] storeImageToMemory:image forKey:cacheKey];
  165. }
  166. else {
  167. /**
  168. * The gif image is too large to be cached in memory
  169. * Only cache images less than 1M
  170. */
  171. if (image.sd_imageData.length < 1 * 1024 * 1024) {
  172. [[SDImageCache sharedImageCache] storeImageToMemory:image forKey:cacheKey];
  173. }
  174. }
  175. finishBlock(image);
  176. });
  177. }];
  178. }
  179. }
  180. - (TUIImageItem *)getTImageItem:(TUIImageType)type {
  181. for (TUIImageItem *item in self.items) {
  182. if (item.type == type) {
  183. return item;
  184. }
  185. }
  186. return nil;
  187. }
  188. - (V2TIMImage *)getIMImage:(TUIImageType)type {
  189. V2TIMMessage *imMsg = self.innerMessage;
  190. if (imMsg.elemType == V2TIM_ELEM_TYPE_IMAGE) {
  191. for (V2TIMImage *imImage in imMsg.imageElem.imageList) {
  192. if (type == TImage_Type_Thumb && imImage.type == V2TIM_IMAGE_TYPE_THUMB) {
  193. return imImage;
  194. } else if (type == TImage_Type_Origin && imImage.type == V2TIM_IMAGE_TYPE_ORIGIN) {
  195. return imImage;
  196. } else if (type == TImage_Type_Large && imImage.type == V2TIM_IMAGE_TYPE_LARGE) {
  197. return imImage;
  198. }
  199. }
  200. }
  201. return nil;
  202. }
  203. @end