TUIVideoMessageCellData.m 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //
  2. // TUIVideoMessageCellData.m
  3. // TXIMSDK_TUIKit_iOS
  4. //
  5. // Created by annidyfeng on 2019/5/21.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIVideoMessageCellData.h"
  9. #import <TIMCommon/TIMDefine.h>
  10. #import <TUICore/NSString+TUIUtil.h>
  11. #import <TUICore/TUILogin.h>
  12. #define TVideo_Block_Progress @"TVideo_Block_Progress";
  13. #define TVideo_Block_Response @"TVideo_Block_Response";
  14. @interface TUIVideoMessageCellData ()
  15. @property(nonatomic, strong) NSString *videoUrl;
  16. @property(nonatomic, assign) BOOL isDownloadingSnapshot;
  17. @property(nonatomic, assign) BOOL isDownloadingVideo;
  18. @property(nonatomic, copy) TUIVideoMessageDownloadCallback onFinish;
  19. @end
  20. @implementation TUIVideoMessageCellData
  21. + (TUIMessageCellData *)getCellData:(V2TIMMessage *)message {
  22. V2TIMVideoElem *elem = message.videoElem;
  23. TUIVideoMessageCellData *videoData = [[TUIVideoMessageCellData alloc] initWithDirection:(message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming)];
  24. videoData.videoPath = [elem.videoPath safePathString];
  25. videoData.snapshotPath = [elem.snapshotPath safePathString];
  26. videoData.videoItem = [[TUIVideoItem alloc] init];
  27. videoData.videoItem.uuid = elem.videoUUID;
  28. videoData.videoItem.type = elem.videoType;
  29. videoData.videoItem.length = elem.videoSize;
  30. videoData.videoItem.duration = elem.duration;
  31. videoData.snapshotItem = [[TUISnapshotItem alloc] init];
  32. videoData.snapshotItem.uuid = elem.snapshotUUID;
  33. // videoData.snapshotItem.type = elem.snaps;
  34. videoData.snapshotItem.length = elem.snapshotSize;
  35. videoData.snapshotItem.size = CGSizeMake(elem.snapshotWidth, elem.snapshotHeight);
  36. videoData.reuseId = TVideoMessageCell_ReuseId;
  37. return videoData;
  38. }
  39. + (TUIMessageCellData *)placeholderCellDataWithSnapshotUrl:(NSString *)snapshotUrl thubImage:(UIImage *)thubImage {
  40. TUIVideoMessageCellData *videoData = [[TUIVideoMessageCellData alloc] initWithDirection:(MsgDirectionOutgoing)];
  41. videoData.thumbImage = thubImage;
  42. videoData.snapshotPath = [snapshotUrl safePathString];
  43. videoData.videoItem = [[TUIVideoItem alloc] init];
  44. videoData.snapshotItem = [[TUISnapshotItem alloc] init];
  45. videoData.snapshotItem.size = CGSizeEqualToSize(thubImage.size, CGSizeZero) ? CGSizeMake(kScale375(100), kScale375(100)) : thubImage.size;
  46. videoData.reuseId = TVideoMessageCell_ReuseId;
  47. videoData.avatarUrl = [NSURL URLWithString:[TUILogin getFaceUrl]];
  48. videoData.isPlaceHolderCellData = YES;
  49. return videoData;
  50. }
  51. + (NSString *)getDisplayString:(V2TIMMessage *)message {
  52. return TIMCommonLocalizableString(TUIkitMessageTypeVideo);
  53. }
  54. - (Class)getReplyQuoteViewDataClass {
  55. return NSClassFromString(@"TUIVideoReplyQuoteViewData");
  56. }
  57. - (Class)getReplyQuoteViewClass {
  58. return NSClassFromString(@"TUIVideoReplyQuoteView");
  59. }
  60. - (instancetype)initWithDirection:(TMsgDirection)direction {
  61. self = [super initWithDirection:direction];
  62. if (self) {
  63. _uploadProgress = 100;
  64. _isDownloadingVideo = NO;
  65. _isDownloadingSnapshot = NO;
  66. if (direction == MsgDirectionIncoming) {
  67. self.cellLayout = [TUIMessageCellLayout incommingVideoMessageLayout];
  68. } else {
  69. self.cellLayout = [TUIMessageCellLayout outgoingVideoMessageLayout];
  70. }
  71. }
  72. return self;
  73. }
  74. - (void)downloadThumb:(TUIVideoMessageDownloadCallback)finish {
  75. self.onFinish = finish;
  76. [self downloadThumb];
  77. }
  78. - (void)downloadThumb {
  79. BOOL isExist = NO;
  80. NSString *path = [self getSnapshotPath:&isExist];
  81. if (isExist) {
  82. [self decodeThumb];
  83. return;
  84. }
  85. if (self.isDownloadingSnapshot) {
  86. return;
  87. }
  88. self.isDownloadingSnapshot = YES;
  89. @weakify(self);
  90. V2TIMMessage *imMsg = self.innerMessage;
  91. if (imMsg.elemType == V2TIM_ELEM_TYPE_VIDEO) {
  92. // Avoid large files that slow down callback progress.
  93. [self updateThumbProgress:1];
  94. [imMsg.videoElem downloadSnapshot:path
  95. progress:^(NSInteger curSize, NSInteger totalSize) {
  96. [self updateThumbProgress:MAX(1, curSize * 100 / totalSize)];
  97. }
  98. succ:^{
  99. @strongify(self);
  100. self.isDownloadingSnapshot = NO;
  101. [self updateThumbProgress:100];
  102. [self decodeThumb];
  103. }
  104. fail:^(int code, NSString *msg) {
  105. @strongify(self);
  106. self.isDownloadingSnapshot = NO;
  107. }];
  108. }
  109. }
  110. - (void)updateThumbProgress:(NSUInteger)progress {
  111. dispatch_async(dispatch_get_main_queue(), ^{
  112. self.thumbProgress = progress;
  113. });
  114. }
  115. - (void)decodeThumb {
  116. BOOL isExist = NO;
  117. NSString *path = [self getSnapshotPath:&isExist];
  118. if (!isExist) {
  119. return;
  120. }
  121. @weakify(self);
  122. [TUITool asyncDecodeImage:path
  123. complete:^(NSString *path, UIImage *image) {
  124. @strongify(self);
  125. @weakify(self);
  126. dispatch_async(dispatch_get_main_queue(), ^{
  127. @strongify(self);
  128. self.thumbImage = image;
  129. self.thumbProgress = 100;
  130. if (self.onFinish) {
  131. self.onFinish();
  132. }
  133. });
  134. }];
  135. }
  136. - (void)downloadVideo {
  137. BOOL isExist = NO;
  138. NSString *path = [self getVideoPath:&isExist];
  139. if (isExist) {
  140. return;
  141. }
  142. if (self.isDownloadingVideo) {
  143. return;
  144. }
  145. self.isDownloadingVideo = YES;
  146. @weakify(self);
  147. V2TIMMessage *imMsg = self.innerMessage;
  148. if (imMsg.elemType == V2TIM_ELEM_TYPE_VIDEO) {
  149. [imMsg.videoElem downloadVideo:path
  150. progress:^(NSInteger curSize, NSInteger totalSize) {
  151. @strongify(self);
  152. [self updateVideoProgress:curSize * 100 / totalSize];
  153. }
  154. succ:^{
  155. @strongify(self);
  156. self.isDownloadingVideo = NO;
  157. [self updateVideoProgress:100];
  158. dispatch_async(dispatch_get_main_queue(), ^{
  159. self.videoPath = path;
  160. });
  161. }
  162. fail:^(int code, NSString *msg) {
  163. @strongify(self);
  164. self.isDownloadingVideo = NO;
  165. }];
  166. }
  167. }
  168. - (void)updateVideoProgress:(NSUInteger)progress {
  169. dispatch_async(dispatch_get_main_queue(), ^{
  170. self.videoProgress = progress;
  171. });
  172. }
  173. - (void)getVideoUrl:(void (^)(NSString *url))urlCallBack {
  174. if (!urlCallBack) {
  175. return;
  176. }
  177. if (self.videoUrl) {
  178. urlCallBack(self.videoUrl);
  179. }
  180. @weakify(self);
  181. V2TIMMessage *imMsg = self.innerMessage;
  182. if (imMsg.elemType == V2TIM_ELEM_TYPE_VIDEO) {
  183. [imMsg.videoElem getVideoUrl:^(NSString *url) {
  184. @strongify(self);
  185. self.videoUrl = url;
  186. urlCallBack(self.videoUrl);
  187. }];
  188. }
  189. }
  190. - (BOOL)isVideoExist {
  191. BOOL isExist;
  192. [self getVideoPath:&isExist];
  193. return isExist;
  194. }
  195. - (NSString *)getVideoPath:(BOOL *)isExist {
  196. NSString *path = nil;
  197. BOOL isDir = NO;
  198. *isExist = NO;
  199. if (_videoPath && _videoPath.lastPathComponent.length) {
  200. path = _videoPath;
  201. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  202. if (!isDir) {
  203. *isExist = YES;
  204. }
  205. }
  206. else {
  207. path = [NSString stringWithFormat:@"%@%@", TUIKit_Video_Path, _videoPath.lastPathComponent];
  208. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  209. if (!isDir) {
  210. *isExist = YES;
  211. }
  212. }
  213. }
  214. }
  215. if (!*isExist) {
  216. if (_videoItem) {
  217. if (_videoItem.uuid && _videoItem.uuid.length && _videoItem.type && _videoItem.type.length) {
  218. path = [NSString stringWithFormat:@"%@%@.%@", TUIKit_Video_Path, _videoItem.uuid, _videoItem.type];
  219. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  220. if (!isDir) {
  221. *isExist = YES;
  222. }
  223. }
  224. }
  225. }
  226. }
  227. if (*isExist) {
  228. _videoPath = path;
  229. }
  230. return path;
  231. }
  232. - (NSString *)getSnapshotPath:(BOOL *)isExist {
  233. NSString *path = nil;
  234. BOOL isDir = NO;
  235. *isExist = NO;
  236. if (_snapshotPath && _snapshotPath.length) {
  237. path = [NSString stringWithFormat:@"%@%@", TUIKit_Video_Path, _snapshotPath.lastPathComponent];
  238. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  239. if (!isDir) {
  240. *isExist = YES;
  241. }
  242. }
  243. }
  244. if (!*isExist) {
  245. if (_snapshotItem) {
  246. if (_snapshotItem.uuid && _snapshotItem.uuid.length) {
  247. path = [NSString stringWithFormat:@"%@%@", TUIKit_Video_Path, _snapshotItem.uuid];
  248. path = [TUIKit_Video_Path stringByAppendingString:_snapshotItem.uuid];
  249. if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
  250. if (!isDir) {
  251. *isExist = YES;
  252. }
  253. }
  254. }
  255. }
  256. }
  257. return path;
  258. }
  259. @end