Fix Message View

This commit is contained in:
Benoit Martins 2023-07-18 17:08:31 +02:00
parent bf539b8743
commit c2c8e014a7
7 changed files with 521 additions and 405 deletions

View file

@ -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)
}

View file

@ -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
}
}

View file

@ -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 }) {

View file

@ -17,70 +17,37 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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 {

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
}
}

View file

@ -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)

View file

@ -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 = "<group>"; };
D779D3A129B5E365007B8087 /* UIImageExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = "<group>"; };
D780FF7C2A459CE3001535E6 /* MediaViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaViewer.swift; sourceTree = "<group>"; };
D783D9B92A669A9E00293E87 /* ContentMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMessageView.swift; sourceTree = "<group>"; };
D7A4C0052A3B135800EFBD1B /* new_chat_attachment_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = new_chat_attachment_default.png; sourceTree = "<group>"; };
D7A4C0062A3B135800EFBD1B /* new_vr_off.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = new_vr_off.png; sourceTree = "<group>"; };
D7A4C0072A3B135800EFBD1B /* new_chat_send_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = new_chat_send_default.png; sourceTree = "<group>"; };
@ -3479,6 +3481,7 @@
D7A7544F29507038005C9D4A /* CustomAlertController.swift */,
D779D39D29AC9E92007B8087 /* AudioPlayer.swift */,
D779D3A129B5E365007B8087 /* UIImageExtension.swift */,
D783D9B92A669A9E00293E87 /* ContentMessageView.swift */,
);
path = Util;
sourceTree = "<group>";
@ -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 */,