From d54e71bb1c8f7e8302b8a5f1b59d391ac977ba10 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 18 Jul 2023 17:08:31 +0200 Subject: [PATCH] Fix Message View --- .../ChatConversationTableViewSwift.swift | 6 +- .../Views/ChatConversationViewSwift.swift | 293 ++++++++++-------- Classes/Swift/Chat/Views/MessageView.swift | 69 +++-- .../Util/BackActionsNavigationView.swift | 282 +++-------------- Classes/Swift/Util/ContentMessageView.swift | 64 +++- Classes/Swift/Voip/Theme/VoipTheme.swift | 1 + linphone.xcodeproj/project.pbxproj | 4 + 7 files changed, 299 insertions(+), 420 deletions(-) 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 e34de9b24..23fb1df7d 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) } @@ -274,31 +277,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() @@ -333,6 +338,8 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll */ field.isUserInteractionEnabled = true + + IQKeyboardManager.shared().isEnabled = false } override func viewDidDisappear(_ animated: Bool) { @@ -343,32 +350,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() { @@ -553,7 +560,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 } } @@ -592,7 +599,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) } @@ -794,14 +801,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() @@ -815,8 +829,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) @@ -835,29 +849,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) @@ -865,9 +879,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 } @@ -895,7 +922,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 != "" { @@ -903,23 +930,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 }) } @@ -927,18 +954,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() @@ -948,17 +975,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) @@ -979,22 +1006,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 }) } @@ -1097,14 +1124,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 @@ -1113,7 +1140,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") @@ -1142,7 +1169,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() } @@ -1315,23 +1342,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 @@ -1363,7 +1390,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 { @@ -1392,8 +1419,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() @@ -1413,10 +1440,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 { @@ -1425,7 +1452,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 @@ -1434,18 +1461,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() } @@ -1457,10 +1490,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) }) } @@ -1469,16 +1502,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() @@ -1486,10 +1519,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() @@ -1498,7 +1531,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() { @@ -1514,15 +1547,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 @@ -1531,9 +1564,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() @@ -1542,28 +1575,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 index f8550c65c..34c63c7d6 100644 --- a/Classes/Swift/Util/ContentMessageView.swift +++ b/Classes/Swift/Util/ContentMessageView.swift @@ -1,15 +1,27 @@ -// -// TopBarNavigationView.swift -// linphone -// -// Created by BenoƮt Martins on 18/07/2023. -// +/* + * 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) @@ -46,6 +58,9 @@ class ContentMessageView: UIViewController { override func viewDidLoad() { super.viewDidLoad() + + view.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() + stackView.axis = .vertical; stackView.distribution = .fill; stackView.alignment = .center; @@ -54,8 +69,13 @@ class ContentMessageView: UIViewController { stackView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stackView) - //stackView.alignParentTop().alignParentBottom().matchParentSideBorders().done() - stackView.alignParentTop().alignParentBottom().done() + 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 @@ -129,7 +149,11 @@ class ContentMessageView: UIViewController { mediaSelector.isHidden = true stackView.addArrangedSubview(messageView) - messageView.alignParentBottom().height(66).matchParentSideBorders().done() + if keyWindow != nil { + message_height = 66 - ((keyWindow!.safeAreaInsets.bottom/2)/2) + } + + messageView.alignParentBottom().height(message_height).matchParentSideBorders().done() stackView.translatesAutoresizingMaskIntoConstraints = false; view.addSubview(stackView) @@ -149,6 +173,7 @@ class ContentMessageView: UIViewController { 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) @@ -213,17 +238,26 @@ class ContentMessageView: UIViewController { @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) + if numLines >= 2 && numLines <= 6 { + messageView.setHeight((message_height * numLines)/2) + } else if numLines < 2 { + messageView.setHeight(message_height) } } @objc func resetSizeOfTextView(){ - messageView.setHeight(66) + 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 diff --git a/Classes/Swift/Voip/Theme/VoipTheme.swift b/Classes/Swift/Voip/Theme/VoipTheme.swift index cd4b7443c..79cb96cf2 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 5deb6e25b..ba20c2b64 100644 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -961,6 +961,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 */; }; @@ -2215,6 +2216,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 = ""; }; @@ -3523,6 +3525,7 @@ D7A7544F29507038005C9D4A /* CustomAlertController.swift */, D779D39D29AC9E92007B8087 /* AudioPlayer.swift */, D779D3A129B5E365007B8087 /* UIImageExtension.swift */, + D783D9B92A669A9E00293E87 /* ContentMessageView.swift */, ); path = Util; sourceTree = ""; @@ -4968,6 +4971,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 */,