rework storage and display files

This commit is contained in:
Danmei Chen 2021-02-25 09:36:14 +01:00
parent 8164a2d944
commit f5b683e9d7
8 changed files with 352 additions and 641 deletions

View file

@ -27,8 +27,8 @@
@protocol ChatConversationDelegate <NSObject>
- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality;
- (BOOL)startFileUpload:(NSData *)data assetId:(NSString *)phAssetId;
- (BOOL)resendFile:(NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message;
- (BOOL)startImageUpload:(UIImage *)image withQuality:(float)quality andMessage:(NSString *)message;
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name;
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url;
- (void)tableViewIsScrolling;

View file

@ -363,9 +363,9 @@ static const CGFloat MESSAGE_SPACING_PERCENTAGE = 1.f;
- (void)removeSelectionUsing:(void (^)(NSIndexPath *))remover {
[super removeSelectionUsing:^(NSIndexPath *indexPath) {
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
// TODO: fix workaround
//linphone_event_log_delete_from_database(event);
linphone_chat_room_delete_message(_chatRoom, linphone_event_log_get_chat_message(event));
if (linphone_event_log_get_chat_message(event)) {
linphone_chat_room_delete_message(_chatRoom, linphone_event_log_get_chat_message(event));
}
NSInteger index = indexPath.row + _currentIndex + (totalEventList.count - eventList.count);
if (index < totalEventList.count)
[totalEventList removeObjectAtIndex:index];

View file

@ -92,6 +92,10 @@
+ (void)markAsRead:(LinphoneChatRoom *)chatRoom;
+ (void)autoDownload:(LinphoneChatMessage *)message;
+(NSString *)getKeyFromFileType:(NSString *)fileType fileName:(NSString *)name;
+ (NSURL *)getCacheFileUrl:(NSString *)name;
+ (void)writeFileInCache:(NSData *)data name:(NSString *)name;
+ (NSData *)getCacheFileData:(NSString *)name;
- (void)configureForRoom:(BOOL)editing;
- (IBAction)onBackClick:(id)event;

View file

@ -337,33 +337,17 @@ static UICompositeViewDescription *compositeDescription = nil;
//file shared from photo lib
NSString *fileName = dict[@"url"];
[_messageField setText:dict[@"message"]];
NSString *key = [[fileName componentsSeparatedByString:@"."] firstObject];
NSMutableDictionary <NSString *, PHAsset *> * assetDict = [LinphoneUtils photoAssetsDictionary];
PHAsset *phasset = [assetDict objectForKey:key];
if (!phasset) {
// for the images or videos not really in the photo album
[self confirmShare:[self nsDataRead] url:nil fileName:fileName assetId:nil];
} else if ([fileName hasSuffix:@"JPG"] || [fileName hasSuffix:@"PNG"] || [fileName hasSuffix:@"jpg"] || [fileName hasSuffix:@"png"]) {
UIImage *image = [[UIImage alloc] initWithData:[self nsDataRead]];
[self chooseImageQuality:image assetId:[phasset localIdentifier]];
} else if ([fileName hasSuffix:@"MOV"] || [fileName hasSuffix:@"mov"]) {
[self confirmShare:[self nsDataRead] url:nil fileName:nil assetId:[phasset localIdentifier]];
} else {
LOGE(@"Unable to parse file %@",fileName);
}
[self confirmShare:[self nsDataRead] url:nil fileName:fileName];
[defaults removeObjectForKey:@"photoData"];
} else if (dictFile) {
NSString *fileName = dictFile[@"url"];
[_messageField setText:dictFile[@"message"]];
[self confirmShare:[self nsDataRead] url:nil fileName:fileName assetId:nil];
[self confirmShare:[self nsDataRead] url:nil fileName:fileName];
[defaults removeObjectForKey:@"icloudData"];
} else if (dictUrl) {
NSString *url = dictUrl[@"url"];
[_messageField setText:dictUrl[@"message"]];
[self confirmShare:nil url:url fileName:nil assetId:nil];
[self confirmShare:nil url:url fileName:nil];
[defaults removeObjectForKey:@"url"];
}
}
@ -417,7 +401,7 @@ static UICompositeViewDescription *compositeDescription = nil;
}
}
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL *)externalUrl withInternalURL:(NSURL *)internalUrl {
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL *)externalUrl {
if (_chatRoom == NULL) {
LOGW(@"Cannot send message: No chatroom");
return FALSE;
@ -428,11 +412,6 @@ static UICompositeViewDescription *compositeDescription = nil;
linphone_chat_message_set_external_body_url(msg, [[externalUrl absoluteString] UTF8String]);
}
if (internalUrl) {
// internal url is saved in the appdata for display and later save
[LinphoneManager setValueInMessageAppData:[internalUrl absoluteString] forKey:@"localimage" inMessage:msg];
}
// we must ref & unref message because in case of error, it will be destroy otherwise
linphone_chat_message_send(msg);
@ -474,7 +453,7 @@ static UICompositeViewDescription *compositeDescription = nil;
});
}
- (void)confirmShare:(NSData *)data url:(NSString *)url fileName:(NSString *)fileName assetId:(NSString *)phAssetId {
- (void)confirmShare:(NSData *)data url:(NSString *)url fileName:(NSString *)fileName {
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:@""];
dispatch_async(dispatch_get_main_queue(), ^{
[sheet addButtonWithTitle:NSLocalizedString(@"Send to this friend", nil)
@ -483,11 +462,10 @@ static UICompositeViewDescription *compositeDescription = nil;
[self sendMessageInMessageField];
}
if (url)
[self sendMessage:url withExterlBodyUrl:nil withInternalURL:nil];
else if (fileName)
[self startFileUpload:data withName:fileName];
[self sendMessage:url withExterlBodyUrl:nil];
else
[self startFileUpload:data assetId:phAssetId];}];
[self startFileUpload:data withName:fileName];
}];
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
[sheet showInView:PhoneMainView.instance.view];
@ -568,7 +546,7 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (void)sendMessageInMessageField {
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil withInternalURL:nil]) {
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil]) {
scrollOnGrowingEnabled = FALSE;
[_messageField setText:@""];
scrollOnGrowingEnabled = TRUE;
@ -651,15 +629,15 @@ static UICompositeViewDescription *compositeDescription = nil;
if ([_imagesArray count] > 0) {
int i = 0;
for (i = 0; i < [_imagesArray count] - 1; ++i) {
[self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue];
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:NULL];
}
if (isOneToOne) {
[self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue];
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:NULL];
if (![[self.messageField text] isEqualToString:@""]) {
[self sendMessage:[_messageField text] withExterlBodyUrl:nil withInternalURL:nil];
[self sendMessage:[_messageField text] withExterlBodyUrl:nil];
}
} else {
[self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:[self.messageField text]];
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:[self.messageField text]];
}
[self clearMessageView];
@ -761,28 +739,15 @@ static UICompositeViewDescription *compositeDescription = nil;
#pragma mark ChatRoomDelegate
- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality {
- (BOOL)startImageUpload:(UIImage *)image withQuality:(float)quality andMessage:(NSString *)message {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer upload:image withassetId:phAssetId forChatRoom:_chatRoom withQuality:quality];
if (message)
[fileTransfer setText:message];
[fileTransfer uploadImage:image forChatRoom:_chatRoom withQuality:quality];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality andMessage:(NSString *)message {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer setText:message];
[fileTransfer upload:image withassetId:phAssetId forChatRoom:_chatRoom withQuality:quality];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)startFileUpload:(NSData *)data assetId:(NSString *)phAssetId {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer uploadVideo:data withassetId:phAssetId forChatRoom:_chatRoom];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer uploadFile:data forChatRoom:_chatRoom withName:name];
@ -790,8 +755,17 @@ static UICompositeViewDescription *compositeDescription = nil;
return TRUE;
}
- (BOOL)resendFile: (NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
if (message)
[fileTransfer setText:message];
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key];
[_tableController scrollToBottom:true];
return TRUE;
}
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url {
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url] withInternalURL:nil];
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url]];
}
#pragma mark ImagePickerDelegate
@ -1179,6 +1153,23 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
[PhoneMainView.instance fullScreen:NO];
}
+ (NSData *)getCacheFileData: (NSString *)name {
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
return [NSData dataWithContentsOfFile:filePath];
}
+ (NSURL *)getCacheFileUrl: (NSString *)name {
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
return [NSURL fileURLWithPath:filePath];
}
+ (void)writeFileInCache:(NSData *)data name:(NSString *)name {
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
[[NSFileManager defaultManager] createFileAtPath:filePath
contents:data
attributes:nil];
}
- (NSURL *)getICloudFileUrl:(NSString *)name {
if (@available(iOS 11.0, *)) {
return [NSURL fileURLWithPath:[LinphoneManager documentFile:name]];
@ -1324,118 +1315,25 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
}
+ (NSString *)getKeyFromFileType:(NSString *)fileType fileName:(NSString *)name{
if ([fileType isEqualToString:@"video"]) {
return @"localvideo";
} else if ([fileType isEqualToString:@"image"] || [name hasSuffix:@"JPG"] || [name hasSuffix:@"PNG"] || [name hasSuffix:@"jpg"] || [name hasSuffix:@"png"]) {
return @"localimage";
}
return @"localfile";
}
+ (void)autoDownload:(LinphoneChatMessage *)message {
ChatConversationView *view = VIEW(ChatConversationView);
//TODO: migrate with "linphone_iphone_file_transfer_recv"
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(message);
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
// get download path
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filePath]) {
NSData* data = [NSData dataWithContentsOfFile:filePath];
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(message);
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name];
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
void (^block)(void)= ^ {
if ([fileType isEqualToString:@"image"]) {
// we're finished, save the image and update the message
UIImage *image = [UIImage imageWithData:data];
if (!image) {
[view showFileDownloadError];
return;
}
__block NSString *createdAssetId = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
createdAssetId = [PHAssetCreationRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset.localIdentifier;
} error:nil];
if (createdAssetId != nil) {
LOGI(@"Image saved to [%@]", createdAssetId);
[LinphoneManager setValueInMessageAppData:createdAssetId
forKey:@"localimage"
inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];
});
} else {
LOGE(@"Cannot save image data downloaded");
[LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
message:NSLocalizedString(@"Cannot write image to photo library",
nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
});
}
} else if ([fileType isEqualToString:@"video"]) {
// until image is properly saved, keep a reminder on it so that the
// chat bubble is aware of the fact that image is being saved to device
__block NSString *createdAssetId = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
createdAssetId = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]].placeholderForCreatedAsset.localIdentifier;
} error:nil];
if (createdAssetId != nil) {
LOGI(@"video saved to [%@]", createdAssetId);
[LinphoneManager setValueInMessageAppData:createdAssetId
forKey:@"localvideo"
inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];
});
} else {
LOGE(@"Cannot save video data downloaded");
[LinphoneManager setValueInMessageAppData:nil forKey:@"localvideo" inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
message:NSLocalizedString(@"Cannot write video to photo library",
nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
});
}
}
};
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
if ([fileType isEqualToString:@"image"] || [fileType isEqualToString:@"video"]) {
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
block();
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
block();
} else {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
}
});
}];
}
} else {
NSString *key = @"localfile";
//write file to path
if([view writeFileInICloud:data fileURL:[view getICloudFileUrl:name]]) {
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];});
} else {
LOGE(@"[Auto download error] can not save the file %@", name);
}
}
}
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];});
}
-(void) documentMenu:(UIDocumentMenuViewController *)documentMenu didPickDocumentPicker:(UIDocumentPickerViewController *)documentPicker {

View file

@ -154,172 +154,105 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
LOGW(@"Cannot update message room cell: NULL message");
return;
}
[super update];
[super update];
const char *url = linphone_chat_message_get_external_body_url(self.message);
BOOL is_external =
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(self.message);
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message];
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
assert(is_external || localImage || localVideo || localFile);
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(self.message);
NSString *type = fileContent ? [NSString stringWithUTF8String:linphone_content_get_type(fileContent)] : @"";
if (!(localImage || localVideo || localFile)) {
// If the file has been downloaded in background, save it in the folders and display it.
ChatConversationView *view = VIEW(ChatConversationView);
//TODO: migrate with "linphone_iphone_file_transfer_recv"
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(self.message);
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
// get download path
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filePath]) {
NSData* data = [NSData dataWithContentsOfFile:filePath];
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
void (^block)(void)= ^ {
if ([fileType isEqualToString:@"image"]) {
// we're finished, save the image and update the message
UIImage *image = [UIImage imageWithData:data];
if (!image) {
[view showFileDownloadError];
return;
}
__block PHObjectPlaceholder *placeHolder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
placeHolder = [request placeholderForCreatedAsset];
} completionHandler:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
[LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:self.message];
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
message:NSLocalizedString(@"Cannot write image to photo library",
nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
} else {
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
forKey:@"localimage"
inMessage:self.message];
[self updateButtons:[LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message] localVideo:localVideo localFile:localFile];
}
});
}];
} else if([fileType isEqualToString:@"video"]) {
// until image is properly saved, keep a reminder on it so that the
// chat bubble is aware of the fact that image is being saved to device
__block PHObjectPlaceholder *placeHolder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
placeHolder = [request placeholderForCreatedAsset];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
[LinphoneManager setValueInMessageAppData:nil forKey:@"localvideo" inMessage:self.message];
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
message:NSLocalizedString(@"Cannot write video to photo library",
nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
} else {
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
forKey:@"localvideo"
inMessage:self.message];
[self updateButtons:localImage localVideo:[LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message] localFile:localFile];
}
});
}];
}
};
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
if ([fileType isEqualToString:@"image"] || [fileType isEqualToString:@"video"]) {
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
block();
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
block();
} else {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
}
});
}];
}
} else {
NSString *key = @"localfile";
//write file to path
if([view writeFileInICloud:data fileURL:[view getICloudFileUrl:name]]) {
dispatch_async(dispatch_get_main_queue(), ^{
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:self.message];
[self updateButtons:localImage localVideo:localVideo localFile:[LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message]];
});
} else {
LOGE(@"[Auto download error] can not save the file %@", name);
}
}
}
}
[self updateButtons:localImage localVideo:localVideo localFile:localFile];
}
- (void)updateButtons: (NSString *)localImage localVideo:(NSString *)localVideo localFile:(NSString *)localFile {
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(self.message);
NSString *type = fileContent ? [NSString stringWithUTF8String:linphone_content_get_type(fileContent)] : nil;
if (!(localImage || localVideo || localFile)) {
_playButton.hidden = YES;
_fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
_messageImageView.hidden = _cancelButton.hidden = (_ftd.message == nil);
_downloadButton.hidden = !_cancelButton.hidden;
_fileTransferProgress.hidden = NO;
} else {
// file is being saved on device - just wait for it
if ([localImage isEqualToString:@"saving..."] || [localVideo isEqualToString:@"saving..."] || [localFile isEqualToString:@"saving..."]) {
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
_playButton.hidden = YES;
_fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
_messageImageView.hidden = _cancelButton.hidden = (_ftd.message == nil);
_downloadButton.hidden = !_cancelButton.hidden;
_fileTransferProgress.hidden = NO;
} else {
// file is being saved on device - just wait for it
if ([localImage isEqualToString:@"saving..."] || [localVideo isEqualToString:@"saving..."] || [localFile isEqualToString:@"saving..."]) {
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
} else {
if(!assetIsLoaded) {
assetIsLoaded = TRUE;
if (localImage) {
// we did not load the image yet, so start doing so
if (_messageImageView.image == nil) {
[self loadFirstImage:localImage type:PHAssetMediaTypeImage];
_imageGestureRecognizer.enabled = YES;
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localImage];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSData* data = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [[UIImage alloc] initWithData:data];
[self loadImageAsset:nil image:image];
_imageGestureRecognizer.enabled = YES;
} else {
// support previous versions
[self loadFirstImage:localImage type:PHAssetMediaTypeImage];
_imageGestureRecognizer.enabled = YES;
dispatch_async(dispatch_get_main_queue(), ^ {
UIImage *image = [chatTableView.imagesInChatroom objectForKey:localImage];
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
NSData *data = UIImageJPEGRepresentation(image, 1);
[ChatConversationView writeFileInCache:data name:name];
[LinphoneManager setValueInMessageAppData:name forKey:@"localimage" inMessage:self.message];
});
}
}
}
else if (localVideo) {
} else if (localVideo) {
if (_messageImageView.image == nil) {
[self loadFirstImage:localVideo type:PHAssetMediaTypeVideo];
_imageGestureRecognizer.enabled = NO;
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localVideo];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:localVideo]];
[self loadImageAsset:nil image:image];
_imageGestureRecognizer.enabled = NO;
} else {
// support previous versions
[self loadFirstImage:localVideo type:PHAssetMediaTypeVideo];
_imageGestureRecognizer.enabled = NO;
dispatch_async(dispatch_get_main_queue(), ^ {
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
if (![assets firstObject])
return;
PHAsset *asset = [assets firstObject];
if (asset.mediaType != PHAssetMediaTypeVideo)
return;
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.version = PHImageRequestOptionsVersionCurrent;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
AVURLAsset *urlAsset = (AVURLAsset *)asset;
NSData *data = [NSData dataWithContentsOfURL:urlAsset.URL];
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
[ChatConversationView writeFileInCache:data name:name];
[LinphoneManager setValueInMessageAppData:name forKey:@"localvideo" inMessage:self.message];
}];
});
}
}
} else if (localFile) {
BOOL newVersion = FALSE;
if(![[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile]]) {
dispatch_async(dispatch_get_main_queue(), ^ {
NSURL *url = [VIEW(ChatConversationView) getICloudFileUrl:localFile];
NSData *data = [NSData dataWithContentsOfURL:url];
[ChatConversationView writeFileInCache:data name:localFile];
});
} else {
newVersion = TRUE;
}
}
else if (localFile) {
if ([type isEqualToString:@"video"]) {
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:newVersion? [ChatConversationView getCacheFileUrl:localFile] : [VIEW(ChatConversationView) getICloudFileUrl:localFile]];
[self loadImageAsset:nil image:image];
_imageGestureRecognizer.enabled = NO;
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
NSData *data = newVersion? [ChatConversationView getCacheFileData:localFile] : [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
UIImage *image = [[UIImage alloc] initWithData:data];
[self loadImageAsset:nil image:image];
_imageGestureRecognizer.enabled = YES;
@ -342,7 +275,7 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
_playButton.hidden = ![type isEqualToString:@"video"];
_fileName.hidden = _fileView.hidden = _fileButton.hidden = localFile ? NO : YES;
}
}
}
}
- (void)loadFirstImage:(NSString *)key type:(PHAssetMediaType)type {
@ -391,11 +324,29 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
}
- (IBAction)onPlayClick:(id)sender {
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
if (localVideo && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localVideo]]) {
AVPlayer *player = [AVPlayer playerWithURL:[ChatConversationView getCacheFileUrl:localVideo]];
[self playVideoByPlayer:player];
return;
} else if (localFile && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile]]) {
AVPlayer *player = [AVPlayer playerWithURL:[ChatConversationView getCacheFileUrl:localFile]];
[self playVideoByPlayer:player];
return;
}
PHAsset *asset = [_messageImageView asset];
if (!asset) {
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
AVPlayer *player = [AVPlayer playerWithURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
NSURL *url = [VIEW(ChatConversationView) getICloudFileUrl:localFile];
AVPlayer *player = [AVPlayer playerWithURL:url];
[self playVideoByPlayer:player];
dispatch_async(dispatch_get_main_queue(), ^ {
NSData *data = [NSData dataWithContentsOfURL:url];
[ChatConversationView writeFileInCache:data name:localFile];
});
return;
}
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
@ -413,7 +364,11 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
- (IBAction)onFileClick:(id)sender {
ChatConversationView *view = VIEW(ChatConversationView);
NSString *name = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
[view openFileWithURL:[view getICloudFileUrl:name]];
if([[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name]]) {
[view openFileWithURL:[ChatConversationView getCacheFileUrl:name]];
} else {
[view openFileWithURL:[view getICloudFileUrl:name]];
}
}
@ -441,22 +396,38 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
- (IBAction)onImageClick:(id)event {
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
if (state == LinphoneChatMessageStateNotDelivered) {
FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:self.message];
if (thiz) {
[thiz stopAndDestroy];
}
[self onResendClick:event];
} else {
if (![_messageImageView isLoading]) {
ImageView *view = VIEW(ImageView);
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
NSString *imageName = NULL;
if (localImage && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localImage]]) {
imageName = localImage;
} else if (localFile && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile]]) {
if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
imageName = localFile;
}
}
if (imageName) {
NSData *data = [NSData dataWithContentsOfFile:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:imageName]];
UIImage *image = [[UIImage alloc] initWithData:data];
if (image)
[view setImage:image];
else
LOGE(@"Can't read image");
return;
}
PHAsset *asset = [_messageImageView asset];
if (!asset) {
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
UIImage *image = [[UIImage alloc] initWithData:data];
if (image)
[view setImage:image];
else
LOGE(@"Can't read image");
}
return;
}
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];

View file

@ -276,74 +276,33 @@
if (linphone_chat_message_get_file_transfer_information(_message) != NULL) {
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:_message];
NSNumber *uploadQuality =[LinphoneManager getMessageAppDataForKey:@"uploadQuality" inMessage:_message];
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:_message];
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:_message];
/*FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:_message];
if (thiz) {
[thiz stop]
}*/
[self onDelete];
if(localImage){
ChatConversationTableView *tableView = VIEW(ChatConversationView).tableController;
UIImage *img = [tableView.imagesInChatroom objectForKey:localImage];
if (img) {
dispatch_async(dispatch_get_main_queue(), ^ {
[_chatRoomDelegate startImageUpload:img assetId:localImage withQuality:(uploadQuality ? [uploadQuality floatValue] : 0.9)];
});
} else {
PHFetchResult<PHAsset *> *assets = [LinphoneManager getPHAssets:localImage];
if (![assets firstObject])
return;
PHAsset *asset = [assets firstObject];
if (asset.mediaType != PHAssetMediaTypeImage)
return;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.synchronous = TRUE;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:options
resultHandler:^(UIImage *image, NSDictionary * info) {
if (image) {
dispatch_async(dispatch_get_main_queue(),
^(void) {
[_chatRoomDelegate startImageUpload:img assetId:localImage withQuality:(uploadQuality ? [uploadQuality floatValue] : 0.9)];
});
} else {
LOGE(@"Can't read image");
}
}];
}
} else if (localVideo) {
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
if (![assets firstObject])
return;
PHAsset *asset = [assets firstObject];
if (asset.mediaType != PHAssetMediaTypeVideo)
return;
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.version = PHImageRequestOptionsVersionCurrent;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
AVURLAsset *urlAsset = (AVURLAsset *)asset;
NSURL *url = urlAsset.URL;
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(),
^(void) {
[_chatRoomDelegate startFileUpload:data assetId:localVideo];
});
}];
} else if (localFile) {
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
[_chatRoomDelegate startFileUpload:data withName:localFile];
}
if(localImage){
dispatch_async(dispatch_get_main_queue(), ^ {
[_chatRoomDelegate resendFile:[ChatConversationView getCacheFileData:localImage] withName:localImage type:@"image" key:@"localimage" message:self.textMessage];
});
} else if (localVideo) {
dispatch_async(dispatch_get_main_queue(), ^ {
[_chatRoomDelegate resendFile:[ChatConversationView getCacheFileData:localVideo] withName:localVideo type:@"video" key:@"localvideo" message:self.textMessage];
});
} else if (localFile) {
dispatch_async(dispatch_get_main_queue(), ^ {
[_chatRoomDelegate resendFile:[ChatConversationView getCacheFileData:localFile] withName:localFile type:@"image" key:@"localfile" message:self.textMessage];
});
}
} else {
[self onDelete];
[self onDelete];
double delayInSeconds = 0.4;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[_chatRoomDelegate resendChat:self.textMessage withExternalUrl:nil];
[_chatRoomDelegate resendChat:self.textMessage withExternalUrl:nil];
});
}
}
@ -443,53 +402,74 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
font:messageFont];
size.height += textSize.height;
}
if(localFile) {
UIImage *image = nil;
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(fileContent)];
if ([type isEqualToString:@"video"]) {
image = [self getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
image = [[UIImage alloc] initWithData:data];
}
if (image) {
size = [self getMediaMessageSizefromOriginalSize:image.size withWidth:width];
// add size for message text
size.height += textSize.height;
size.width = MAX(textSize.width, size.width);
} else {
CGSize fileSize = CGSizeMake(230, 50);
size = [self getMediaMessageSizefromOriginalSize:fileSize withWidth:width];
}
} else {
if (!localImage && !localVideo) {
//We are loading the image
return CGSizeMake(CELL_MIN_WIDTH + CELL_MESSAGE_X_MARGIN, CELL_MIN_HEIGHT + CELL_MESSAGE_Y_MARGIN + textSize.height + 20);
}
PHFetchResult<PHAsset *> *assets;
if(localImage)
assets = [LinphoneManager getPHAssets:localImage];
else
assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
if (![assets firstObject]) {
return CGSizeMake(CELL_MIN_WIDTH, CELL_MIN_WIDTH + CELL_MESSAGE_Y_MARGIN + textSize.height);
} else {
PHAsset *asset = [assets firstObject];
CGSize originalImageSize = CGSizeMake([asset pixelWidth], [asset pixelHeight]);
size = [self getMediaMessageSizefromOriginalSize:originalImageSize withWidth:width];
// add size for message text
size.height += textSize.height;
size.width = MAX(textSize.width, size.width);
}
}
}
CGSize originalImageSize = CGSizeMake(230, 50);
if (localFile) {
UIImage *image = nil;
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(fileContent)];
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile];
if ([type isEqualToString:@"video"]) {
if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
image = [self getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:localFile]];
} else {
image = [self getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
}
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
NSData *data = [NSData dataWithContentsOfFile:filePath];
image = [[UIImage alloc] initWithData:data];
} else {
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
image = [[UIImage alloc] initWithData:data];
}
} else {
// other files // todo for text
CGSize fileSize = CGSizeMake(230, 50);
size = [self getMediaMessageSizefromOriginalSize:fileSize withWidth:width];
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
return size;
}
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
return size;
originalImageSize = image.size;
} else {
if (!localImage && !localVideo) {
//We are loading the image
return CGSizeMake(CELL_MIN_WIDTH + CELL_MESSAGE_X_MARGIN, CELL_MIN_HEIGHT + CELL_MESSAGE_Y_MARGIN + textSize.height + 20);
}
if (localImage && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localImage]]) {
NSData* data = [ChatConversationView getCacheFileData:localImage];
UIImage *image = [[UIImage alloc] initWithData:data];
originalImageSize = image.size;
} else if (localVideo && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localVideo]]) {
UIImage *image = [UIChatBubbleTextCell getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:localVideo]];
originalImageSize = image.size;
} else {
// support previous versions
PHFetchResult<PHAsset *> *assets;
if(localImage)
assets = [LinphoneManager getPHAssets:localImage];
else
assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
if (![assets firstObject]) {
return CGSizeMake(CELL_MIN_WIDTH, CELL_MIN_WIDTH + CELL_MESSAGE_Y_MARGIN + textSize.height);
} else {
PHAsset *asset = [assets firstObject];
originalImageSize = CGSizeMake([asset pixelWidth], [asset pixelHeight]);
}
}
}
size = [self getMediaMessageSizefromOriginalSize:originalImageSize withWidth:width];
// add size for message text
size.height += textSize.height;
size.width = MAX(textSize.width, size.width);
}
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
return size;
}
+ (CGSize)ViewSizeForMessage:(LinphoneChatMessage *)chat withWidth:(int)width {

View file

@ -23,12 +23,14 @@
@interface FileTransferDelegate : NSObject
- (void)upload:(UIImage *)image withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality;
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key;
- (void)uploadImage:(UIImage *)image forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality;
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name;
- (void)uploadVideo:(NSData *)data withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom;
- (void)cancel;
- (BOOL)download:(LinphoneChatMessage *)message;
- (void)stopAndDestroy;
+ (FileTransferDelegate *)messageDelegate:(LinphoneChatMessage *)message;
@property() LinphoneChatMessage *message;
@property() NSString *text;

View file

@ -53,160 +53,26 @@ static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, con
}
if (size == 0) {
LOGI(@"Transfer of %s (%d bytes): download finished", linphone_content_get_name(content), size);
NSString *name = [NSString stringWithUTF8String: linphone_content_get_name(content) ? : ""];
LOGI(@"Transfer of %@ (%d bytes): download finished", name, size);
assert([thiz.data length] == linphone_content_get_file_size(content));
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
ChatConversationView *view = VIEW(ChatConversationView);
void (^block)(void)= ^ {
if ([fileType isEqualToString:@"image"]) {
// we're finished, save the image and update the message
UIImage *image = [UIImage imageWithData:thiz.data];
if (!image) {
[view showFileDownloadError];
[thiz stopAndDestroy];
return;
}
CFBridgingRetain(thiz);
[[LinphoneManager.instance fileTransferDelegates] removeObject:thiz];
// until image is properly saved, keep a reminder on it so that the
// chat bubble is aware of the fact that image is being saved to device
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:@"localimage" inMessage:message];
__block PHObjectPlaceholder *placeHolder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
placeHolder = [request placeholderForCreatedAsset];
} completionHandler:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
[LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:message];
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
message:NSLocalizedString(@"Cannot write image to photo library",
nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
} else {
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
forKey:@"localimage"
inMessage:message];
}
[NSNotificationCenter.defaultCenter
postNotificationName:kLinphoneFileTransferRecvUpdate
object:thiz
userInfo:@{
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to
// trigger
// FileTransferDone here
@"image" : image,
@"progress" : @(1.f),
}];
[thiz stopAndDestroy];
CFRelease((__bridge CFTypeRef)thiz);
});
}];
} else if([fileType isEqualToString:@"video"]) {
CFBridgingRetain(thiz);
[[LinphoneManager.instance fileTransferDelegates] removeObject:thiz];
NSString *name =[NSString stringWithUTF8String:linphone_content_get_name(content)];
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
[[NSFileManager defaultManager] createFileAtPath:filePath
contents:thiz.data
attributes:nil];
// until image is properly saved, keep a reminder on it so that the
// chat bubble is aware of the fact that image is being saved to device
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:@"localvideo" inMessage:message];
__block PHObjectPlaceholder *placeHolder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
placeHolder = [request placeholderForCreatedAsset];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
[LinphoneManager setValueInMessageAppData:nil forKey:@"localvideo" inMessage:message];
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
message:NSLocalizedString(@"Cannot write video to photo library",
nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
} else {
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
forKey:@"localvideo"
inMessage:message];
}
[NSNotificationCenter.defaultCenter
postNotificationName:kLinphoneFileTransferRecvUpdate
object:thiz
userInfo:@{
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to
// trigger
// FileTransferDone here
@"progress" : @(1.f),
}];
[thiz stopAndDestroy];
CFRelease((__bridge CFTypeRef)thiz);
});
}];
}
};
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
if ([fileType isEqualToString:@"image"] || [fileType isEqualToString:@"video"]) {
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
block();
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
block();
} else {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
[thiz stopAndDestroy];
}
});
}];
}
} else {
[[LinphoneManager.instance fileTransferDelegates] removeObject:thiz];
NSString *key = @"localfile" ;
NSString *name =[NSString stringWithUTF8String:linphone_content_get_name(content)];
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:key inMessage:message];
//write file to path
dispatch_async(dispatch_get_main_queue(), ^{
if([view writeFileInICloud:thiz.data fileURL:[view getICloudFileUrl:name]]) {
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
[NSNotificationCenter.defaultCenter
postNotificationName:kLinphoneFileTransferRecvUpdate
object:thiz
userInfo:@{
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to trigger
@"progress" : @(1.f), // FileTransferDone here
}];
}
[thiz stopAndDestroy];
});
}
} else {
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name];
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:key inMessage:message];
dispatch_async(dispatch_get_main_queue(), ^{
[ChatConversationView writeFileInCache:thiz.data name:name];
[LinphoneManager setValueInMessageAppData:name
forKey:key
inMessage:message];
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneFileTransferRecvUpdate
object:thiz
userInfo:@{
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to trigger
@"progress" : @(1.f), // FileTransferDone here
}];
});
} else {
LOGD(@"Transfer of %s (%d bytes): already %ld sent, adding %ld", linphone_content_get_name(content),
linphone_content_get_file_size(content), [thiz.data length], size);
[thiz.data appendBytes:linphone_buffer_get_string_content(buffer) length:size];
@ -218,7 +84,6 @@ static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, con
@"progress" : @([thiz.data length] * 1.f / linphone_content_get_file_size(content)),
}];
}
}
static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *message, const LinphoneContent *content,
@ -248,14 +113,18 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
// this is the last time we will be notified, so destroy ourselve
if (remaining <= size) {
LOGI(@"Upload ended");
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(thiz.message), NULL);
thiz.message = NULL;
[thiz stopAndDestroy];
//workaround fix : avoid chatconversationtableview scrolling
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneFileTransferSendUpdate
object:thiz
userInfo:@{@"state" : @(LinphoneChatMessageStateDelivered),
}];
//workaround fix : avoid chatconversationtableview scrolling
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneFileTransferSendUpdate
object:thiz
userInfo:@{@"state" : @(LinphoneChatMessageStateDelivered),
}];
}
return buffer;
} else {
@ -266,65 +135,52 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
return NULL;
}
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key keyData:(NSString *)keyData qualityData:(NSNumber *)qualityData {
[LinphoneManager.instance.fileTransferDelegates addObject:self];
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom));
_data = [NSMutableData dataWithData:data];
linphone_content_set_type(content, [type UTF8String]);
linphone_content_set_subtype(content, [subtype UTF8String]);
linphone_content_set_name(content, [name UTF8String]);
linphone_content_set_size(content, _data.length);
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
BOOL isOneToOneChat = linphone_chat_room_get_capabilities(chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
if (!isOneToOneChat && (_text!=nil && ![_text isEqualToString:@""]))
linphone_chat_message_add_text_content(_message, [_text UTF8String]);
linphone_content_unref(content);
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message),
linphone_iphone_file_transfer_send);
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key{
[LinphoneManager.instance.fileTransferDelegates addObject:self];
// internal url is saved in the appdata for display and later save
[LinphoneManager setValueInMessageAppData:keyData forKey:key inMessage:_message];
[LinphoneManager setValueInMessageAppData:qualityData forKey:@"uploadQuality" inMessage:_message];
LOGI(@"%p Uploading content from message %p", self, _message);
linphone_chat_message_send(_message);
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom));
_data = [NSMutableData dataWithData:data];
linphone_content_set_type(content, [type UTF8String]);
linphone_content_set_subtype(content, [subtype UTF8String]);
linphone_content_set_name(content, [name UTF8String]);
linphone_content_set_size(content, _data.length);
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
BOOL isOneToOneChat = linphone_chat_room_get_capabilities(chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
if (!isOneToOneChat && (_text!=nil && ![_text isEqualToString:@""]))
linphone_chat_message_add_text_content(_message, [_text UTF8String]);
linphone_content_unref(content);
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message), linphone_iphone_file_transfer_send);
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:_message];
LOGI(@"%p Uploading content from message %p", self, _message);
linphone_chat_message_send(_message);
}
- (void)upload:(UIImage *)image withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality {
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
if (phAssetId)
[self uploadData:UIImageJPEGRepresentation(image, quality) forChatRoom:chatRoom type:@"image" subtype:@"jpeg" name:name key:@"localimage" keyData:phAssetId qualityData:[NSNumber numberWithFloat:quality]];
else
[self uploadData:UIImageJPEGRepresentation(image, quality) forChatRoom:chatRoom type:@"image" subtype:@"jpeg" name:name key:@"localimage" keyData:nil qualityData:nil];
- (void)uploadImage:(UIImage *)image forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality {
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
NSData *data = UIImageJPEGRepresentation(image, quality);
[ChatConversationView writeFileInCache:data name:name];
[self uploadData:data forChatRoom:chatRoom type:@"image" subtype:@"jpg" name:name key:@"localimage"];
}
- (void)uploadVideo:(NSData *)data withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom {
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
if (phAssetId)
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:nil name:name key:@"localvideo" keyData:phAssetId qualityData:nil];
else
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:nil name:name key:@"localvideo" keyData:@"ending..." qualityData:nil];
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
[ChatConversationView writeFileInCache:data name:name];
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:@"mov" name:name key:@"localvideo"];
}
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name {
// we will write local files into ours folder of icloud
ChatConversationView *view = VIEW(ChatConversationView);
NSURL *url = [view getICloudFileUrl:name];
if ([view writeFileInICloud:data fileURL:url]) {
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
if ([[asset tracksWithMediaType:AVMediaTypeVideo] count] > 0) {
// if it's a video
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:nil name:name key:@"localfile" keyData:name qualityData:nil];
} else {
[self uploadData:data forChatRoom:chatRoom type:@"file" subtype:nil name:name key:@"localfile" keyData:name qualityData:nil];
}
}
[ChatConversationView writeFileInCache:data name:name];
NSURL *url = [ChatConversationView getCacheFileUrl:name];
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
NSString *fileType = [[asset tracksWithMediaType:AVMediaTypeVideo] count] > 0 ? @"video" : @"file";
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name];
[self uploadData:data forChatRoom:chatRoom type:fileType subtype:name.lastPathComponent name:name key:key];
}
- (BOOL)download:(LinphoneChatMessage *)message {
[[LinphoneManager.instance fileTransferDelegates] addObject:self];