123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- /**
- * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
- #import <MobileCoreServices/MobileCoreServices.h>
- #import "ShareItemController.h"
- #import "NextcloudTalk-Swift.h"
- //TODO: Should the quality be user-selectable?
- CGFloat const kShareItemControllerImageQuality = 0.7f;
- @interface ShareItemController ()
- @property (nonatomic, strong) NSString *tempDirectoryPath;
- @property (nonatomic, strong) NSURL *tempDirectoryURL;
- @property (nonatomic, strong) NSMutableArray *internalShareItems;
- @end
- @implementation ShareItemController
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- self.internalShareItems = [[NSMutableArray alloc] init];
- [self initTempDirectory];
- }
- return self;
- }
- - (NSArray<ShareItem *> *)shareItems {
- return [self.internalShareItems copy];
- }
- - (void)initTempDirectory
- {
- NSFileManager *fileManager = [NSFileManager defaultManager];
- self.tempDirectoryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"/upload/"];
-
- if (![fileManager fileExistsAtPath:self.tempDirectoryPath]) {
- // Make sure our upload directory exists
- [fileManager createDirectoryAtPath:self.tempDirectoryPath withIntermediateDirectories:YES attributes:nil error:nil];
- } else {
- // Clean up any temporary files from a previous upload
- NSArray *previousFiles = [fileManager contentsOfDirectoryAtPath:self.tempDirectoryPath error:nil];
-
- for (NSString *previousFile in previousFiles) {
- [fileManager removeItemAtPath:[self.tempDirectoryPath stringByAppendingPathComponent:previousFile] error:nil];
- }
- }
-
- self.tempDirectoryURL = [NSURL fileURLWithPath:self.tempDirectoryPath isDirectory:YES];
- }
- - (NSURL *)getFileLocalURL:(NSString *)fileName
- {
- NSURL *fileLocalURL = [self.tempDirectoryURL URLByAppendingPathComponent:fileName];
-
- if ([NSFileManager.defaultManager fileExistsAtPath:fileLocalURL.path]) {
- NSString *extension = [fileName pathExtension];
- NSString *nameWithoutExtension = [fileName stringByDeletingPathExtension];
-
- NSString *newFileName = [NSString stringWithFormat:@"%@%.f.%@", nameWithoutExtension, [[NSDate date] timeIntervalSince1970] * 1000, extension];
- fileLocalURL = [self.tempDirectoryURL URLByAppendingPathComponent:newFileName];
- }
-
- return fileLocalURL;
- }
- - (void)addItemWithURL:(NSURL *)fileURL
- {
- [self addItemWithURLAndName:fileURL withName:fileURL.lastPathComponent];
- }
- - (BOOL)prepareFileForUploadingAtURL:(NSURL *)fileURL toLocalURL:(NSURL *)fileLocalURL withCoordinatorOption:(NSFileCoordinatorReadingOptions)options
- {
- NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
- __block NSError *error;
- // Make a local copy to prevent bug where file is removed after some time from inbox
- // See: https://stackoverflow.com/a/48007752/2512312
- [coordinator coordinateReadingItemAtURL:fileURL options:options error:&error byAccessor:^(NSURL *newURL) {
- if ([NSFileManager.defaultManager fileExistsAtPath:fileLocalURL.path]) {
- [NSFileManager.defaultManager removeItemAtPath:fileLocalURL.path error:nil];
- }
- [NSFileManager.defaultManager moveItemAtPath:newURL.path toPath:fileLocalURL.path error:nil];
- }];
- BOOL success = (error == nil);
- return success;
- }
- - (void)addItemWithURLAndName:(NSURL *)fileURL withName:(NSString *)fileName
- {
- NSURL *fileLocalURL = [self getFileLocalURL:fileName];
- // First try to prepare the file with NSFileCoordinatorReadingForUploading
- BOOL preparedSuccessfully = [self prepareFileForUploadingAtURL:fileURL toLocalURL:fileLocalURL withCoordinatorOption:NSFileCoordinatorReadingForUploading];
- if (!preparedSuccessfully) {
- // We failed to prepare the file with NSFileCoordinatorReadingForUploading, use NSFileCoordinatorReadingWithoutChanges as a fallback
- preparedSuccessfully = [self prepareFileForUploadingAtURL:fileURL toLocalURL:fileLocalURL withCoordinatorOption:NSFileCoordinatorReadingWithoutChanges];
- if (!preparedSuccessfully) {
- NSLog(@"Failed to prepare file for sharing");
- return;
- }
- }
- NSLog(@"Adding shareItem: %@ %@", fileName, fileLocalURL);
-
- // Try to determine if the item is an image file
- // This can happen when sharing an image from the native ios files app
- NSString *extension = fileLocalURL.pathExtension;
- BOOL fileIsImage = (extension && [NCUtils isImageWithFileExtension:extension]);
-
- ShareItem* item = [ShareItem initWithURL:fileLocalURL withName:fileName withPlaceholderImage:[self getPlaceholderImageForFileURL:fileLocalURL] isImage:fileIsImage];
- [self.internalShareItems addObject:item];
- [self.delegate shareItemControllerItemsChanged:self];
- }
- - (void)addItemWithImage:(UIImage *)image
- {
- NSString *imageName = [NSString stringWithFormat:@"IMG_%.f.jpg", [[NSDate date] timeIntervalSince1970] * 1000];
- [self addItemWithImageAndName:image withName:imageName];
- }
- - (void)addItemWithImageAndName:(UIImage *)image withName:(NSString *)imageName
- {
- NSURL *fileLocalURL = [self getFileLocalURL:imageName];
- NSData *jpegData = UIImageJPEGRepresentation(image, kShareItemControllerImageQuality);
-
- [jpegData writeToFile:fileLocalURL.path atomically:YES];
-
- NSLog(@"Adding shareItem with image: %@ %@", imageName, fileLocalURL);
-
- ShareItem* item = [ShareItem initWithURL:fileLocalURL withName:imageName withPlaceholderImage:[self getPlaceholderImageForFileURL:fileLocalURL] isImage:YES];
- [self.internalShareItems addObject:item];
- [self.delegate shareItemControllerItemsChanged:self];
- }
- - (UIImage *)getImageFromItem:(ShareItem *)item
- {
- if (!item || !item.fileURL) {
- return nil;
- }
-
- return [UIImage imageWithContentsOfFile:item.filePath];
- }
- - (void)addItemWithContactData:(NSData *)data
- {
- NSString *vCardFileName = [NSString stringWithFormat:@"Contact_%.f.vcf", [[NSDate date] timeIntervalSince1970] * 1000];
- [self addItemWithContactDataAndName:data withName:vCardFileName];
- }
- - (void)addItemWithContactDataAndName:(NSData *)data withName:(NSString *)vCardFileName
- {
- NSURL *fileLocalURL = [self getFileLocalURL:vCardFileName];
- NSString* vcString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-
- [vcString writeToFile:fileLocalURL.path atomically:YES encoding:NSUTF8StringEncoding error:nil];
-
- NSLog(@"Adding shareItem with contact: %@ %@", vCardFileName, fileLocalURL);
-
- ShareItem* item = [ShareItem initWithURL:fileLocalURL withName:vCardFileName withPlaceholderImage:[self getPlaceholderImageForFileURL:fileLocalURL] isImage:YES];
- [self.internalShareItems addObject:item];
- [self.delegate shareItemControllerItemsChanged:self];
- }
- - (void)updateItem:(ShareItem *)item withURL:(NSURL *)fileURL
- {
- // This is called when an item was edited in quicklook and we want to use the edited image
- NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
- __block NSError *error;
-
- [coordinator coordinateReadingItemAtURL:fileURL options:NSFileCoordinatorReadingForUploading error:&error byAccessor:^(NSURL *newURL) {
- if ([NSFileManager.defaultManager fileExistsAtPath:item.filePath]) {
- [NSFileManager.defaultManager removeItemAtPath:item.filePath error:nil];
- }
-
- [NSFileManager.defaultManager moveItemAtPath:newURL.path toPath:item.filePath error:nil];
- }];
-
- NSLog(@"Updating shareItem: %@ %@", item.fileName, item.fileURL);
-
- [self.delegate shareItemControllerItemsChanged:self];
- }
- - (void)updateItem:(ShareItem *)item withImage:(UIImage *)image
- {
- NSData *jpegData = UIImageJPEGRepresentation(image, kShareItemControllerImageQuality);
- [jpegData writeToFile:item.filePath atomically:YES];
-
- NSLog(@"Updating shareItem with Image: %@ %@", item.fileName, item.fileURL);
-
- [self.delegate shareItemControllerItemsChanged:self];
- }
- - (void)removeItem:(ShareItem *)item
- {
- [self removeItems:@[item]];
- }
- - (void)removeItems:(NSArray<ShareItem *> *)items
- {
- for (ShareItem *item in items) {
- [self cleanupItem:item];
- NSLog(@"Removing shareItem: %@ %@", item.fileName, item.fileURL);
- [self.internalShareItems removeObject:item];
- }
- [self.delegate shareItemControllerItemsChanged:self];
- }
- - (void)cleanupItem:(ShareItem *)item
- {
- if ([NSFileManager.defaultManager fileExistsAtPath:item.filePath]) {
- [NSFileManager.defaultManager removeItemAtPath:item.filePath error:nil];
- }
- }
- - (void)removeAllItems
- {
- for (ShareItem *item in self.internalShareItems) {
- [self cleanupItem:item];
- }
-
- [self.internalShareItems removeAllObjects];
- }
- - (UIImage *)getPlaceholderImageForFileURL:(NSURL *)fileURL
- {
- NSString *previewImage = [NCUtils previewImageForFileExtension:[fileURL pathExtension]];
- return [UIImage imageNamed:previewImage];
- }
- @end
|