diff --git a/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift b/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift index ab94f00ba..0f90f824b 100644 --- a/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift +++ b/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift @@ -349,7 +349,7 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour } let view: ChatConversationViewSwift = self.VIEW(ChatConversationViewSwift.compositeViewDescription()) - view.messageView.endEditing(true) + view.contentMessageView.messageView.endEditing(true) menu!.show() menu!.selectionAction = { [weak self] (index: Int, item: String) in @@ -476,8 +476,8 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour func replyMessage(message: ChatMessage){ let view: ChatConversationViewSwift = self.VIEW(ChatConversationViewSwift.compositeViewDescription()) - if (view.messageView.messageText.text == "" && view.stackView.arrangedSubviews[3].isHidden && view.stackView.arrangedSubviews[4].isHidden){ - view.messageView.messageText.becomeFirstResponder() + if (view.contentMessageView.messageView.messageText.textColor == UIColor.lightGray && view.contentMessageView.stackView.arrangedSubviews[3].isHidden && view.contentMessageView.stackView.arrangedSubviews[4].isHidden){ + view.contentMessageView.messageView.messageText.becomeFirstResponder() } view.initiateReplyView(forMessage: message.getCobject) } diff --git a/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift b/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift index 6d885b680..4726645a4 100644 --- a/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift +++ b/Classes/Swift/Chat/Views/ChatConversationViewSwift.swift @@ -24,6 +24,7 @@ import DropDown import PhotosUI import AVFoundation import EmojiPicker +import IQKeyboardManager class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControllerDelegate, UIDocumentPickerDelegate, UICompositeViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate, UIImagePickerControllerDelegate, EmojiPickerDelegate, CoreDelegate & UINavigationControllerDelegate{ // Replaces ChatConversationView @@ -151,6 +152,8 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll ) setupViews() markAsRead = true + + IQKeyboardManager.shared().disabledDistanceHandlingClasses.add(BackActionsNavigationView.self) //PhoneMainView.instance()!.mainViewController.view.makeSecure(field: field) /* @@ -171,7 +174,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll */ ChatConversationViewModel.sharedModel.isComposing.observe { compose in - if((compose! && self.isComposingView.isHidden)||(!compose! && !self.isComposingView.isHidden)){ + if((compose! && self.contentMessageView.isComposingView.isHidden)||(!compose! && !self.contentMessageView.isComposingView.isHidden)){ self.setComposingVisible(compose!, withDelay: 0.3) } } @@ -189,7 +192,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll ChatConversationViewModel.sharedModel.secureLevelChanged.observe { secure in self.updateParticipantLabel() self.tableControllerSwift.refreshData(isOutgoing: false) - self.changeSecureLevel(secureLevel: ChatConversationViewModel.sharedModel.secureLevel != nil, imageBadge: ChatConversationViewModel.sharedModel.secureLevel) + self.contentMessageView.changeSecureLevel(secureLevel: ChatConversationViewModel.sharedModel.secureLevel != nil, imageBadge: ChatConversationViewModel.sharedModel.secureLevel) } ChatConversationViewModel.sharedModel.subjectChanged.observe { subject in @@ -211,23 +214,23 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll ChatConversationViewModel.sharedModel.indexPathVM.observe { index in self.collectionViewMedia.reloadData() if(ChatConversationViewModel.sharedModel.mediaCollectionView.count > 0){ - self.messageView.sendButton.isEnabled = true + self.contentMessageView.messageView.sendButton.isEnabled = true } self.loadingView.isHidden = true - self.messageView.isLoading = false + self.contentMessageView.messageView.isLoading = false self.loading.stopRotation() - self.messageView.sendButton.isEnabled = true - self.messageView.pictureButton.isEnabled = true + self.contentMessageView.messageView.sendButton.isEnabled = true + self.contentMessageView.messageView.pictureButton.isEnabled = true } ChatConversationViewModel.sharedModel.shareFileName.observe { name in - self.messageView.messageText.text = ChatConversationViewModel.sharedModel.shareFileMessage + self.contentMessageView.messageView.messageText.text = ChatConversationViewModel.sharedModel.shareFileMessage self.confirmShare(ChatConversationViewModel.sharedModel.nsDataRead(), url: nil, fileName: name) } ChatConversationViewModel.sharedModel.shareFileURL.observe { url in - self.messageView.messageText.text = ChatConversationViewModel.sharedModel.shareFileMessage + self.contentMessageView.messageView.messageText.text = ChatConversationViewModel.sharedModel.shareFileMessage self.confirmShare(ChatConversationViewModel.sharedModel.nsDataRead(), url: url, fileName: nil) } @@ -271,31 +274,33 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + IQKeyboardManager.shared().isEnabled = true + IQKeyboardManager.shared().isEnableAutoToolbar = false ChatConversationViewModel.sharedModel.createChatConversation() topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - self.contentView.addSubview(tableControllerSwift.view) + self.contentMessageView.contentView.addSubview(tableControllerSwift.view) // Setup Autolayout constraints tableControllerSwift.view.translatesAutoresizingMaskIntoConstraints = false - tableControllerSwift.view.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: 0).isActive = true - tableControllerSwift.view.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0).isActive = true - tableControllerSwift.view.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0).isActive = true - tableControllerSwift.view.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: 0).isActive = true + tableControllerSwift.view.bottomAnchor.constraint(equalTo: self.contentMessageView.contentView.bottomAnchor, constant: 0).isActive = true + tableControllerSwift.view.leftAnchor.constraint(equalTo: self.contentMessageView.contentView.leftAnchor, constant: 0).isActive = true + tableControllerSwift.view.topAnchor.constraint(equalTo: self.contentMessageView.contentView.topAnchor, constant: 0).isActive = true + tableControllerSwift.view.rightAnchor.constraint(equalTo: self.contentMessageView.contentView.rightAnchor, constant: 0).isActive = true ChatConversationTableViewModel.sharedModel.chatRoom = ChatConversationViewModel.sharedModel.chatRoom - messageView.sendButton.onClickAction = onSendClick - messageView.pictureButton.onClickAction = alertAction - messageView.voiceRecordButton.onClickAction = onVrStart - messageView.emojisButton.addTarget(self,action:#selector(openEmojiPickerModule), + contentMessageView.messageView.sendButton.onClickAction = onSendClick + contentMessageView.messageView.pictureButton.onClickAction = alertAction + contentMessageView.messageView.voiceRecordButton.onClickAction = onVrStart + contentMessageView.messageView.emojisButton.addTarget(self,action:#selector(openEmojiPickerModule), for:.touchUpInside) - recordingDeleteButton.onClickAction = cancelVoiceRecording - recordingPlayButton.onClickAction = onvrPlayPauseStop - recordingStopButton.onClickAction = onvrPlayPauseStop + contentMessageView.recordingDeleteButton.onClickAction = cancelVoiceRecording + contentMessageView.recordingPlayButton.onClickAction = onvrPlayPauseStop + contentMessageView.recordingStopButton.onClickAction = onvrPlayPauseStop if !ChatConversationViewModel.sharedModel.chatRoom!.isReadOnly { - messageView.ephemeralIndicator.isHidden = !ChatConversationViewModel.sharedModel.chatRoom!.ephemeralEnabled + contentMessageView.messageView.ephemeralIndicator.isHidden = !ChatConversationViewModel.sharedModel.chatRoom!.ephemeralEnabled } handlePendingTransferIfAny() @@ -330,6 +335,8 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll */ field.isUserInteractionEnabled = true + + IQKeyboardManager.shared().isEnabled = false } override func viewDidDisappear(_ animated: Bool) { @@ -340,32 +347,32 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll ChatConversationViewModel.sharedModel.resetViewModel() linphoneChatRoom = nil editModeOff() - if(self.isComposingView.isHidden == false){ - self.isComposingView.isHidden = true + if(self.contentMessageView.isComposingView.isHidden == false){ + self.contentMessageView.isComposingView.isHidden = true } - if(self.mediaSelector.isHidden == false){ - self.mediaSelector.isHidden = true + if(self.contentMessageView.mediaSelector.isHidden == false){ + self.contentMessageView.mediaSelector.isHidden = true } - if(self.replyBubble.isHidden == false){ - self.replyBubble.isHidden = true + if(self.contentMessageView.replyBubble.isHidden == false){ + self.contentMessageView.replyBubble.isHidden = true } cancelVoiceRecording() ChatConversationViewModel.sharedModel.mediaCollectionView = [] ChatConversationViewModel.sharedModel.replyCollectionView.removeAll() - self.messageView.fileContext = false + self.contentMessageView.messageView.fileContext = false ChatConversationViewModel.sharedModel.imageT = [] self.collectionViewMedia.reloadData() self.collectionViewReply.reloadData() - if self.messageView.messageText.text.isEmpty{ - self.messageView.sendButton.isEnabled = false + if contentMessageView.messageView.messageText.textColor == UIColor.lightGray || self.contentMessageView.messageView.messageText.text.isEmpty{ + self.contentMessageView.messageView.sendButton.isEnabled = false } else { - self.messageView.sendButton.isEnabled = true + self.contentMessageView.messageView.sendButton.isEnabled = true } - self.messageView.pictureButton.isEnabled = true + self.contentMessageView.messageView.pictureButton.isEnabled = true - isComposingTextView.text = "" + contentMessageView.isComposingTextView.text = "" } func goBackChatListView() { @@ -550,7 +557,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll menu.dataSource.append(VoipTexts.dropdown_menu_chat_conversation_delete_messages) if !ChatConversationViewModel.sharedModel.chatRoom!.isReadOnly { - messageView.ephemeralIndicator.isHidden = !ChatConversationViewModel.sharedModel.chatRoom!.ephemeralEnabled + contentMessageView.messageView.ephemeralIndicator.isHidden = !ChatConversationViewModel.sharedModel.chatRoom!.ephemeralEnabled } } @@ -589,7 +596,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll action1BisButton.isEnabled = false } let secureLevel = FastAddressBook.image(for: linphone_chat_room_get_security_level(cChatRoom)) - changeSecureLevel(secureLevel: secureLevel != nil, imageBadge: secureLevel) + contentMessageView.changeSecureLevel(secureLevel: secureLevel != nil, imageBadge: secureLevel) initDataSource(groupeChat: !isOneToOneChat, secureLevel: secureLevel != nil, cChatRoom: cChatRoom) } @@ -791,14 +798,21 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll func sendMessageInMessageField(rootMessage: ChatMessage?) { - if ChatConversationViewModel.sharedModel.sendMessage(message: messageView.messageText.text.trimmingCharacters(in: .whitespacesAndNewlines), withExterlBodyUrl: nil, rootMessage: rootMessage) { - messageView.messageText.text = "" - messageView.isComposing = false + if ChatConversationViewModel.sharedModel.sendMessage(message: contentMessageView.messageView.messageText.textColor != UIColor.lightGray ? contentMessageView.messageView.messageText.text.trimmingCharacters(in: .whitespacesAndNewlines) : "", withExterlBodyUrl: nil, rootMessage: rootMessage) { + if !contentMessageView.messageView.messageText.isFirstResponder{ + contentMessageView.messageView.messageText.textColor = UIColor.lightGray + contentMessageView.messageView.messageText.text = "Message" + } else { + contentMessageView.messageView.messageText.text = "" + } + contentMessageView.messageView.emojisButton.isHidden = false + contentMessageView.messageView.isComposing = false } + setSendButtonState() } func onSendClick() { - let rootMessage = !replyBubble.isHidden ? linphone_chat_room_create_reply_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject, ChatConversationViewModel.sharedModel.replyMessage) : linphone_chat_room_create_empty_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject) + let rootMessage = !contentMessageView.replyBubble.isHidden ? linphone_chat_room_create_reply_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject, ChatConversationViewModel.sharedModel.replyMessage) : linphone_chat_room_create_empty_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject) if ChatConversationViewModel.sharedModel.isVoiceRecording { stopVoiceRecording() @@ -812,8 +826,8 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll if (linphone_chat_room_get_capabilities(ChatConversationViewModel.sharedModel.chatRoom?.getCobject) != 0) && conference { linphone_chat_message_add_content(rootMessage, voiceContent) }else{ - if messageView.messageText.text != "" { - let rootMessageText = !replyBubble.isHidden ? linphone_chat_room_create_reply_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject, ChatConversationViewModel.sharedModel.replyMessage) : linphone_chat_room_create_empty_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject) + if contentMessageView.messageView.messageText.textColor != UIColor.lightGray { + let rootMessageText = !contentMessageView.replyBubble.isHidden ? linphone_chat_room_create_reply_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject, ChatConversationViewModel.sharedModel.replyMessage) : linphone_chat_room_create_empty_message(ChatConversationViewModel.sharedModel.chatRoom?.getCobject) let result = ChatMessage.getSwiftObject(cObject: rootMessageText!) sendMessageInMessageField(rootMessage: result) @@ -832,29 +846,29 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll for i in 0..<(ChatConversationViewModel.sharedModel.fileContext.count) { startUploadData(ChatConversationViewModel.sharedModel.fileContext[i], withType: FileType.init(ChatConversationViewModel.sharedModel.mediaURLCollection[i].pathExtension)?.getGroupTypeFromFile(), withName: ChatConversationViewModel.sharedModel.mediaURLCollection[i].lastPathComponent, andMessage: nil, rootMessage: nil) } - if messageView.messageText.text != "" { + if contentMessageView.messageView.messageText.textColor != UIColor.lightGray { let result = ChatMessage.getSwiftObject(cObject: rootMessage!) sendMessageInMessageField(rootMessage: result) } } ChatConversationViewModel.sharedModel.fileContext = [] - messageView.fileContext = false + contentMessageView.messageView.fileContext = false ChatConversationViewModel.sharedModel.mediaCollectionView = [] ChatConversationViewModel.sharedModel.mediaURLCollection = [] - if(self.mediaSelector.isHidden == false){ - self.mediaSelector.isHidden = true + if(self.contentMessageView.mediaSelector.isHidden == false){ + self.contentMessageView.mediaSelector.isHidden = true } - if(self.replyBubble.isHidden == false){ - self.replyBubble.isHidden = true + if(self.contentMessageView.replyBubble.isHidden == false){ + self.contentMessageView.replyBubble.isHidden = true } return } - if(self.mediaSelector.isHidden == false){ - self.mediaSelector.isHidden = true + if(self.contentMessageView.mediaSelector.isHidden == false){ + self.contentMessageView.mediaSelector.isHidden = true } - if(self.replyBubble.isHidden == false){ - self.replyBubble.isHidden = true + if(self.contentMessageView.replyBubble.isHidden == false){ + self.contentMessageView.replyBubble.isHidden = true } let result = ChatMessage.getSwiftObject(cObject: rootMessage!) sendMessageInMessageField(rootMessage: result) @@ -862,9 +876,22 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll func startMultiFilesUpload(_ rootMessage: ChatMessage?) -> Bool { let fileTransfer = FileTransferDelegate() - fileTransfer.text = messageView.messageText.text + if contentMessageView.messageView.messageText.textColor != UIColor.lightGray { + fileTransfer.text = contentMessageView.messageView.messageText.text + } else { + fileTransfer.text = "" + } fileTransfer.uploadFileContent(forSwift: ChatConversationViewModel.sharedModel.fileContext, urlList: ChatConversationViewModel.sharedModel.mediaURLCollection, for: ChatConversationViewModel.sharedModel.chatRoom?.getCobject, rootMessage: rootMessage?.getCobject) - messageView.messageText.text = "" + if fileTransfer.text.isEmpty && !contentMessageView.messageView.messageText.isFirstResponder{ + contentMessageView.messageView.messageText.textColor = UIColor.lightGray + contentMessageView.messageView.messageText.text = "Message" + contentMessageView.messageView.emojisButton.isHidden = false + } else { + contentMessageView.messageView.messageText.text = "" + contentMessageView.messageView.emojisButton.isHidden = false + } + contentMessageView.messageView.sendButton.isEnabled = false + tableControllerSwift.refreshData(isOutgoing: true) return true } @@ -892,7 +919,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll if addresses.count == 1 { composingAddresses = FastAddressBook.displayName(for: addresses.first?.getCobject) - isComposingTextView.text = String.localizedStringWithFormat(NSLocalizedString("%@ is writing...", comment: ""), composingAddresses!) + contentMessageView.isComposingTextView.text = String.localizedStringWithFormat(NSLocalizedString("%@ is writing...", comment: ""), composingAddresses!) } else { addresses.forEach({ addressItem in if composingAddresses != "" { @@ -900,23 +927,23 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } composingAddresses = composingAddresses! + FastAddressBook.displayName(for: addressItem.getCobject) }) - isComposingTextView.text = String.localizedStringWithFormat(NSLocalizedString("%@ are writing...", comment: ""), composingAddresses!) + contentMessageView.isComposingTextView.text = String.localizedStringWithFormat(NSLocalizedString("%@ are writing...", comment: ""), composingAddresses!) } } UIView.animate(withDuration: 0.3, animations: { - self.isComposingView.isHidden = !self.isComposingView.isHidden + self.contentMessageView.isComposingView.isHidden = !self.contentMessageView.isComposingView.isHidden }) } func selectionMedia() { UIView.animate(withDuration: 0.3, animations: { - self.mediaSelector.isHidden = !self.mediaSelector.isHidden + self.contentMessageView.mediaSelector.isHidden = !self.contentMessageView.mediaSelector.isHidden }) } func setRecordingVisible(visible : Bool) { UIView.animate(withDuration: 0.3, animations: { - self.recordingView.isHidden = visible + self.contentMessageView.recordingView.isHidden = visible }) } @@ -924,18 +951,18 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll if visible { let addresses = ChatMessage.getSwiftObject(cObject: message!).fromAddress let composingAddresses : String? = FastAddressBook.displayName(for: addresses?.getCobject) - replyLabelTextView.text = String.localizedStringWithFormat(NSLocalizedString("%@", comment: ""), composingAddresses!) + contentMessageView.replyLabelTextView.text = String.localizedStringWithFormat(NSLocalizedString("%@", comment: ""), composingAddresses!) let isIcal = ICSBubbleView.isConferenceInvitationMessage(cmessage: message!) let content : String? = (isIcal ? ICSBubbleView.getSubjectFromContent(cmessage: message!) : ChatMessage.getSwiftObject(cObject: message!).utf8Text) - replyContentTextView.text = content - replyContentForMeetingTextView.text = content - backgroundReplyColor.backgroundColor = (linphone_chat_message_is_outgoing(message) != 0) ? UIColor("A").withAlphaComponent(0.2) : UIColor("D").withAlphaComponent(0.2) + contentMessageView.replyContentTextView.text = content + contentMessageView.replyContentForMeetingTextView.text = content + contentMessageView.backgroundReplyColor.backgroundColor = (linphone_chat_message_is_outgoing(message) != 0) ? UIColor("A").withAlphaComponent(0.2) : UIColor("D").withAlphaComponent(0.2) - replyDeleteButton.isHidden = false - replyDeleteButton.onClickAction = { - self.replyDeleteButton.isHidden = true + contentMessageView.replyDeleteButton.isHidden = false + contentMessageView.replyDeleteButton.onClickAction = { + self.contentMessageView.replyDeleteButton.isHidden = true self.initReplyView(false, message: nil) ChatConversationViewModel.sharedModel.replyURLCollection.removeAll() ChatConversationViewModel.sharedModel.replyCollectionView.removeAll() @@ -945,17 +972,17 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll let contentList = linphone_chat_message_get_contents(message) if(isIcal){ - replyMeetingSchedule.image = UIImage(named: "voip_meeting_schedule") - replyMeetingSchedule.isHidden = false - replyContentForMeetingTextView.isHidden = false - replyContentTextView.isHidden = true - mediaSelectorReply.isHidden = true - replyContentTextSpacing.isHidden = true + contentMessageView.replyMeetingSchedule.image = UIImage(named: "voip_meeting_schedule") + contentMessageView.replyMeetingSchedule.isHidden = false + contentMessageView.replyContentForMeetingTextView.isHidden = false + contentMessageView.replyContentTextView.isHidden = true + contentMessageView.mediaSelectorReply.isHidden = true + contentMessageView.replyContentTextSpacing.isHidden = true }else{ if(bctbx_list_size(contentList) > 1 || content == ""){ - mediaSelectorReply.isHidden = false - replyContentTextSpacing.isHidden = true + contentMessageView.mediaSelectorReply.isHidden = false + contentMessageView.replyContentTextSpacing.isHidden = true ChatMessage.getSwiftObject(cObject: message!).contents.forEach({ content in if(content.isFile){ let indexPath = IndexPath(row: ChatConversationViewModel.sharedModel.replyCollectionView.count, section: 0) @@ -976,22 +1003,22 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll collectionViewReply.reloadData() }else if(content.isText){ - replyContentTextSpacing.isHidden = false + contentMessageView.replyContentTextSpacing.isHidden = false } }) }else{ - mediaSelectorReply.isHidden = true + contentMessageView.mediaSelectorReply.isHidden = true } - replyMeetingSchedule.isHidden = true - replyContentForMeetingTextView.isHidden = true - replyContentTextView.isHidden = false + contentMessageView.replyMeetingSchedule.isHidden = true + contentMessageView.replyContentForMeetingTextView.isHidden = true + contentMessageView.replyContentTextView.isHidden = false } } UIView.animate(withDuration: 0.3, animations: { - self.replyBubble.isHidden = !self.replyBubble.isHidden + self.contentMessageView.replyBubble.isHidden = !self.contentMessageView.replyBubble.isHidden }) } @@ -1094,14 +1121,14 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } func setupViews() { - mediaSelector.addSubview(collectionViewMedia) + contentMessageView.mediaSelector.addSubview(collectionViewMedia) collectionViewMedia.dataSource = self collectionViewMedia.delegate = self collectionViewMedia.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell") loadingView.backgroundColor = UIColor(red: 0.77, green: 0.77, blue: 0.77, alpha: 0.80) - mediaSelector.addSubview(loadingView) + contentMessageView.mediaSelector.addSubview(loadingView) loadingView.matchParentEdges().done() loadingText.text = VoipTexts.operation_in_progress_wait @@ -1110,7 +1137,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll loadingText.alignParentLeft(withMargin: 10).alignParentRight(withMargin: 10).alignParentBottom(withMargin: 30).alignVerticalCenterWith(loadingView).done() loading.square(Int(top_bar_height)).alignVerticalCenterWith(loadingView).alignParentTop(withMargin: 20).done() - mediaSelectorReply.addSubview(collectionViewReply) + contentMessageView.mediaSelectorReply.addSubview(collectionViewReply) collectionViewReply.dataSource = self collectionViewReply.delegate = self collectionViewReply.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellReply") @@ -1139,7 +1166,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll ChatConversationViewModel.sharedModel.imageT.remove(at: indexPath.row) ChatConversationViewModel.sharedModel.data.remove(at: indexPath.row) if(ChatConversationViewModel.sharedModel.mediaCollectionView.count == 0){ - self.messageView.fileContext = false + self.contentMessageView.messageView.fileContext = false self.selectionMedia() self.setSendButtonState() } @@ -1312,23 +1339,23 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll public func initListMedia(sequenceCount : Int){ if(ChatConversationViewModel.sharedModel.mediaCollectionView.count == 0 && sequenceCount >= 1){ self.selectionMedia() - self.messageView.sendButton.isEnabled = !messageView.isLoading - self.messageView.fileContext = true + self.contentMessageView.messageView.sendButton.isEnabled = !contentMessageView.messageView.isLoading + self.contentMessageView.messageView.fileContext = true ChatConversationViewModel.sharedModel.urlFile = [] ChatConversationViewModel.sharedModel.imageT = [] ChatConversationViewModel.sharedModel.data = [] } if(ChatConversationViewModel.sharedModel.mediaCollectionView.count > 0){ - self.messageView.sendButton.isEnabled = !messageView.isLoading + self.contentMessageView.messageView.sendButton.isEnabled = !contentMessageView.messageView.isLoading } if(sequenceCount >= 1){ loadingView.isHidden = false - messageView.isLoading = true + contentMessageView.messageView.isLoading = true loading.startRotation() - self.messageView.sendButton.isEnabled = false - self.messageView.pictureButton.isEnabled = false + self.contentMessageView.messageView.sendButton.isEnabled = false + self.contentMessageView.messageView.pictureButton.isEnabled = false ChatConversationViewModel.sharedModel.mediaCount = ChatConversationViewModel.sharedModel.mediaCollectionView.count ChatConversationViewModel.sharedModel.newMediaCount = sequenceCount @@ -1360,7 +1387,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll sheet!.addButton( withTitle: NSLocalizedString("Send to this conversation", comment: "")) { [self] in do{ - if messageView.messageText.text != "" { + if contentMessageView.messageView.messageText.textColor != UIColor.lightGray { try sendMessageInMessageField(rootMessage: ChatConversationViewModel.sharedModel.chatRoom?.createEmptyMessage()) } if let sUrl = url { @@ -1389,8 +1416,8 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } @objc func initiateReplyView(forMessage: OpaquePointer?) { - if(replyBubble.isHidden == false){ - replyBubble.isHidden = true + if(contentMessageView.replyBubble.isHidden == false){ + contentMessageView.replyBubble.isHidden = true } ChatConversationViewModel.sharedModel.replyURLCollection.removeAll() ChatConversationViewModel.sharedModel.replyCollectionView.removeAll() @@ -1410,10 +1437,10 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } func onVrStart() { - self.recordingWaveImageMask.isHidden = false - recordingWaveView.progress = 0.0 - recordingWaveView.setProgress(recordingWaveView.progress, animated: false) - self.messageView.sendButton.isEnabled = true + self.contentMessageView.recordingWaveImageMask.isHidden = false + contentMessageView.recordingWaveView.progress = 0.0 + contentMessageView.recordingWaveView.setProgress(contentMessageView.recordingWaveView.progress, animated: false) + self.contentMessageView.messageView.sendButton.isEnabled = true if ChatConversationViewModel.sharedModel.isVoiceRecording { stopVoiceRecording() } else { @@ -1422,7 +1449,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } @objc private func openEmojiPickerModule(sender: UIButton) { - messageView.messageText.resignFirstResponder() + contentMessageView.messageView.messageText.resignFirstResponder() let viewController = EmojiPickerViewController() viewController.delegate = self viewController.sourceView = sender @@ -1431,18 +1458,24 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } func didGetEmoji(emoji: String) { - messageView.messageText.text = messageView.messageText.text + emoji + if contentMessageView.messageView.messageText.textColor != UIColor.lightGray { + contentMessageView.messageView.messageText.text = contentMessageView.messageView.messageText.text + emoji + } else { + contentMessageView.messageView.messageText.textColor = VoipTheme.backgroundBlackWhite.get() + contentMessageView.messageView.messageText.text = emoji + } + } func startVoiceRecording() { ChatConversationViewModel.sharedModel.startVoiceRecording() setRecordingVisible(visible: false) - messageView.voiceRecordButton.isSelected = true - recordingStopButton.isHidden = false - recordingPlayButton.isHidden = true - self.recordingWaveImageMask.transform = CGAffineTransform.identity - recordingDurationTextView.isHidden = false - recordingDurationTextView.text = ChatConversationViewModel.sharedModel.formattedDuration(Int(linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject))) + contentMessageView.messageView.voiceRecordButton.isSelected = true + contentMessageView.recordingStopButton.isHidden = false + contentMessageView.recordingPlayButton.isHidden = true + self.contentMessageView.recordingWaveImageMask.transform = CGAffineTransform.identity + contentMessageView.recordingDurationTextView.isHidden = false + contentMessageView.recordingDurationTextView.text = ChatConversationViewModel.sharedModel.formattedDuration(Int(linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject))) ChatConversationViewModel.sharedModel.vrRecordTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in self.voiceRecordTimerUpdate() } @@ -1454,10 +1487,10 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll Log.i("[Chat Message Sending] Max duration for voice recording exceeded, stopping. (max = \(LinphoneManager.instance().lpConfigInt(forKey: "voice_recording_max_duration", withDefault: 59999))") stopVoiceRecording() } else { - recordingDurationTextView.text = ChatConversationViewModel.sharedModel.formattedDuration(Int(linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject))) + contentMessageView.recordingDurationTextView.text = ChatConversationViewModel.sharedModel.formattedDuration(Int(linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject))) UIView.animate(withDuration: 10.0, delay: 0.0, options: [.repeat], animations: { - self.recordingWaveImageMask.transform = CGAffineTransform(translationX: 98, y: 0).scaledBy(x: 0.01, y: 1) + self.contentMessageView.recordingWaveImageMask.transform = CGAffineTransform(translationX: 98, y: 0).scaledBy(x: 0.01, y: 1) }) } @@ -1466,16 +1499,16 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll func stopVoiceRecording() { ChatConversationViewModel.sharedModel.stopVoiceRecording() if (ChatConversationViewModel.sharedModel.voiceRecorder != nil) && linphone_recorder_get_state(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject) == LinphoneRecorderRunning { - recordingDurationTextView.text = ChatConversationViewModel.sharedModel.formattedDuration(Int(linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject))) + contentMessageView.recordingDurationTextView.text = ChatConversationViewModel.sharedModel.formattedDuration(Int(linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject))) } if LinphoneManager.instance().lpConfigBool(forKey: "voice_recording_send_right_away", withDefault: false) { onSendClick() } - recordingStopButton.isHidden = true - recordingPlayButton.isHidden = false + contentMessageView.recordingStopButton.isHidden = true + contentMessageView.recordingPlayButton.isHidden = false - messageView.voiceRecordButton.isSelected = false - recordingWaveImageMask.layer.removeAllAnimations() + contentMessageView.messageView.voiceRecordButton.isSelected = false + contentMessageView.recordingWaveImageMask.layer.removeAllAnimations() setSendButtonState() @@ -1483,10 +1516,10 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll func cancelVoiceRecording() { setRecordingVisible(visible: true) - recordingStopButton.isHidden = false - recordingPlayButton.isHidden = true - recordingWaveImageMask.layer.removeAllAnimations() - messageView.voiceRecordButton.isSelected = false + contentMessageView.recordingStopButton.isHidden = false + contentMessageView.recordingPlayButton.isHidden = true + contentMessageView.recordingWaveImageMask.layer.removeAllAnimations() + contentMessageView.messageView.voiceRecordButton.isSelected = false ChatConversationViewModel.sharedModel.cancelVoiceRecordingVM() @@ -1495,7 +1528,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } func setSendButtonState() { - self.messageView.sendButton.isEnabled = ((ChatConversationViewModel.sharedModel.isPendingVoiceRecord && linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject) > 0) || self.messageView.messageText.text.count > 0 || ChatConversationViewModel.sharedModel.fileContext.count > 0) + self.contentMessageView.messageView.sendButton.isEnabled = ((ChatConversationViewModel.sharedModel.isPendingVoiceRecord && linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject) > 0) || (contentMessageView.messageView.messageText.textColor != UIColor.lightGray && self.contentMessageView.messageView.messageText.text.count > 0) || ChatConversationViewModel.sharedModel.fileContext.count > 0) } func onvrPlayPauseStop() { @@ -1511,15 +1544,15 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } func playRecordedMessage() { - self.recordingWaveImageMask.isHidden = true - self.recordingPlayButton.isHidden = true - self.recordingStopButton.isHidden = false + self.contentMessageView.recordingWaveImageMask.isHidden = true + self.contentMessageView.recordingPlayButton.isHidden = true + self.contentMessageView.recordingStopButton.isHidden = false ChatConversationViewModel.sharedModel.initSharedPlayer() AudioPlayer.sharedModel.fileChanged.value = ChatConversationViewModel.sharedModel.voiceRecorder?.file ChatConversationViewModel.sharedModel.startSharedPlayer(ChatConversationViewModel.sharedModel.voiceRecorder?.file) - recordingWaveView.progress = 0.0 + contentMessageView.recordingWaveView.progress = 0.0 ChatConversationViewModel.sharedModel.isPlayingVoiceRecording = true AudioPlayer.sharedModel.fileChanged.observe { file in @@ -1528,9 +1561,9 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } } - recordingWaveView.progress = 1.0 + contentMessageView.recordingWaveView.progress = 1.0 UIView.animate(withDuration: TimeInterval(Double(AudioPlayer.getSharedPlayer()!.duration) / 1000.00), delay: 0.0, options: .curveLinear, animations: { - self.recordingWaveView.layoutIfNeeded() + self.contentMessageView.recordingWaveView.layoutIfNeeded() }, completion: { (finished: Bool) in if (ChatConversationViewModel.sharedModel.isPlayingVoiceRecording) { self.stopVoiceRecordPlayer() @@ -1539,28 +1572,28 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll } func stopVoiceRecordPlayer() { - recordingView.subviews.forEach({ view in + contentMessageView.recordingView.subviews.forEach({ view in view.removeFromSuperview() }) resetRecordingProgressBar() - self.recordingWaveView.progress = 0.0 - self.recordingWaveView.setProgress(self.recordingWaveView.progress, animated: false) + self.contentMessageView.recordingWaveView.progress = 0.0 + self.contentMessageView.recordingWaveView.setProgress(self.contentMessageView.recordingWaveView.progress, animated: false) ChatConversationViewModel.sharedModel.stopSharedPlayer() - self.recordingWaveImageMask.isHidden = false - self.recordingPlayButton.isHidden = false - self.recordingStopButton.isHidden = true + self.contentMessageView.recordingWaveImageMask.isHidden = false + self.contentMessageView.recordingPlayButton.isHidden = false + self.contentMessageView.recordingStopButton.isHidden = true ChatConversationViewModel.sharedModel.isPlayingVoiceRecording = false } func configureMessageField() { let isOneToOneChat = ChatConversationViewModel.sharedModel.chatRoom!.hasCapability(mask: Int(LinphoneChatRoomCapabilitiesOneToOne.rawValue)) if isOneToOneChat { - messageView.isHidden = false + contentMessageView.messageView.isHidden = false if ChatConversationViewModel.sharedModel.chatRoom!.isReadOnly { ChatConversationViewModel.sharedModel.chatRoom!.addParticipant(addr: (ChatConversationViewModel.sharedModel.chatRoom?.me?.address)!) } } else { - messageView.isHidden = ChatConversationViewModel.sharedModel.chatRoom!.isReadOnly + contentMessageView.messageView.isHidden = ChatConversationViewModel.sharedModel.chatRoom!.isReadOnly } } diff --git a/Classes/Swift/Chat/Views/MessageView.swift b/Classes/Swift/Chat/Views/MessageView.swift index 097ef7fe8..22c75a7d6 100644 --- a/Classes/Swift/Chat/Views/MessageView.swift +++ b/Classes/Swift/Chat/Views/MessageView.swift @@ -82,7 +82,9 @@ class MessageView: UIView, UITextViewDelegate { messageText.matchParentHeight().alignParentLeft().alignParentRight(withMargin: 40).done() messageText.font = UIFont.systemFont(ofSize: 18) messageText.delegate = self - + messageText.textColor = UIColor.lightGray + messageText.text = "Message" + messageText.inputAccessoryView = UIView() messageWithEmojiView.addArrangedSubview(emojisButton) emojisButton.alignParentRight().matchParentHeight().done() @@ -93,38 +95,40 @@ class MessageView: UIView, UITextViewDelegate { } func textViewDidChangeSelection(_ textView: UITextView) { - let chatRoom = ChatRoom.getSwiftObject(cObject: PhoneMainView.instance().currentRoom) - if ((messageText.text.isEmpty && !fileContext) || isLoading) { - sendButton.isEnabled = false - emojisButton.isHidden = false - NotificationCenter.default.post(name: Notification.Name("LinphoneResetTextViewSize"), object: self) - lastNumLines = 0 - } else { - if (messageText.text.trimmingCharacters(in: .whitespacesAndNewlines).unicodeScalars.first?.properties.isEmojiPresentation == true){ - var onlyEmojis = true - messageText.text.trimmingCharacters(in: .whitespacesAndNewlines).unicodeScalars.forEach { emoji in - if !emoji.properties.isEmojiPresentation && !emoji.properties.isWhitespace{ - onlyEmojis = false + if messageText.textColor != UIColor.lightGray { + let chatRoom = ChatRoom.getSwiftObject(cObject: PhoneMainView.instance().currentRoom) + if ((messageText.text.isEmpty && !fileContext) || isLoading) { + sendButton.isEnabled = false + emojisButton.isHidden = false + NotificationCenter.default.post(name: Notification.Name("LinphoneResetTextViewSize"), object: self) + lastNumLines = 0 + } else { + if (messageText.text.trimmingCharacters(in: .whitespacesAndNewlines).unicodeScalars.first?.properties.isEmojiPresentation == true){ + var onlyEmojis = true + messageText.text.trimmingCharacters(in: .whitespacesAndNewlines).unicodeScalars.forEach { emoji in + if !emoji.properties.isEmojiPresentation && !emoji.properties.isWhitespace{ + onlyEmojis = false + } + } + if onlyEmojis { + emojisButton.isHidden = false + } else { + emojisButton.isHidden = true } - } - if onlyEmojis { - emojisButton.isHidden = false } else { emojisButton.isHidden = true } - } else { - emojisButton.isHidden = true - } - if !isComposing { - chatRoom.compose() - let timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { timer in - self.isComposing = false + if !isComposing { + chatRoom.compose() + let timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { timer in + self.isComposing = false + } } } isComposing = true - - sendButton.isEnabled = true + sendButton.isEnabled = true + let numLines = (messageText.contentSize.height / messageText.font!.lineHeight) if(Int(numLines) != Int(lastNumLines)){ NotificationCenter.default.post(name: Notification.Name("LinphoneTextViewSize"), object: self) @@ -132,8 +136,23 @@ class MessageView: UIView, UITextViewDelegate { lastNumLines = numLines } } + + func textViewDidBeginEditing(_ textView: UITextView) { + if messageText.textColor == UIColor.lightGray { + messageText.text = nil + messageText.textColor = VoipTheme.backgroundBlackWhite.get() + } + } + + func textViewDidEndEditing(_ textView: UITextView) { + if messageText.text.isEmpty { + messageText.textColor = UIColor.lightGray + messageText.text = "Message" + } + } } + extension UIView { func setWidth(_ w:CGFloat, animateTime:TimeInterval?=nil) { if let c = self.constraints.first(where: { $0.firstAttribute == .width && $0.relation == .equal }) { diff --git a/Classes/Swift/Util/BackActionsNavigationView.swift b/Classes/Swift/Util/BackActionsNavigationView.swift index 56e2d6f0c..a8e6a085a 100644 --- a/Classes/Swift/Util/BackActionsNavigationView.swift +++ b/Classes/Swift/Util/BackActionsNavigationView.swift @@ -17,70 +17,37 @@ * along with this program. If not, see . */ - import UIKit import Foundation import linphonesw import SnapKit class BackActionsNavigationView: UIViewController { - - - let top_bar_height = 66.0 - let side_buttons_margin = 5 - - let titleLabel = StyledLabel(VoipTheme.chat_conversation_title) + let contentMessageView = ContentMessageView() + + let topBar = UIView() + let top_bar_height = 66.0 + let side_buttons_margin = 5 + + let titleLabel = StyledLabel(VoipTheme.chat_conversation_title) let titleParticipants = UIView() let titleGroupLabel = StyledLabel(VoipTheme.chat_conversation_title) - let participantsGroupLabel = StyledLabel(VoipTheme.chat_conversation_participants) - - let topBar = UIView() - let contentView = UIView() - let isComposingView = UIView() - let isComposingTextView = StyledLabel(VoipTheme.chat_conversation_is_composing_text) - let replyLabelTextView = StyledLabel(VoipTheme.chat_conversation_reply_label) - let replyContentTextView = StyledLabel(VoipTheme.chat_conversation_reply_content) - let replyContentTextSpacing = UIView() - let replyContentForMeetingTextView = StyledLabel(VoipTheme.chat_conversation_reply_content) - let replyDeleteButton = CallControlButton(width: 22, height: 22, buttonTheme:VoipTheme.nav_black_button("reply_cancel")) - let replyMeetingSchedule = UIImageView() - let recordingView = UIView() - let recordingDeleteButton = CallControlButton(width: 40, height: 40, buttonTheme:VoipTheme.nav_button("delete_default")) - let recordingPlayButton = CallControlButton(width: 40, height: 40, buttonTheme:VoipTheme.nav_button("vr_play")) - let recordingStopButton = CallControlButton(width: 40, height: 40, buttonTheme:VoipTheme.nav_button("vr_stop")) - var recordingWaveView = UIProgressView() - let recordingDurationTextView = StyledLabel(VoipTheme.chat_conversation_recording_duration) - let recordingWaveImage = UIImageView(image: UIImage(named: "vr_wave.png")) - let recordingWaveImageMask = UIView() + let participantsGroupLabel = StyledLabel(VoipTheme.chat_conversation_participants) - let recordingPlayerImage = UIView() + var backAction : (() -> Void)? = nil + var action1 : (() -> Void)? = nil + var action2 : (() -> Void)? = nil - let messageView = MessageView() - let mediaSelector = UIView() - let mediaSelectorReply = UIView() - var replyBubble = UIView() - var backgroundReplyColor = UIView() - var backAction : (() -> Void)? = nil - var action1 : (() -> Void)? = nil - var action2 : (() -> Void)? = nil - - let backButton = CallControlButton(buttonTheme:VoipTheme.nav_button("back_default")) + let backButton = CallControlButton(buttonTheme:VoipTheme.nav_button("back_default")) let cancelButton = CallControlButton(buttonTheme:VoipTheme.nav_button("cancel_edit_default")) - let action1Button = CallControlButton(buttonTheme:VoipTheme.nav_button("call_audio_start_default")) + let action1Button = CallControlButton(buttonTheme:VoipTheme.nav_button("call_audio_start_default")) let action1BisButton = CallControlButton(buttonTheme:VoipTheme.nav_button("voip_conference_new")) let action1SelectAllButton = CallControlButton(buttonTheme:VoipTheme.nav_button("select_all_default")) let action1DeselectAllButton = CallControlButton(buttonTheme:VoipTheme.nav_button("deselect_all")) - let action2Button = CallControlButton(buttonTheme:VoipTheme.nav_button("more_menu_default")) + let action2Button = CallControlButton(buttonTheme:VoipTheme.nav_button("more_menu_default")) let action2Delete = CallControlButton(buttonTheme:VoipTheme.nav_button("delete_default")) - var isSecure : Bool = false var isGroupChat : Bool = false - let floatingButton = CallControlButton(buttonTheme:VoipTheme.nav_button("")) - var constraintFloatingButton : NSLayoutConstraint? = nil - var constraintLandscapeFloatingButton : NSLayoutConstraint? = nil - - var stackView = UIStackView() - var stackViewReply = UIStackView() func viewDidLoad(backAction : @escaping () -> Void, action1 : @escaping () -> Void, @@ -157,160 +124,18 @@ class BackActionsNavigationView: UIViewController { super.viewDidLoad() - stackView.axis = .vertical; - stackView.distribution = .fill; - stackView.alignment = .center; - stackView.spacing = 1; - - stackView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(stackView) - - //stackView.alignParentTop().alignParentBottom().matchParentSideBorders().done() - stackView.alignParentTop().alignParentBottom().done() - stackView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true - stackView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true - - stackView.addArrangedSubview(contentView) - contentView.alignParentTop(withMargin: top_bar_height).matchParentSideBorders().done() - - stackView.addArrangedSubview(isComposingView) - isComposingView.height(top_bar_height/2).matchParentSideBorders().done() - isComposingView.isHidden = true - - isComposingView.addSubview(isComposingTextView) - isComposingTextView.alignParentLeft(withMargin: 10).alignParentRight(withMargin: 10).alignParentTop(withMargin: 10).matchParentHeight().done() - isComposingView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() - - stackView.addArrangedSubview(replyBubble) - replyBubble.matchParentSideBorders().maxHeight(top_bar_height*3).done() - replyBubble.translatesAutoresizingMaskIntoConstraints = false - replyBubble.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - replyBubble.isHidden = true - - replyBubble.addSubview(backgroundReplyColor) - backgroundReplyColor.matchParentSideBorders().matchParentHeight().done() - - stackViewReply.axis = .vertical; - stackViewReply.distribution = .fill; - stackViewReply.alignment = .leading; - - replyBubble.addSubview(stackViewReply) - stackViewReply.alignParentLeft(withMargin: 10).alignParentRight(withMargin: 50).alignParentBottom(withMargin: 10).matchParentHeight().wrapContentY().done() - stackViewReply.translatesAutoresizingMaskIntoConstraints = false - - stackViewReply.addArrangedSubview(replyLabelTextView) - replyLabelTextView.height(30).done() - - stackViewReply.addArrangedSubview(replyMeetingSchedule) - replyMeetingSchedule.size(w: 100, h: 40).wrapContentY().done() - replyMeetingSchedule.contentMode = .scaleAspectFit - replyMeetingSchedule.isHidden = true - - stackViewReply.addArrangedSubview(replyContentForMeetingTextView) - replyContentForMeetingTextView.width(100).wrapContentY().done() - replyContentForMeetingTextView.textAlignment = .center - replyContentForMeetingTextView.numberOfLines = 5 - replyContentForMeetingTextView.isHidden = true - - stackViewReply.addArrangedSubview(mediaSelectorReply) - mediaSelectorReply.height(top_bar_height).wrapContentY().alignParentRight(withMargin: 50).done() - mediaSelectorReply.isHidden = true - - stackViewReply.addArrangedSubview(replyContentTextSpacing) - replyContentTextSpacing.height(8 ).wrapContentY().done() - replyContentTextSpacing.isHidden = true - - stackViewReply.addArrangedSubview(replyContentTextView) - replyContentTextView.wrapContentY().done() - replyContentTextView.numberOfLines = 5 - - replyBubble.addSubview(replyDeleteButton) - replyDeleteButton.alignParentRight(withMargin: 15).centerY().done() - - stackView.addArrangedSubview(recordingView) - recordingView.height(top_bar_height).wrapContentY().matchParentSideBorders().done() - recordingView.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - recordingView.isHidden = true - - resetRecordingProgressBar() - - stackView.addArrangedSubview(mediaSelector) - mediaSelector.height(top_bar_height*2).matchParentSideBorders().done() - mediaSelector.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - mediaSelector.isHidden = true - - stackView.addArrangedSubview(messageView) - messageView.alignParentBottom().height(66).matchParentSideBorders().done() - - stackView.translatesAutoresizingMaskIntoConstraints = false; - view.addSubview(stackView) - - view.addSubview(floatingButton) - constraintFloatingButton = floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 3) - constraintLandscapeFloatingButton = floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -56) - if UIDevice.current.orientation.isLandscape { - constraintLandscapeFloatingButton!.isActive = true - } else { - constraintFloatingButton!.isActive = true - } - constraintFloatingButton!.isActive = true - floatingButton.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor, constant: top_bar_height).isActive = true - floatingButton.setImage(UIImage(named:"security_alert_indicator.png"), for: .normal) - floatingButton.imageEdgeInsets = UIEdgeInsets(top: 42, left: 42, bottom: 42, right: 42) - floatingButton.onClickAction = action3 - - stackView.centerXAnchor.constraint(equalTo:self.view.centerXAnchor).isActive = true - stackView.centerYAnchor.constraint(equalTo:self.view.centerYAnchor).isActive = true + view.addSubview(contentMessageView.view) view.bringSubviewToFront(topBar) UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in self.topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() self.titleParticipants.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - self.replyBubble.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - self.recordingView.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - self.mediaSelector.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() - self.isComposingView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() - self.recordingWaveView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() - self.recordingWaveImageMask.backgroundColor = VoipTheme.backgroundWhiteBlack.get() } - - NotificationCenter.default.addObserver(self, selector: #selector(self.rotated), name: UIDevice.orientationDidChangeNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(self.changeSizeOfTextView), name: Notification.Name("LinphoneTextViewSize"), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(self.resetSizeOfTextView), name: Notification.Name("LinphoneResetTextViewSize"), object: nil) } func resetRecordingProgressBar(){ - recordingView.addSubview(recordingDeleteButton) - recordingDeleteButton.alignParentLeft(withMargin: 10).matchParentHeight().done() - recordingView.addSubview(recordingPlayButton) - recordingPlayButton.alignParentRight(withMargin: 10).matchParentHeight().done() - recordingPlayButton.isHidden = true - - recordingView.addSubview(recordingStopButton) - recordingStopButton.alignParentRight(withMargin: 10).matchParentHeight().done() - - let newRecordingWaveView = UIProgressView() - recordingWaveView = newRecordingWaveView - - recordingView.addSubview(recordingWaveView) - recordingWaveView.toRightOf(recordingDeleteButton, withLeftMargin: 10).toLeftOf(recordingStopButton, withRightMargin: 10).alignParentTop(withMargin: 10).alignParentBottom(withMargin: 10).done() - recordingWaveView.progressViewStyle = .bar - recordingWaveView.layer.cornerRadius = 5 - recordingWaveView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() - recordingWaveView.progressImage = UIImage.withColor(UIColor("L")) - recordingWaveView.clipsToBounds = true - - recordingWaveView.addSubview(recordingDurationTextView) - recordingDurationTextView.alignParentRight(withMargin: 10).matchParentHeight().done() - - recordingWaveView.addSubview(recordingWaveImage) - recordingWaveImage.alignParentTop(withMargin: 10).alignParentBottom(withMargin: 10).alignParentLeft(withMargin: 10).alignParentRight(withMargin: 65).done() - - recordingWaveView.addSubview(recordingWaveImageMask) - recordingWaveImageMask.alignParentTop(withMargin: 5).alignParentBottom(withMargin: 5).alignParentLeft(withMargin: 10).alignParentRight(withMargin: 65).done() - recordingWaveImageMask.backgroundColor = VoipTheme.backgroundWhiteBlack.get() } override func viewWillAppear(_ animated: Bool) { @@ -318,50 +143,6 @@ class BackActionsNavigationView: UIViewController { topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() } - deinit { - NotificationCenter.default.removeObserver(self) - } - - @objc func rotated() { - if UIDevice.current.orientation.isLandscape { - constraintLandscapeFloatingButton!.isActive = true - constraintFloatingButton!.isActive = false - } else { - constraintLandscapeFloatingButton!.isActive = false - constraintFloatingButton!.isActive = true - } - } - - func changeTitle(titleString: String){ - titleLabel.text = titleString - titleGroupLabel.text = titleString - } - - func changeSecureLevel(secureLevel: Bool, imageBadge: UIImage?){ - isSecure = secureLevel - if(isSecure){ - floatingButton.isHidden = false - floatingButton.setImage(imageBadge, for: .normal) - }else{ - floatingButton.isHidden = true - } - } - - func changeCallIcon(groupChat: Bool){ - isGroupChat = groupChat - let defaultAccount = Core.getSwiftObject(cObject: LinphoneManager.getLc()).defaultAccount - if(groupChat && (defaultAccount != nil) && (defaultAccount!.params!.audioVideoConferenceFactoryAddress != nil)){ - action1Button.isHidden = true - action1BisButton.isHidden = false - }else if(groupChat){ - action1Button.isHidden = true - action1BisButton.isHidden = true - }else{ - action1Button.isHidden = false - action1BisButton.isHidden = true - } - } - func editModeOn(){ backButton.isHidden = true cancelButton.isHidden = false @@ -384,6 +165,21 @@ class BackActionsNavigationView: UIViewController { changeCallIcon(groupChat: isGroupChat) } + func changeCallIcon(groupChat: Bool){ + isGroupChat = groupChat + let defaultAccount = Core.getSwiftObject(cObject: LinphoneManager.getLc()).defaultAccount + if(groupChat && (defaultAccount != nil) && (defaultAccount!.params!.audioVideoConferenceFactoryAddress != nil)){ + action1Button.isHidden = true + action1BisButton.isHidden = false + }else if(groupChat){ + action1Button.isHidden = true + action1BisButton.isHidden = true + }else{ + action1Button.isHidden = false + action1BisButton.isHidden = true + } + } + func selectDeselectAll(){ if(action1SelectAllButton.isHidden){ action1SelectAllButton.isHidden = false @@ -396,21 +192,13 @@ class BackActionsNavigationView: UIViewController { } } + func changeTitle(titleString: String){ + titleLabel.text = titleString + titleGroupLabel.text = titleString + } + func deleteSelected(){ } - - @objc func changeSizeOfTextView(){ - let numLines = (messageView.messageText.contentSize.height / messageView.messageText.font!.lineHeight) - if numLines >= 3 && numLines <= 6 { - messageView.setHeight(33*numLines - 33) - } else if numLines < 3 { - messageView.setHeight(66) - } - } - - @objc func resetSizeOfTextView(){ - messageView.setHeight(66) - } } extension UIView { diff --git a/Classes/Swift/Util/ContentMessageView.swift b/Classes/Swift/Util/ContentMessageView.swift new file mode 100644 index 000000000..34c63c7d6 --- /dev/null +++ b/Classes/Swift/Util/ContentMessageView.swift @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-iphone + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import UIKit + +class ContentMessageView: UIViewController { + var message_height = 66.0 + let top_bar_height = 66.0 + let contentView = UIView() + let isComposingView = UIView() + let isComposingTextView = StyledLabel(VoipTheme.chat_conversation_is_composing_text) + let replyLabelTextView = StyledLabel(VoipTheme.chat_conversation_reply_label) + let replyContentTextView = StyledLabel(VoipTheme.chat_conversation_reply_content) + let replyContentTextSpacing = UIView() + let replyContentForMeetingTextView = StyledLabel(VoipTheme.chat_conversation_reply_content) + let replyDeleteButton = CallControlButton(width: 22, height: 22, buttonTheme:VoipTheme.nav_black_button("reply_cancel")) + let replyMeetingSchedule = UIImageView() + let recordingView = UIView() + let recordingDeleteButton = CallControlButton(width: 40, height: 40, buttonTheme:VoipTheme.nav_button("delete_default")) + let recordingPlayButton = CallControlButton(width: 40, height: 40, buttonTheme:VoipTheme.nav_button("vr_play")) + let recordingStopButton = CallControlButton(width: 40, height: 40, buttonTheme:VoipTheme.nav_button("vr_stop")) + var recordingWaveView = UIProgressView() + let recordingDurationTextView = StyledLabel(VoipTheme.chat_conversation_recording_duration) + let recordingWaveImage = UIImageView(image: UIImage(named: "vr_wave.png")) + let recordingWaveImageMask = UIView() + + let recordingPlayerImage = UIView() + + let messageView = MessageView() + let mediaSelector = UIView() + let mediaSelectorReply = UIView() + var replyBubble = UIView() + var backgroundReplyColor = UIView() + + var isSecure : Bool = false + let floatingButton = CallControlButton(buttonTheme:VoipTheme.nav_button("")) + var constraintFloatingButton : NSLayoutConstraint? = nil + var constraintLandscapeFloatingButton : NSLayoutConstraint? = nil + + var stackView = UIStackView() + var stackViewReply = UIStackView() + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + + stackView.axis = .vertical; + stackView.distribution = .fill; + stackView.alignment = .center; + stackView.spacing = 1; + + stackView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(stackView) + + let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first + if keyWindow != nil { + stackView.alignParentTop().alignParentBottom(withMargin: keyWindow!.safeAreaInsets.bottom/2).done() + }else{ + stackView.alignParentTop().alignParentBottom().done() + } + + stackView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true + stackView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true + + stackView.addArrangedSubview(contentView) + contentView.alignParentTop(withMargin: top_bar_height).matchParentSideBorders().done() + + stackView.addArrangedSubview(isComposingView) + isComposingView.height(top_bar_height/2).matchParentSideBorders().done() + isComposingView.isHidden = true + + isComposingView.addSubview(isComposingTextView) + isComposingTextView.alignParentLeft(withMargin: 10).alignParentRight(withMargin: 10).alignParentTop(withMargin: 10).matchParentHeight().done() + isComposingView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + + stackView.addArrangedSubview(replyBubble) + replyBubble.matchParentSideBorders().maxHeight(top_bar_height*3).done() + replyBubble.translatesAutoresizingMaskIntoConstraints = false + replyBubble.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + replyBubble.isHidden = true + + replyBubble.addSubview(backgroundReplyColor) + backgroundReplyColor.matchParentSideBorders().matchParentHeight().done() + + stackViewReply.axis = .vertical; + stackViewReply.distribution = .fill; + stackViewReply.alignment = .leading; + + replyBubble.addSubview(stackViewReply) + stackViewReply.alignParentLeft(withMargin: 10).alignParentRight(withMargin: 50).alignParentBottom(withMargin: 10).matchParentHeight().wrapContentY().done() + stackViewReply.translatesAutoresizingMaskIntoConstraints = false + + stackViewReply.addArrangedSubview(replyLabelTextView) + replyLabelTextView.height(30).done() + + stackViewReply.addArrangedSubview(replyMeetingSchedule) + replyMeetingSchedule.size(w: 100, h: 40).wrapContentY().done() + replyMeetingSchedule.contentMode = .scaleAspectFit + replyMeetingSchedule.isHidden = true + + stackViewReply.addArrangedSubview(replyContentForMeetingTextView) + replyContentForMeetingTextView.width(100).wrapContentY().done() + replyContentForMeetingTextView.textAlignment = .center + replyContentForMeetingTextView.numberOfLines = 5 + replyContentForMeetingTextView.isHidden = true + + stackViewReply.addArrangedSubview(mediaSelectorReply) + mediaSelectorReply.height(top_bar_height).wrapContentY().alignParentRight(withMargin: 50).done() + mediaSelectorReply.isHidden = true + + stackViewReply.addArrangedSubview(replyContentTextSpacing) + replyContentTextSpacing.height(8 ).wrapContentY().done() + replyContentTextSpacing.isHidden = true + + stackViewReply.addArrangedSubview(replyContentTextView) + replyContentTextView.wrapContentY().done() + replyContentTextView.numberOfLines = 5 + + replyBubble.addSubview(replyDeleteButton) + replyDeleteButton.alignParentRight(withMargin: 15).centerY().done() + + stackView.addArrangedSubview(recordingView) + recordingView.height(top_bar_height).wrapContentY().matchParentSideBorders().done() + recordingView.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + recordingView.isHidden = true + + resetRecordingProgressBar() + + stackView.addArrangedSubview(mediaSelector) + mediaSelector.height(top_bar_height*2).matchParentSideBorders().done() + mediaSelector.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + mediaSelector.isHidden = true + + stackView.addArrangedSubview(messageView) + if keyWindow != nil { + message_height = 66 - ((keyWindow!.safeAreaInsets.bottom/2)/2) + } + + messageView.alignParentBottom().height(message_height).matchParentSideBorders().done() + + stackView.translatesAutoresizingMaskIntoConstraints = false; + view.addSubview(stackView) + + view.addSubview(floatingButton) + constraintFloatingButton = floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 3) + constraintLandscapeFloatingButton = floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -56) + if UIDevice.current.orientation.isLandscape { + constraintLandscapeFloatingButton!.isActive = true + } else if UIDevice.current.orientation.isPortrait { + constraintFloatingButton!.isActive = true + } + floatingButton.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor, constant: top_bar_height).isActive = true + floatingButton.setImage(UIImage(named:"security_alert_indicator.png"), for: .normal) + floatingButton.imageEdgeInsets = UIEdgeInsets(top: 42, left: 42, bottom: 42, right: 42) + + stackView.centerXAnchor.constraint(equalTo:self.view.centerXAnchor).isActive = true + stackView.centerYAnchor.constraint(equalTo:self.view.centerYAnchor).isActive = true + + self.dismissKeyboard() + + NotificationCenter.default.addObserver(self, selector: #selector(self.rotated), name: UIDevice.orientationDidChangeNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(self.changeSizeOfTextView), name: Notification.Name("LinphoneTextViewSize"), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(self.resetSizeOfTextView), name: Notification.Name("LinphoneResetTextViewSize"), object: nil) + + UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in + self.replyBubble.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + self.recordingView.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + self.mediaSelector.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + self.isComposingView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + self.recordingWaveView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + self.recordingWaveImageMask.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + } + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + + func resetRecordingProgressBar(){ + recordingView.addSubview(recordingDeleteButton) + recordingDeleteButton.alignParentLeft(withMargin: 10).matchParentHeight().done() + + recordingView.addSubview(recordingPlayButton) + recordingPlayButton.alignParentRight(withMargin: 10).matchParentHeight().done() + recordingPlayButton.isHidden = true + + recordingView.addSubview(recordingStopButton) + recordingStopButton.alignParentRight(withMargin: 10).matchParentHeight().done() + + let newRecordingWaveView = UIProgressView() + recordingWaveView = newRecordingWaveView + + recordingView.addSubview(recordingWaveView) + recordingWaveView.toRightOf(recordingDeleteButton, withLeftMargin: 10).toLeftOf(recordingStopButton, withRightMargin: 10).alignParentTop(withMargin: 10).alignParentBottom(withMargin: 10).done() + recordingWaveView.progressViewStyle = .bar + recordingWaveView.layer.cornerRadius = 5 + recordingWaveView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + recordingWaveView.progressImage = UIImage.withColor(UIColor("L")) + recordingWaveView.clipsToBounds = true + + recordingWaveView.addSubview(recordingDurationTextView) + recordingDurationTextView.alignParentRight(withMargin: 10).matchParentHeight().done() + + recordingWaveView.addSubview(recordingWaveImage) + recordingWaveImage.alignParentTop(withMargin: 10).alignParentBottom(withMargin: 10).alignParentLeft(withMargin: 10).alignParentRight(withMargin: 65).done() + + recordingWaveView.addSubview(recordingWaveImageMask) + recordingWaveImageMask.alignParentTop(withMargin: 5).alignParentBottom(withMargin: 5).alignParentLeft(withMargin: 10).alignParentRight(withMargin: 65).done() + recordingWaveImageMask.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + } + + @objc func rotated() { + if UIDevice.current.orientation.isLandscape { + constraintLandscapeFloatingButton!.isActive = true + constraintFloatingButton!.isActive = false + } else if UIDevice.current.orientation.isPortrait { + constraintLandscapeFloatingButton!.isActive = false + constraintFloatingButton!.isActive = true + } + } + + @objc func changeSizeOfTextView(){ + let numLines = (messageView.messageText.contentSize.height / messageView.messageText.font!.lineHeight) + if numLines >= 2 && numLines <= 6 { + messageView.setHeight((message_height * numLines)/2) + } else if numLines < 2 { + messageView.setHeight(message_height) + } + } + + @objc func resetSizeOfTextView(){ + messageView.setHeight(message_height) + } + + func dismissKeyboard() { + let tap: UITapGestureRecognizer = UITapGestureRecognizer( target: self, action: #selector(self.dismissKeyboardTouchOutside)) + tap.cancelsTouchesInView = false + view.addGestureRecognizer(tap) + } + + @objc private func dismissKeyboardTouchOutside() { + view.endEditing(true) + } + + func changeSecureLevel(secureLevel: Bool, imageBadge: UIImage?){ + isSecure = secureLevel + if(isSecure){ + floatingButton.isHidden = false + floatingButton.setImage(imageBadge, for: .normal) + }else{ + floatingButton.isHidden = true + } + } +} diff --git a/Classes/Swift/Voip/Theme/VoipTheme.swift b/Classes/Swift/Voip/Theme/VoipTheme.swift index ef507964c..ba2f56084 100644 --- a/Classes/Swift/Voip/Theme/VoipTheme.swift +++ b/Classes/Swift/Voip/Theme/VoipTheme.swift @@ -68,6 +68,7 @@ import UIKit static let voipBackgroundColor = LightDarkColor(voip_gray_blue_color,voip_dark_color) @objc static let voipBackgroundBWColor = LightDarkColor(.white,voip_dark_color) @objc static let backgroundWhiteBlack = LightDarkColor(.white,.black) + @objc static let backgroundBlackWhite = LightDarkColor(.black,.white) static let voipParticipantBackgroundColor = LightDarkColor(voip_gray_background,voip_dark_color2) static let voipParticipantMeBackgroundColor = LightDarkColor(voip_dark_color3,voip_dark_color3) static let voipExtraButtonsBackgroundColor = LightDarkColor(voip_gray,voip_dark_color3) diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj index 2a0711bca..34e916fdd 100644 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -954,6 +954,7 @@ D779D39E29AC9E93007B8087 /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D779D39D29AC9E92007B8087 /* AudioPlayer.swift */; }; D779D3A229B5E365007B8087 /* UIImageExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D779D3A129B5E365007B8087 /* UIImageExtension.swift */; }; D780FF7D2A459CE3001535E6 /* MediaViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D780FF7C2A459CE3001535E6 /* MediaViewer.swift */; }; + D783D9BA2A669A9E00293E87 /* ContentMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D783D9B92A669A9E00293E87 /* ContentMessageView.swift */; }; D7A4C0082A3B135800EFBD1B /* new_chat_attachment_default.png in Resources */ = {isa = PBXBuildFile; fileRef = D7A4C0052A3B135800EFBD1B /* new_chat_attachment_default.png */; }; D7A4C0092A3B135800EFBD1B /* new_vr_off.png in Resources */ = {isa = PBXBuildFile; fileRef = D7A4C0062A3B135800EFBD1B /* new_vr_off.png */; }; D7A4C00A2A3B135800EFBD1B /* new_chat_send_default.png in Resources */ = {isa = PBXBuildFile; fileRef = D7A4C0072A3B135800EFBD1B /* new_chat_send_default.png */; }; @@ -2202,6 +2203,7 @@ D779D39D29AC9E92007B8087 /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = ""; }; D779D3A129B5E365007B8087 /* UIImageExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = ""; }; D780FF7C2A459CE3001535E6 /* MediaViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaViewer.swift; sourceTree = ""; }; + D783D9B92A669A9E00293E87 /* ContentMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMessageView.swift; sourceTree = ""; }; D7A4C0052A3B135800EFBD1B /* new_chat_attachment_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = new_chat_attachment_default.png; sourceTree = ""; }; D7A4C0062A3B135800EFBD1B /* new_vr_off.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = new_vr_off.png; sourceTree = ""; }; D7A4C0072A3B135800EFBD1B /* new_chat_send_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = new_chat_send_default.png; sourceTree = ""; }; @@ -3479,6 +3481,7 @@ D7A7544F29507038005C9D4A /* CustomAlertController.swift */, D779D39D29AC9E92007B8087 /* AudioPlayer.swift */, D779D3A129B5E365007B8087 /* UIImageExtension.swift */, + D783D9B92A669A9E00293E87 /* ContentMessageView.swift */, ); path = Util; sourceTree = ""; @@ -5028,6 +5031,7 @@ 1D60589B0D05DD56006BFB54 /* main.m in Sources */, C63F725C285A24B10066163B /* IncomingCallView.swift in Sources */, C63F726B285A24B10066163B /* ButtonWithStateBackgrounds.swift in Sources */, + D783D9BA2A669A9E00293E87 /* ContentMessageView.swift in Sources */, C63F7218285A24B10066163B /* ScheduledConferencesCell.swift in Sources */, C63F722E285A24B10066163B /* IceState.swift in Sources */, 6135761C240E81BB005304D4 /* UIInterfaceStyleButton.m in Sources */,