ShareViewController.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. //
  2. // ShareViewController.m
  3. // ShareExtension
  4. //
  5. // Created by Tom Lee on 2020/10/6.
  6. // Copyright © 2020 WildFireChat. All rights reserved.
  7. //
  8. #import "ShareViewController.h"
  9. #import "ConversationListViewController.h"
  10. #import "ShareAppService.h"
  11. #import "WFCConfig.h"
  12. #import "ShareUtility.h"
  13. #import "MBProgressHUD.h"
  14. @interface ShareViewController () <UITableViewDataSource, UITableViewDelegate>
  15. @property(nonatomic, strong)UITableView *tableView;
  16. @property(nonatomic, assign)BOOL dataLoaded;
  17. //文本
  18. @property(nonatomic, strong)NSString *textMessageContent;
  19. //链接
  20. @property(nonatomic, strong)NSString *urlTitle;
  21. @property(nonatomic, strong)NSString *url;
  22. @property(nonatomic, strong)NSString *urlThumbnail;
  23. //图片
  24. @property(nonatomic, assign)BOOL *fullImage;
  25. @property(nonatomic, strong)NSMutableArray<NSString *> *imageUrls;
  26. @property(nonatomic, strong)UIImage *image;
  27. //文件
  28. @property(nonatomic, strong)NSString *fileUrl;
  29. @end
  30. @implementation ShareViewController
  31. - (void)viewDidLoad {
  32. [super viewDidLoad];
  33. self.view.backgroundColor = [UIColor whiteColor];
  34. if (![[ShareAppService sharedAppService] isLogin]) {
  35. __weak typeof(self)ws = self;
  36. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"没有登录" message:@"请先登录野火IM" preferredStyle:UIAlertControllerStyleAlert];
  37. UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
  38. [ws.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
  39. }];
  40. [alertController addAction:cancel];
  41. [ws presentViewController:alertController animated:YES completion:nil];
  42. return;
  43. }
  44. self.dataLoaded = NO;
  45. self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleDone target:self action:@selector(onLeftBarBtn:)];
  46. self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStyleGrouped];
  47. if (@available(iOS 15, *)) {
  48. self.tableView.sectionHeaderTopPadding = 0;
  49. }
  50. self.tableView.delegate = self;
  51. self.tableView.dataSource = self;
  52. [self.view addSubview:self.tableView];
  53. self.tableView.tableHeaderView = [self loadTableViewHeader];
  54. self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
  55. [self.tableView reloadData];
  56. }
  57. - (UIView *)loadTableViewHeader {
  58. CGFloat width = self.view.bounds.size.width;
  59. UIView *header = [[UIView alloc] initWithFrame:CGRectZero];
  60. if (self.extensionContext.inputItems.count) {
  61. NSExtensionItem *item = self.extensionContext.inputItems[0];
  62. NSLog(@"title: %@", item.attributedTitle);
  63. NSLog(@"content: %@", item.attributedContentText.string);
  64. if (item.attachments.count) {
  65. __weak typeof(self)ws = self;
  66. for (NSItemProvider *provider in item.attachments) {
  67. NSLog(@"the provider is %@", provider);
  68. header.frame = CGRectMake(0, 0, width, 40);
  69. UILabel *fileLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 8, width, 24)];
  70. [header addSubview:fileLabel];
  71. if ([provider hasItemConformingToTypeIdentifier:@"public.file-url"]) {
  72. [provider loadItemForTypeIdentifier:@"public.file-url" options:nil completionHandler:^(__kindof id<NSSecureCoding> _Nullable item, NSError * _Null_unspecified error) {
  73. NSURL *url = (NSURL *)item;
  74. NSString *fileName = url.absoluteString.lastPathComponent;
  75. NSLog(@"file name is %@", fileName);
  76. ws.fileUrl = url.absoluteString;
  77. dispatch_async(dispatch_get_main_queue(), ^{
  78. fileLabel.text = fileName;
  79. ws.dataLoaded = YES;
  80. });
  81. }];
  82. } else if ([provider hasItemConformingToTypeIdentifier:@"public.url"]) {
  83. //链接
  84. header.frame = CGRectMake(0, 0, width, 132);
  85. UIImageView *iconView = [[UIImageView alloc] initWithFrame:CGRectMake(16, 16, 100, 100)];
  86. [header addSubview:iconView];
  87. UILabel *titleLabel = [[UILabel alloc] init];
  88. titleLabel.text = item.attributedContentText.string;
  89. titleLabel.font = [UIFont systemFontOfSize:18];
  90. titleLabel.numberOfLines = 0;
  91. CGSize titleSize = [self getTextDrawingSize:item.attributedContentText.string font:titleLabel.font constrainedSize:CGSizeMake(width, 48)];
  92. titleLabel.frame = CGRectMake(132, 16, width-132-16, titleSize.height);
  93. [header addSubview: titleLabel];
  94. UILabel *contentLabel = [[UILabel alloc] initWithFrame:CGRectMake(132, titleSize.height + 16 + 8, width-132-16, 0)];
  95. contentLabel.numberOfLines = 0;
  96. contentLabel.textColor = [UIColor grayColor];
  97. contentLabel.font = [UIFont systemFontOfSize:16];
  98. [header addSubview: contentLabel];
  99. self.urlTitle = item.attributedContentText.string;
  100. [provider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(__kindof id<NSSecureCoding> _Nullable item, NSError * _Null_unspecified error) {
  101. NSURL *url = (NSURL *)item;
  102. if ([url.scheme isEqualToString:@"http"] || [url.scheme isEqualToString:@"https"]) {
  103. NSString *favIcon = [NSString stringWithFormat:@"%@://%@/favicon.ico", url.scheme, url.host];
  104. dispatch_async(dispatch_get_main_queue(), ^{
  105. contentLabel.text = url.absoluteString;
  106. CGSize size = [ws getTextDrawingSize:url.absoluteString font:contentLabel.font constrainedSize:CGSizeMake(width, 132 - 16 - titleSize.height - 8 - 8)];
  107. CGRect frame = contentLabel.frame;
  108. frame.size.height = size.height;
  109. contentLabel.frame = frame;
  110. ws.url = url.absoluteString;
  111. ws.dataLoaded = YES;
  112. iconView.image = [UIImage imageNamed:@"DefaultLink"];
  113. });
  114. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  115. UIImage *portrait = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:favIcon]]];
  116. if (portrait) {
  117. dispatch_async(dispatch_get_main_queue(), ^{
  118. iconView.image = portrait;
  119. ws.urlThumbnail = favIcon;
  120. });
  121. }
  122. });
  123. }
  124. }];
  125. } else if ([provider hasItemConformingToTypeIdentifier:@"public.jpeg"] || [provider hasItemConformingToTypeIdentifier:@"public.png"] || [provider hasItemConformingToTypeIdentifier:@"public.image"]) {
  126. header.frame = CGRectMake(0, 0, width, 400);
  127. UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, 400)];
  128. [header addSubview:imageView];
  129. self.imageUrls = [[NSMutableArray alloc] init];
  130. NSString *typeIdentifier = @"public.jpeg";
  131. if ([provider hasItemConformingToTypeIdentifier:@"public.png"]) {
  132. typeIdentifier = @"public.png";
  133. } else if ([provider hasItemConformingToTypeIdentifier:@"public.image"]) {
  134. typeIdentifier = @"public.image";
  135. }
  136. [provider loadItemForTypeIdentifier:typeIdentifier options:nil completionHandler:^(__kindof id<NSSecureCoding> _Nullable item, NSError * _Null_unspecified error) {
  137. NSLog(@"the value is %@", item);
  138. UIImage *image = nil;
  139. if ([provider hasItemConformingToTypeIdentifier:@"public.image"] && [item isKindOfClass:[UIImage class]]) {
  140. image = (UIImage *)item;
  141. ws.dataLoaded = YES;
  142. ws.image = image;
  143. } else {
  144. NSURL *url = (NSURL *)item;
  145. if ([url.scheme isEqual:@"file"]) {
  146. ws.dataLoaded = YES;
  147. [ws.imageUrls addObject:url.absoluteString];
  148. image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
  149. }
  150. }
  151. dispatch_async(dispatch_get_main_queue(), ^{
  152. imageView.image = image;
  153. NSExtensionItem *item = ws.extensionContext.inputItems[0];
  154. if (item.attachments.count > 1) {
  155. [ws showImageLimit];
  156. }
  157. [ws.tableView reloadData];
  158. });
  159. }];
  160. break;
  161. } else if ([provider hasItemConformingToTypeIdentifier:@"public.plain-text"]) {
  162. self.textMessageContent = item.attributedContentText.string;
  163. header.frame = CGRectMake(0, 0, width, 132);
  164. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 132)];
  165. label.numberOfLines = 0;
  166. label.text = item.attributedContentText.string;
  167. [header addSubview:label];
  168. self.dataLoaded = YES;
  169. } else if ([provider hasItemConformingToTypeIdentifier:@"public.jpeg"] || [provider hasItemConformingToTypeIdentifier:@"public.png"]) {
  170. }
  171. }
  172. }
  173. }
  174. return header;
  175. }
  176. - (void)setDataLoaded:(BOOL)dataLoaded {
  177. _dataLoaded = dataLoaded;
  178. [self.tableView reloadData];
  179. }
  180. - (void)onLeftBarBtn:(id)sender {
  181. [self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
  182. }
  183. - (CGSize)getTextDrawingSize:(NSString *)text
  184. font:(UIFont *)font
  185. constrainedSize:(CGSize)constrainedSize {
  186. if (text.length <= 0) {
  187. return CGSizeZero;
  188. }
  189. if ([text respondsToSelector:@selector(boundingRectWithSize:
  190. options:
  191. attributes:
  192. context:)]) {
  193. return [text boundingRectWithSize:constrainedSize
  194. options:(NSStringDrawingTruncatesLastVisibleLine |
  195. NSStringDrawingUsesLineFragmentOrigin |
  196. NSStringDrawingUsesFontLeading)
  197. attributes:@{
  198. NSFontAttributeName : font
  199. }
  200. context:nil]
  201. .size;
  202. } else {
  203. return [text sizeWithFont:font
  204. constrainedToSize:constrainedSize
  205. lineBreakMode:NSLineBreakByTruncatingTail];
  206. }
  207. }
  208. - (void)sendTo:(SharedConversation *)conversation {
  209. __weak typeof(self)ws = self;
  210. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"确认发送给" message:conversation.title preferredStyle:UIAlertControllerStyleAlert];
  211. UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
  212. [MBProgressHUD showHUDAddedTo:ws.view animated:YES];
  213. [MBProgressHUD HUDForView:ws.view].mode = MBProgressHUDModeDeterminate;
  214. [MBProgressHUD HUDForView:ws.view].label.text = @"正在发送中...";
  215. if (ws.textMessageContent.length) {
  216. [[ShareAppService sharedAppService] sendTextMessage:conversation text:ws.textMessageContent success:^(NSDictionary * _Nonnull dict) {
  217. [ws showSuccess];
  218. } error:^(NSString * _Nonnull message) {
  219. [ws showFailure];
  220. }];
  221. } else if(ws.url.length) {
  222. [[ShareAppService sharedAppService] sendLinkMessage:conversation link:ws.url title:ws.urlTitle thumbnailLink:ws.urlThumbnail success:^(NSDictionary * _Nonnull dict) {
  223. [ws showSuccess];
  224. } error:^(NSString * _Nonnull message) {
  225. NSLog(@"send msg failure %@", message);
  226. [ws showFailure];
  227. }];
  228. } else if(ws.imageUrls.count) {
  229. [[ShareAppService sharedAppService] uploadFiles:ws.imageUrls[0] mediaType:1 fullImage:self.fullImage progress:^(int sentcount, int dataSize) {
  230. [ws showProgress:sentcount total:dataSize];
  231. } success:^(NSString *url){
  232. UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ws.imageUrls[0]]]];
  233. UIImage *thumbnail = [ShareUtility generateThumbnail:image withWidth:120 withHeight:120];
  234. [[ShareAppService sharedAppService] sendImageMessage:conversation
  235. mediaUrl:url
  236. thubnail:thumbnail
  237. success:^(NSDictionary * _Nonnull dict) {
  238. [ws showSuccess];
  239. }
  240. error:^(NSString * _Nonnull message) {
  241. [ws showFailure];
  242. }];
  243. } error:^(NSString * _Nonnull errorMsg) {
  244. [ws showFailure];
  245. }];
  246. } else if(ws.fileUrl.length) {
  247. __block int size = 0;
  248. [[ShareAppService sharedAppService] uploadFiles:ws.fileUrl mediaType:4 fullImage:YES progress:^(int sentcount, int total) {
  249. size = total;
  250. [ws showProgress:sentcount total:total];
  251. } success:^(NSString * _Nonnull url) {
  252. NSString *fileName = ws.fileUrl.lastPathComponent;
  253. [[ShareAppService sharedAppService] sendFileMessage:conversation mediaUrl:url fileName:fileName size:size success:^(NSDictionary * _Nonnull dict) {
  254. [ws showSuccess];
  255. } error:^(NSString * _Nonnull message) {
  256. [ws showFailure];
  257. }];
  258. } error:^(NSString * _Nonnull errorMsg) {
  259. [ws showFailure];
  260. }];
  261. } else if(ws.image) {
  262. UIImage *image = [ShareUtility generateThumbnail:ws.image withWidth:1024 withHeight:1024];
  263. NSData *imgData = UIImageJPEGRepresentation(image, 0.85);
  264. [[ShareAppService sharedAppService] uploadData:imgData mediaType:1 progress:^(int sentcount, int total) {
  265. [ws showProgress:sentcount total:total];
  266. } success:^(NSString * _Nonnull url) {
  267. UIImage *thumbnail = [ShareUtility generateThumbnail:ws.image withWidth:120 withHeight:120];
  268. [[ShareAppService sharedAppService] sendImageMessage:conversation
  269. mediaUrl:url
  270. thubnail:thumbnail
  271. success:^(NSDictionary * _Nonnull dict) {
  272. [ws showSuccess];
  273. } error:^(NSString * _Nonnull message) {
  274. [ws showFailure];
  275. }];
  276. } error:^(NSString * _Nonnull errorMsg) {
  277. [ws showFailure];
  278. }];
  279. }
  280. }];
  281. UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
  282. }];
  283. [alertController addAction:cancel];
  284. [alertController addAction:action];
  285. [self presentViewController:alertController animated:YES completion:nil];
  286. }
  287. - (void)showImageLimit {
  288. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"不支持发送多张图片" message:@"每次只能发送一张。如果您需要一次发送多张,请打开野火IM选择图片发送。" preferredStyle:UIAlertControllerStyleAlert];
  289. UIAlertAction *action = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
  290. }];
  291. [alertController addAction:action];
  292. [self presentViewController:alertController animated:YES completion:nil];
  293. }
  294. - (void)showProgress:(int)sent total:(int)total {
  295. NSLog(@"progress %d %d", sent, total);
  296. __weak typeof(self)ws = self;
  297. dispatch_async(dispatch_get_main_queue(), ^{
  298. [MBProgressHUD HUDForView:ws.view].progress = (float)sent/total;
  299. });
  300. }
  301. - (void)showSuccess {
  302. [MBProgressHUD hideHUDForView:self.view animated:YES];
  303. __weak typeof(self)ws = self;
  304. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"已发送" message:@"您可以在野火IM中查看" preferredStyle:UIAlertControllerStyleAlert];
  305. UIAlertAction *action = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
  306. [ws.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
  307. }];
  308. [alertController addAction:action];
  309. [self presentViewController:alertController animated:YES completion:nil];
  310. }
  311. - (void)showFailure {
  312. __weak typeof(self)ws = self;
  313. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"网络错误" message:@"糟糕!网络出问题了!" preferredStyle:UIAlertControllerStyleAlert];
  314. UIAlertAction *action = [UIAlertAction actionWithTitle:@"算了吧" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
  315. [ws.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
  316. }];
  317. [alertController addAction:action];
  318. [self presentViewController:alertController animated:YES completion:nil];
  319. }
  320. #pragma mark - UITableViewDataSource
  321. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  322. if (!self.dataLoaded) {
  323. return 0;
  324. }
  325. return 2;
  326. }
  327. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  328. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
  329. if (!cell) {
  330. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
  331. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  332. }
  333. if (indexPath.row == 0) {
  334. cell.textLabel.text = @"发给朋友";
  335. } else if(indexPath.row == 1) {
  336. cell.textLabel.text = @"发给自己";
  337. } else {
  338. cell.textLabel.text = @"分享到朋友圈";
  339. }
  340. return cell;
  341. }
  342. #pragma mark - UITableViewDelegate
  343. -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  344. NSLog(@"did select row %ld", indexPath.row);
  345. if (indexPath.row == 0) {
  346. ConversationListViewController *vc = [[ConversationListViewController alloc] init];
  347. vc.url = self.url;
  348. vc.urlThumbnail = self.urlThumbnail;
  349. vc.urlTitle = self.urlTitle;
  350. vc.textMessageContent = self.textMessageContent;
  351. vc.imageUrls = self.imageUrls;
  352. vc.fullImage = self.fullImage;
  353. vc.fileUrl = self.fileUrl;
  354. vc.image = self.image;
  355. [self.navigationController pushViewController:vc animated:YES];
  356. } else if(indexPath.row == 1) {
  357. SharedConversation *conversation = [[SharedConversation alloc] init];
  358. conversation.type = 0;//Single_Type;
  359. conversation.target = FILE_TRANSFER_ID;
  360. conversation.line = 0;
  361. conversation.title = @"自己";
  362. [self sendTo:conversation];
  363. }
  364. }
  365. @end