WFCUCompositeMessageViewController.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. //
  2. // WFCUCompositeMessageViewController.m
  3. // WFChatUIKit
  4. //
  5. // Created by Tom Lee on 2020/10/4.
  6. // Copyright © 2020 WildFireChat. All rights reserved.
  7. //
  8. #import "WFCUCompositeMessageViewController.h"
  9. #import <WFChatClient/WFCChatClient.h>
  10. #import "WFCUUtilities.h"
  11. #import "WFCUCompositeBaseCell.h"
  12. #import "WFCUCompositeTextCell.h"
  13. #import <CommonCrypto/CommonCrypto.h>
  14. #import "MBProgressHUD.h"
  15. @interface WFCUCompositeMessageViewController () <UITableViewDelegate, UITableViewDataSource>
  16. @property(nonatomic, strong)UITableView *tableView;
  17. @property(nonatomic, strong)NSMutableArray<WFCCMessage *> *messages;
  18. @property (nonatomic, strong)WFCCCompositeMessageContent *compositeContent;
  19. @end
  20. @implementation WFCUCompositeMessageViewController
  21. - (void)viewDidLoad {
  22. [super viewDidLoad];
  23. self.view.backgroundColor = [UIColor whiteColor];
  24. self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
  25. if (@available(iOS 15, *)) {
  26. self.tableView.sectionHeaderTopPadding = 0;
  27. }
  28. self.tableView.delegate = self;
  29. self.tableView.dataSource = self;
  30. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  31. self.messages = [[NSMutableArray alloc] initWithArray:self.compositeContent.messages];
  32. [self setupTableHeaderView];
  33. self.title = self.compositeContent.title;
  34. self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
  35. [self.tableView reloadData];
  36. [self.view addSubview:self.tableView];
  37. if (!self.compositeContent.loaded && self.compositeContent.remoteUrl) {
  38. [self downloadComositeContent];
  39. }
  40. }
  41. - (void)downloadComositeContent {
  42. MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
  43. hud.label.text = WFCString(@"Loading");
  44. [hud showAnimated:YES];
  45. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  46. NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.compositeContent.remoteUrl]];
  47. dispatch_async(dispatch_get_main_queue(), ^{
  48. [hud hideAnimated:YES];
  49. if(data.length) {
  50. NSString *uuid = nil;
  51. if (self.message.messageId > 0) {
  52. CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault);
  53. uuid = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuidObject));
  54. CFRelease(uuidObject);
  55. } else {
  56. uuid = [self getMD5WithData:data];
  57. }
  58. NSString *path = [[WFCCUtilities getDocumentPathWithComponent:@"/COMPOSITE_MESSAGE"] stringByAppendingPathComponent:uuid];
  59. if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {
  60. [data writeToFile:path atomically:YES];
  61. }
  62. WFCCCompositeMessageContent *content = self.compositeContent;
  63. content.localPath = path;
  64. self.message.content = content;
  65. if (self.message.messageId > 0) {
  66. [[WFCCIMService sharedWFCIMService] updateMessage:self.message.messageId content:content];
  67. }
  68. self.messages = [[NSMutableArray alloc] initWithArray:self.compositeContent.messages];
  69. [self.tableView reloadData];
  70. } else {
  71. MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
  72. hud.mode = MBProgressHUDModeText;
  73. hud.label.text = WFCString(@"LoadFailure");
  74. hud.offset = CGPointMake(0.f, MBProgressMaxOffset);
  75. [hud hideAnimated:YES afterDelay:1.f];
  76. }
  77. });
  78. });
  79. }
  80. - (NSString *)getMD5WithData:(NSData *)data {
  81. CC_MD5_CTX md5;
  82. CC_MD5_Init(&md5);
  83. CC_MD5_Update(&md5, data.bytes, (uint32_t)data.length);
  84. unsigned char result[CC_MD5_DIGEST_LENGTH];
  85. CC_MD5_Final(result, &md5);
  86. NSMutableString *resultString = [NSMutableString string];
  87. for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
  88. [resultString appendFormat:@"%02x", result[i]];
  89. }
  90. return resultString;
  91. }
  92. - (WFCCCompositeMessageContent *)compositeContent {
  93. return (WFCCCompositeMessageContent *)self.message.content;
  94. }
  95. - (void)setupTableHeaderView {
  96. #define HEADER_HEIGHT 30
  97. #define HEADER_FONT_SIZE 16
  98. #define HEADER_LINE_PADDING 16
  99. NSDate *from = [[NSDate alloc] initWithTimeIntervalSince1970:self.messages.firstObject.serverTime/1000];
  100. NSDate *to = [[NSDate alloc] initWithTimeIntervalSince1970:self.messages.lastObject.serverTime/1000];
  101. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  102. [dateFormatter setDateFormat:@"yyyy-MM-dd"];
  103. [dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
  104. NSString *fromString = [dateFormatter stringFromDate:from];
  105. NSString *toString = [dateFormatter stringFromDate:to];
  106. CGFloat width = self.view.frame.size.width;
  107. UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, HEADER_HEIGHT)];
  108. NSString *timeString;
  109. if ([fromString isEqualToString:toString]) {
  110. timeString = fromString;
  111. } else {
  112. timeString = [NSString stringWithFormat:@"%@ 至 %@", fromString, toString];
  113. }
  114. CGSize size = [WFCUUtilities getTextDrawingSize:timeString font:[UIFont systemFontOfSize:HEADER_FONT_SIZE] constrainedSize:CGSizeMake(width, HEADER_HEIGHT)];
  115. UIView *leftLine = [[UIView alloc] initWithFrame:CGRectMake(HEADER_LINE_PADDING, HEADER_HEIGHT/2, (width-size.width)/2-HEADER_LINE_PADDING-HEADER_LINE_PADDING, 1)];
  116. leftLine.backgroundColor = [UIColor grayColor];
  117. [headerView addSubview:leftLine];
  118. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake((width-size.width)/2, (HEADER_HEIGHT-size.height)/2, size.width, size.height)];
  119. label.text = timeString;
  120. label.textColor = [UIColor grayColor];
  121. label.font = [UIFont systemFontOfSize:HEADER_FONT_SIZE];
  122. [headerView addSubview:label];
  123. UIView *rightLine = [[UIView alloc] initWithFrame:CGRectMake((width+size.width)/2+HEADER_LINE_PADDING, HEADER_HEIGHT/2, (width-size.width)/2-HEADER_LINE_PADDING-HEADER_LINE_PADDING, 1)];
  124. rightLine.backgroundColor = [UIColor grayColor];
  125. [headerView addSubview:rightLine];
  126. self.tableView.tableHeaderView = headerView;
  127. }
  128. #pragma mark - UITableViewDataSource
  129. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  130. return self.messages.count;
  131. }
  132. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  133. WFCCMessage *msg = self.messages[indexPath.row];
  134. WFCUCompositeBaseCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([msg.content class])];
  135. if (!cell) {
  136. cell = [WFCUCompositeBaseCell cellOfMessage:msg];
  137. }
  138. if (indexPath.row == self.messages.count-1) {
  139. cell.lastMessage = YES;
  140. } else {
  141. cell.lastMessage = NO;
  142. }
  143. BOOL sameUser = NO;
  144. if (indexPath.row != 0) {
  145. WFCCMessage *premsg = self.messages[indexPath.row-1];
  146. if ([premsg.fromUser isEqualToString:msg.fromUser]) {
  147. sameUser = YES;
  148. }
  149. }
  150. cell.hiddenPortrait = sameUser;
  151. cell.message = msg;
  152. return cell;
  153. }
  154. -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  155. WFCCMessage *msg = self.messages[indexPath.row];
  156. WFCUCompositeBaseCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([msg.content class])];
  157. if (!cell) {
  158. cell = [WFCUCompositeBaseCell cellOfMessage:msg];
  159. }
  160. return [cell.class heightForMessage:msg];
  161. }
  162. @end