From e2233674ae73f6bbddc1f7c66883b09791cecf67 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Mon, 6 Feb 2023 14:37:49 +0100 Subject: [PATCH] Add Sharing Media feature --- Classes/ChatsListView.m | 10 +- Classes/LinphoneAppDelegate.m | 4 +- .../Views/ChatConversationViewSwift.swift | 91 ++++++++++++++++++- Classes/Utils/FileTransferDelegate.m | 15 +-- 4 files changed, 102 insertions(+), 18 deletions(-) diff --git a/Classes/ChatsListView.m b/Classes/ChatsListView.m index 3a62c0358..945a25dd0 100644 --- a/Classes/ChatsListView.m +++ b/Classes/ChatsListView.m @@ -71,15 +71,15 @@ NSDictionary *dict = [defaults valueForKey:@"photoData"]; NSDictionary *dictFile = [defaults valueForKey:@"icloudData"]; NSDictionary *dictUrl = [defaults valueForKey:@"url"]; - if(dict||dictFile||dictUrl) VIEW(ChatConversationView).sharingMedia = TRUE; + if(dict||dictFile||dictUrl) VIEW(ChatConversationViewSwift).sharingMedia = TRUE; - if(VIEW(ChatConversationView).sharingMedia == nil){ + if(VIEW(ChatConversationViewSwift).sharingMedia == false){ forwardMode = VIEW(ChatConversationViewSwift).pendingForwardMessage != nil; }else{ - forwardMode = VIEW(ChatConversationView).sharingMedia != nil; + forwardMode = VIEW(ChatConversationViewSwift).sharingMedia != false; } _tableController.editButton.hidden = forwardMode; - if(VIEW(ChatConversationView).sharingMedia == nil){ + if(VIEW(ChatConversationViewSwift).sharingMedia == false){ _forwardTitle.text = NSLocalizedString(@"Select a discussion or create a new one",nil); } else{ @@ -201,7 +201,7 @@ static UICompositeViewDescription *compositeDescription = nil; } - (IBAction)onCancelForwardClicked:(id)sender { - VIEW(ChatConversationView).sharingMedia = nil; + VIEW(ChatConversationViewSwift).sharingMedia = false; VIEW(ChatConversationViewSwift).pendingForwardMessage = nil; NSString* groupName = [NSString stringWithFormat:@"group.%@.linphoneExtension",[[NSBundle mainBundle] bundleIdentifier]]; NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:groupName]; diff --git a/Classes/LinphoneAppDelegate.m b/Classes/LinphoneAppDelegate.m index f31ee4d3e..04841965d 100644 --- a/Classes/LinphoneAppDelegate.m +++ b/Classes/LinphoneAppDelegate.m @@ -423,12 +423,12 @@ } } else if([[url scheme] isEqualToString:@"message-linphone"]) { if ([[PhoneMainView.instance currentView] equal:ChatsListView.compositeViewDescription]) { - VIEW(ChatConversationView).sharingMedia = TRUE; + VIEW(ChatConversationViewSwift).sharingMedia = TRUE; ChatsListView *view = VIEW(ChatsListView); [view mediaSharing]; }else{ [SVProgressHUD dismiss]; - VIEW(ChatConversationView).sharingMedia = TRUE; + VIEW(ChatConversationViewSwift).sharingMedia = TRUE; [PhoneMainView.instance popToView:ChatsListView.compositeViewDescription]; } } else if ([scheme isEqualToString:@"sip"]||[scheme isEqualToString:@"sips"]) { diff --git a/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift b/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift index 13bc44a6d..92f5c05e5 100644 --- a/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift +++ b/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift @@ -151,10 +151,13 @@ import AVFoundation var showReplyView = false var replyMessage : OpaquePointer? = nil + @objc var sharingMedia : Bool = false + override func viewDidLoad() { super.viewDidLoad( backAction: { self.goBackChatListView() + }, action1: { self.onCallClick(cChatRoom: self.chatRoom?.getCobject) @@ -220,6 +223,7 @@ import AVFoundation } self.handlePendingTransferIfAny() + self.shareFile() } override func viewWillDisappear(_ animated: Bool) { @@ -271,6 +275,7 @@ import AVFoundation } func goBackChatListView() { + sharingMedia = false PhoneMainView.instance().pop(toView: ChatsListView.compositeViewDescription()) } @@ -527,7 +532,7 @@ import AVFoundation } - @objc func alertActionGoToDevicesList() { + func alertActionGoToDevicesList() { let notAskAgain = ConfigManager.instance().lpConfigBoolForKey(key: "confirmation_dialog_before_sas_call_not_ask_again"); if(!notAskAgain){ @@ -977,7 +982,7 @@ import AVFoundation result = self.formattedDuration(linphonePlayer.duration)! linphonePlayer.close() }catch{ - + print(error) } return result } @@ -1005,7 +1010,7 @@ import AVFoundation // we're finished, save the image and update the message let image = UIImage(data: data!) if image == nil { - showFileDownloadError() + ChatConversationViewSwift.showFileDownloadError() return } var placeHolder: PHObjectPlaceholder? = nil @@ -1199,7 +1204,7 @@ import AVFoundation collectionViewReply.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellReply") } - @objc func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if(collectionView == collectionViewMedia){ return mediaCollectionView.count } @@ -1498,6 +1503,74 @@ import AVFoundation } } + func shareFile() { + let groupName = "group.\(Bundle.main.bundleIdentifier ?? "").linphoneExtension" + let defaults = UserDefaults(suiteName: groupName) + let dict = defaults?.value(forKey: "photoData") as? [AnyHashable : Any] + let dictFile = defaults?.value(forKey: "icloudData") as? [AnyHashable : Any] + let dictUrl = defaults?.value(forKey: "url") as? [AnyHashable : Any] + if let dict { + //file shared from photo lib + let fileName = dict["url"] as? String + messageView.messageText.text = dict["message"] as? String + confirmShare(nsDataRead(), url: nil, fileName: fileName) + defaults?.removeObject(forKey: "photoData") + } else if let dictFile { + let fileName = dictFile["url"] as? String + messageView.messageText.text = dictFile["message"] as? String + confirmShare(nsDataRead(), url: nil, fileName: fileName) + defaults?.removeObject(forKey: "icloudData") + } else if let dictUrl { + let url = dictUrl["url"] as? String + messageView.messageText.text = dictUrl["message"] as? String + confirmShare(nil, url: url, fileName: nil) + defaults?.removeObject(forKey: "url") + } + } + + func nsDataRead() -> Data? { + let groupName = "group.\(Bundle.main.bundleIdentifier ?? "").linphoneExtension" + let path = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupName)?.path + let fullCacheFilePathPath = "\(path ?? "")/\("nsData")" + return NSData(contentsOfFile: fullCacheFilePathPath) as Data? + } + + func confirmShare(_ data: Data?, url: String?, fileName: String?) { + let sheet = DTActionSheet(title: NSLocalizedString("Select or create a conversation to share the file(s)", comment: "")) + DispatchQueue.main.async(execute: { [self] in + sheet!.addButton( + withTitle: NSLocalizedString("Send to this conversation", comment: "")) { [self] in + do{ + if messageView.messageText.text != "" { + try sendMessageInMessageField(rootMessage: chatRoom?.createEmptyMessage()) + } + if let url { + _ = try sendMessage(message: url, withExterlBodyUrl: nil, rootMessage: chatRoom?.createEmptyMessage()) + } else { + _ = try startFileUpload(data, withName: fileName, rootMessage: chatRoom?.createEmptyMessage()) + } + }catch{ + print(error) + } + } + + sheet!.addCancelButton(withTitle: NSLocalizedString("Cancel", comment: ""), block: nil) + sheet!.show(in: PhoneMainView.instance().view) + }) + } + + func startFileUpload(_ data: Data?, withName name: String?, rootMessage: ChatMessage?) -> Bool { + let fileTransfer = FileTransferDelegate() + fileTransfer.uploadFile(data, for: chatRoom?.getCobject, withName: name, rootMessage: rootMessage?.getCobject) + tableController.scroll(toBottom: true) + return true + } + + @objc class func getFileUrl(_ name: String?) -> URL? { + let filePath = LinphoneManager.validFilePath(name) + return URL(fileURLWithPath: filePath!) + } + @objc func initiateReplyView(forMessage: OpaquePointer?) { if(replyBubble.isHidden == false){ replyBubble.isHidden = true @@ -1508,4 +1581,14 @@ import AVFoundation replyMessage = forMessage initReplyView(true, message: forMessage) } + + @objc class func isBasicChatRoom(_ room: OpaquePointer?) -> Bool { + if room == nil { + return true + } + + let charRoomBasic = ChatRoom.getSwiftObject(cObject: room!) + let isBasic = charRoomBasic.hasCapability(mask: Int(LinphoneChatRoomCapabilitiesBasic.rawValue)) + return isBasic + } } diff --git a/Classes/Utils/FileTransferDelegate.m b/Classes/Utils/FileTransferDelegate.m index b8f4e0148..b8cccb6ad 100644 --- a/Classes/Utils/FileTransferDelegate.m +++ b/Classes/Utils/FileTransferDelegate.m @@ -22,6 +22,7 @@ #import "LinphoneManager.h" #import "PhoneMainView.h" #import "Utils.h" +#import "linphoneapp-Swift.h" @interface FileTransferDelegate () @property(strong) NSMutableData *data; @@ -51,7 +52,7 @@ static void file_transfer_progress_indication_recv(LinphoneChatMessage *message, NSString *name = [NSString stringWithUTF8String: linphone_content_get_name(content) ? : ""]; LOGI(@"Transfer of %@ (%d bytes): download finished", name, total); NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)]; - NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name]; + NSString *key = [ChatConversationViewSwift getKeyFromFileType:fileType fileName:name]; dispatch_async(dispatch_get_main_queue(), ^{ [LinphoneManager setValueInMessageAppData:name @@ -59,7 +60,7 @@ static void file_transfer_progress_indication_recv(LinphoneChatMessage *message, inMessage:message]; dispatch_async(dispatch_get_main_queue(), ^{ if (![VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] && [ConfigManager.instance lpConfigBoolForKeyWithKey:@"auto_write_to_gallery_preference"]) { - [ChatConversationView writeMediaToGallery:name fileType:fileType]; + [ChatConversationViewSwift writeMediaToGalleryFromName:name fileType:fileType]; } }); }); @@ -109,7 +110,7 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message, return; } [LinphoneManager.instance.fileTransferDelegates addObject:self]; - [ChatConversationView writeFileInImagesDirectory:data name:name]; + [ChatConversationViewSwift writeFileInImagesDirectory:data name:name]; LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom)); linphone_content_set_type(content, [type UTF8String]); @@ -120,7 +121,7 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message, linphone_chat_message_add_file_content(_message, content); const LinphoneAccountParams *params = linphone_account_get_params(linphone_core_get_default_account(LC)); BOOL cpimEnabled = linphone_account_params_cpim_in_basic_chat_room_enabled(params); - BOOL basic = [ChatConversationView isBasicChatRoom:linphone_chat_message_get_chat_room(_message)]; + BOOL basic = [ChatConversationViewSwift isBasicChatRoom:linphone_chat_message_get_chat_room(_message)]; if ((!basic || cpimEnabled) && (_text!=nil && ![_text isEqualToString:@""])) linphone_chat_message_add_utf8_text_content(_message, [_text UTF8String]); @@ -166,7 +167,7 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message, linphone_content_unref(content); } - BOOL basic = [ChatConversationView isBasicChatRoom:linphone_chat_message_get_chat_room(rootMessage)]; + BOOL basic = [ChatConversationViewSwift isBasicChatRoom:linphone_chat_message_get_chat_room(rootMessage)]; const LinphoneAccountParams *params = linphone_account_get_params(linphone_core_get_default_account(LC)); BOOL cpimEnabled = linphone_account_params_cpim_in_basic_chat_room_enabled(params); @@ -248,10 +249,10 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message, - (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name rootMessage:(LinphoneChatMessage *)rootMessage { - NSURL *url = [ChatConversationView getFileUrl:name]; + NSURL *url = [ChatConversationViewSwift getFileUrl:name]; AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; NSString *fileType = [[asset tracksWithMediaType:AVMediaTypeVideo] count] > 0 ? @"video" : @"file"; - NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name]; + NSString *key = [ChatConversationViewSwift getKeyFromFileType:fileType fileName:name]; [self uploadData:data forChatRoom:chatRoom type:fileType subtype:name.lastPathComponent name:name key:key rootMessage:rootMessage]; }