diff --git a/Classes/Swift/Chat/Views/DownloadMessageCell.swift b/Classes/Swift/Chat/Views/DownloadMessageCell.swift new file mode 100644 index 000000000..4198fc2bb --- /dev/null +++ b/Classes/Swift/Chat/Views/DownloadMessageCell.swift @@ -0,0 +1,52 @@ +// +// DownloadMessageCell.swift +// linphone +// +// Created by BenoƮt Martins on 21/03/2023. +// + +import Foundation +import linphonesw + +class DownloadMessageCell: UIView { + let downloadStackView = UIStackView() + let downloadView = UIView() + let downloadImageView = UIImageView(image: UIImage(named: "file_picture_default")) + let downloadNameLabel = StyledLabel(VoipTheme.chat_conversation_download_button) + let downloadButtonLabel = StyledLabel(VoipTheme.chat_conversation_download_button) + let downloadProgressBar = UIProgressView() + let downloadSpacing = UIView() + + var content: Content? = nil + + override init(frame: CGRect) { + super.init(frame: frame) + downloadStackView.axis = .vertical + downloadStackView.distribution = .fill + downloadStackView.alignment = .center + + addSubview(downloadStackView) + downloadStackView.addArrangedSubview(downloadView) + downloadView.addSubview(downloadImageView) + downloadStackView.addArrangedSubview(downloadNameLabel) + downloadStackView.addArrangedSubview(downloadButtonLabel) + downloadStackView.addArrangedSubview(downloadProgressBar) + downloadStackView.addArrangedSubview(downloadSpacing) + + + downloadStackView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + + downloadStackView.size(w: 138, h: 138).done() + downloadView.size(w: 138, h: 80).done() + downloadNameLabel.size(w: 130, h: 22).done() + downloadButtonLabel.size(w: 130, h: 22).done() + downloadSpacing.size(w: 138, h: 14).done() + downloadImageView.center = CGPoint(x: 69, y: 40) + downloadProgressBar.size(w: 120, h: 22).done() + downloadProgressBar.isHidden = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Classes/Swift/Chat/Views/MultilineMessageCell.swift b/Classes/Swift/Chat/Views/MultilineMessageCell.swift index 1eb8dc23a..7e720fd1b 100644 --- a/Classes/Swift/Chat/Views/MultilineMessageCell.swift +++ b/Classes/Swift/Chat/Views/MultilineMessageCell.swift @@ -46,7 +46,6 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI var recordingConstraints: [NSLayoutConstraint] = [] var recordingWaveConstraints: [NSLayoutConstraint] = [] var meetingConstraints: [NSLayoutConstraint] = [] - var downloadStackViewConstraints: [NSLayoutConstraint] = [] let eventMessageLineView: UIView = UIView(frame: .zero) let eventMessageLabelView: UIView = UIView(frame: .zero) @@ -106,6 +105,7 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI var imagesGridCollectionView : [UIImage?] = [] var imagesGridURLCollection : [URL?] = [] var imagesGridContentCollection : [Content] = [] + var downloadContentCollection: [DownloadMessageCell?] = [] let imageViewBubble = UIImageView(image: UIImage(named: "chat_error")) let imageVideoViewBubble = UIImageView(image: UIImage(named: "file_video_default")) @@ -118,6 +118,9 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI var isPlayingVoiceRecording = false var chatMessage: ChatMessage? + var chatMessageDelegate: ChatMessageDelegate? = nil + + var indexTransferProgress: Int = -1 override init(frame: CGRect) { super.init(frame: frame) @@ -527,6 +530,7 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI func configure(event: EventLog) { chatMessage = event.chatMessage + addMessageDelegate() if event.chatMessage != nil { contentBubble.isHidden = false eventMessageView.isHidden = true @@ -795,6 +799,16 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI } } + + func addMessageDelegate(){ + chatMessageDelegate = ChatMessageDelegateStub( + onFileTransferProgressIndication: { (message: ChatMessage, content: Content, offset: Int, total: Int) -> Void in + self.file_transfer_progress_indication_recv(message: message, content: content, offset: offset, total: total) + } + ) + chatMessage?.addDelegate(delegate: chatMessageDelegate!) + } + override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { label.preferredMaxLayoutWidth = (UIScreen.main.bounds.size.width*3/4) layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height @@ -953,49 +967,29 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI cell.addSubview(viewCell) if imagesGridURLCollection[indexPath.row] == nil { - let downloadStackViewMulti = UIStackView() - let downloadViewMulti = UIView() - let downloadImageViewMulti = UIImageView(image: UIImage(named: "file_picture_default")) - let downloadNameLabelMulti = StyledLabel(VoipTheme.chat_conversation_download_button) - let downloadButtonLabelMulti = StyledLabel(VoipTheme.chat_conversation_download_button) - let downloadSpacingMulti = UIView() - - downloadStackViewMulti.axis = .vertical; - downloadStackViewMulti.distribution = .fill; - downloadStackViewMulti.alignment = .center; - - cell.addSubview(downloadStackViewMulti) - downloadStackViewMulti.addArrangedSubview(downloadViewMulti) - downloadViewMulti.addSubview(downloadImageViewMulti) - downloadStackViewMulti.addArrangedSubview(downloadNameLabelMulti) - downloadStackViewMulti.addArrangedSubview(downloadButtonLabelMulti) - downloadStackViewMulti.addArrangedSubview(downloadSpacingMulti) - - - downloadStackViewMulti.backgroundColor = VoipTheme.backgroundWhiteBlack.get() - - downloadStackViewMulti.size(w: 138, h: 138).done() - downloadViewMulti.size(w: 138, h: 80).done() - downloadNameLabelMulti.size(w: 130, h: 22).done() - downloadButtonLabelMulti.size(w: 130, h: 22).done() - downloadSpacingMulti.size(w: 138, h: 14).done() - downloadImageViewMulti.center = CGPoint(x: 69, y: 40) - - downloadNameLabelMulti.text = imagesGridContentCollection[indexPath.row].name.replacingOccurrences(of: imagesGridContentCollection[indexPath.row].name.dropFirst(6).dropLast(8), with: "...") + let downloadView = DownloadMessageCell() + downloadContentCollection.append(downloadView) + downloadView.content = imagesGridContentCollection[indexPath.row] + downloadView.size(w: 138, h: 138).done() + viewCell.addSubview(downloadView) + downloadView.downloadNameLabel.text = imagesGridContentCollection[indexPath.row].name.replacingOccurrences(of: imagesGridContentCollection[indexPath.row].name.dropFirst(6).dropLast(8), with: "...") + let underlineAttribute = [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.thick.rawValue] - let underlineAttributedString = NSAttributedString(string: "\(VoipTexts.bubble_chat_download_file) (\(Float(imagesGridContentCollection[indexPath.row].fileSize / 1000000)) Mo)", attributes: underlineAttribute) - downloadButtonLabelMulti.attributedText = underlineAttributedString - downloadButtonLabelMulti.onClick { - DispatchQueue.main.async(execute: { - self.imagesGridContentCollection[indexPath.row].filePath = LinphoneManager.imagesDirectory() + self.imagesGridContentCollection[indexPath.row].name - self.chatMessage!.downloadContent(content: self.imagesGridContentCollection[indexPath.row]) - }) + let underlineAttributedString = NSAttributedString(string: "\(VoipTexts.bubble_chat_download_file) (\(String(format: "%.1f", Float(imagesGridContentCollection[indexPath.row].fileSize) / 1000000)) Mo)", attributes: underlineAttribute) + downloadView.downloadButtonLabel.attributedText = underlineAttributedString + downloadView.downloadButtonLabel.onClick { + self.imagesGridContentCollection[indexPath.row].filePath = LinphoneManager.imagesDirectory() + self.imagesGridContentCollection[indexPath.row].name + let _ = self.chatMessage!.downloadContent(content: self.imagesGridContentCollection[indexPath.row]) } + downloadView.downloadButtonLabel.isUserInteractionEnabled = true + if(linphone_core_get_max_size_for_auto_download_incoming_files(LinphoneManager.getLc()) > -1 && self.chatMessage!.isFileTransferInProgress){ - downloadButtonLabelMulti.isHidden = true + downloadView.downloadButtonLabel.isHidden = true } } else { + downloadContentCollection.append(nil) + let imageCell = imagesGridCollectionView[indexPath.row] let myImageView = UIImageView() @@ -1167,6 +1161,36 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI return VoipTexts.bubble_chat_event_message_ephemeral_unexpected_duration } } + + func file_transfer_progress_indication_recv(message: ChatMessage, content: Content, offset: Int, total: Int) { + let p = Float(offset) / Float(total) + + if indexTransferProgress == -1 { + for indexItem in 0...imagesGridContentCollection.count - 1 { + if imagesGridContentCollection[indexItem].name == content.name { + indexTransferProgress = indexItem + break + } + } + + downloadContentCollection[indexTransferProgress]!.downloadButtonLabel.isHidden = true + downloadContentCollection[indexTransferProgress]!.downloadProgressBar.isHidden = false + } + + DispatchQueue.main.async(execute: { [self] in + if (offset == total) { + downloadContentCollection[indexTransferProgress] = nil + imagesGridContentCollection[indexTransferProgress] = content + imagesGridURLCollection[indexTransferProgress] = (URL(string: content.filePath)!) + imagesGridCollectionView[indexTransferProgress] = getImageFrom(content.getCobject, filePath: content.filePath, forReplyBubble: true)! + + collectionViewImagesGrid.reloadItems(at: [IndexPath(row: indexTransferProgress, section: 0)]) + indexTransferProgress = -1 + } else { + downloadContentCollection[indexTransferProgress]!.downloadProgressBar.setProgress(p, animated: true) + } + }) + } } class DynamicHeightCollectionView: UICollectionView { diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj index f1dd99be5..c98f6acdf 100644 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -946,6 +946,7 @@ D7421D9E29228A5200290CAB /* DetailChatRoomFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7421D9D29228A5200290CAB /* DetailChatRoomFragment.swift */; }; D7013DB82940AA12004EEAAE /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7013DB72940AA12004EEAAE /* MessageView.swift */; }; D7097B35296D684900AEF6C5 /* FileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7097B34296D684900AEF6C5 /* FileType.swift */; }; + D71418E329C9B4E0002EEF75 /* DownloadMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71418E229C9B4E0002EEF75 /* DownloadMessageCell.swift */; }; D7421D9E29228A5200290CAB /* ChatConversationViewSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7421D9D29228A5200290CAB /* ChatConversationViewSwift.swift */; }; D74A44912923BAF90017D063 /* BackActionsNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74A44902923BAF90017D063 /* BackActionsNavigationView.swift */; }; D77057F1292E4A340031A970 /* ChatConversationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77057F0292E4A340031A970 /* ChatConversationViewModel.swift */; }; @@ -2207,6 +2208,7 @@ D59A11B7EA2D725CDEB15DDF /* Pods_msgNotificationContent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_msgNotificationContent.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7013DB72940AA12004EEAAE /* MessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageView.swift; sourceTree = ""; }; D7097B34296D684900AEF6C5 /* FileType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileType.swift; sourceTree = ""; }; + D71418E229C9B4E0002EEF75 /* DownloadMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadMessageCell.swift; sourceTree = ""; }; D7421D9D29228A5200290CAB /* ChatConversationViewSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatConversationViewSwift.swift; sourceTree = ""; }; D74A44902923BAF90017D063 /* BackActionsNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackActionsNavigationView.swift; sourceTree = ""; }; D77057F0292E4A340031A970 /* ChatConversationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatConversationViewModel.swift; sourceTree = ""; }; @@ -3889,6 +3891,7 @@ D779D39929A4C285007B8087 /* MultilineMessageCell.swift */, D7C6DE812948CF3100756E03 /* DropDownCell.swift */, D7C6DE822948CF3100756E03 /* DropDownCell.xib */, + D71418E229C9B4E0002EEF75 /* DownloadMessageCell.swift */, ); path = Views; sourceTree = ""; @@ -5334,6 +5337,7 @@ C63F7248285A24B10066163B /* MicMuted.swift in Sources */, C63F7243285A24B10066163B /* AudioRoutesView.swift in Sources */, D3807FF415C2894A005BE9BC /* IASKSettingsStoreUserDefaults.m in Sources */, + D71418E329C9B4E0002EEF75 /* DownloadMessageCell.swift in Sources */, C63F7240285A24B10066163B /* VoipTheme.swift in Sources */, C63F7265285A24B10066163B /* VoipExtraButton.swift in Sources */, 639E9C801C0DB13D00019A75 /* UICheckBoxTableView.m in Sources */,