From da9d90e368f6e2c8de140cba7fa56d57fc513f6c Mon Sep 17 00:00:00 2001 From: "benoit.martins" Date: Tue, 13 Feb 2024 17:04:36 +0100 Subject: [PATCH] Add chat room callbacks --- Linphone/Contacts/ContactsManager.swift | 7 +- Linphone/Localizable.xcstrings | 6 - .../Fragments/ConversationsListFragment.swift | 41 ++--- .../ConversationsListViewModel.swift | 167 +++++++++++++----- 4 files changed, 145 insertions(+), 76 deletions(-) diff --git a/Linphone/Contacts/ContactsManager.swift b/Linphone/Contacts/ContactsManager.swift index 6808a6b49..91af15221 100644 --- a/Linphone/Contacts/ContactsManager.swift +++ b/Linphone/Contacts/ContactsManager.swift @@ -295,10 +295,13 @@ final class ContactsManager: ObservableObject { } func getFriendWithAddress(address: Address) -> Friend? { + let clonedAddress = address.clone() + clonedAddress!.clean() + let sipUri = clonedAddress!.asStringUriOnly() if friendList != nil { - var friend = friendList!.friends.first(where: {$0.addresses.contains(where: {$0.asStringUriOnly() == address.asStringUriOnly()})}) + var friend = friendList!.friends.first(where: {$0.addresses.contains(where: {$0.asStringUriOnly() == sipUri})}) if friend == nil { - friend = linphoneFriendList!.friends.first(where: {$0.addresses.contains(where: {$0.asStringUriOnly() == address.asStringUriOnly()})}) + friend = linphoneFriendList!.friends.first(where: {$0.addresses.contains(where: {$0.asStringUriOnly() == sipUri})}) } return friend } else { diff --git a/Linphone/Localizable.xcstrings b/Linphone/Localizable.xcstrings index 279f2ae7b..750aa39b8 100644 --- a/Linphone/Localizable.xcstrings +++ b/Linphone/Localizable.xcstrings @@ -244,9 +244,6 @@ }, "Contacts" : { - }, - "Content" : { - }, "Continue" : { @@ -573,9 +570,6 @@ }, "This contact will be deleted definitively." : { - }, - "Title" : { - }, "TLS" : { diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift index 38b047733..c582fea2a 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift @@ -44,7 +44,6 @@ struct ConversationsListFragment: View { }) : ContactAvatarModel(friend: nil, withPresence: false) - if LinphoneUtils.isChatRoomAGroup(chatRoom: conversationsListViewModel.conversationsList[index]) { Image(uiImage: contactsManager.textToImage( firstName: conversationsListViewModel.conversationsList[index].subject!, @@ -117,7 +116,8 @@ struct ConversationsListFragment: View { .frame(maxWidth: .infinity, alignment: .leading) .lineLimit(1) } else { - if conversationsListViewModel.conversationsList[index].participants.first != nil && conversationsListViewModel.conversationsList[index].participants.first!.address != nil { + if conversationsListViewModel.conversationsList[index].participants.first != nil + && conversationsListViewModel.conversationsList[index].participants.first!.address != nil { Text(conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName != nil ? conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName! : conversationsListViewModel.conversationsList[index].participants.first!.address!.username!) @@ -131,16 +131,18 @@ struct ConversationsListFragment: View { } } - let text = conversationsListViewModel.conversationsList[index].lastMessageInHistory?.contents.first(where: {$0.isText == true})?.utf8Text ?? "" - - Text(text) - .foregroundStyle(Color.grayMain2c400) - .if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in - view.default_text_style_700(styleSize: 14) - } - .default_text_style(styleSize: 14) - .frame(maxWidth: .infinity, alignment: .leading) - .lineLimit(1) + Text( + conversationsListViewModel.conversationsList[index].lastMessageInHistory != nil + ? conversationsListViewModel.getContentTextMessage(message: conversationsListViewModel.conversationsList[index].lastMessageInHistory!) + : "" + ) + .foregroundStyle(Color.grayMain2c400) + .if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in + view.default_text_style_700(styleSize: 14) + } + .default_text_style(styleSize: 14) + .frame(maxWidth: .infinity, alignment: .leading) + .lineLimit(1) Spacer() } @@ -160,17 +162,10 @@ struct ConversationsListFragment: View { .frame(width: 18, height: 18, alignment: .trailing) } - if conversationsListViewModel.conversationsList[index].lastMessageInHistory != nil { - Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastMessageInHistory!.time)) - .foregroundStyle(Color.grayMain2c400) - .default_text_style(styleSize: 14) - .lineLimit(1) - } else { - Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastUpdateTime)) - .foregroundStyle(Color.grayMain2c400) - .default_text_style(styleSize: 14) - .lineLimit(1) - } + Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastUpdateTime)) + .foregroundStyle(Color.grayMain2c400) + .default_text_style(styleSize: 14) + .lineLimit(1) } Spacer() diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift index 8b7bac6c6..5d4e1633d 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift @@ -19,17 +19,21 @@ import Foundation import linphonesw +import Combine class ConversationsListViewModel: ObservableObject { private var coreContext = CoreContext.shared + private var contactsManager = ContactsManager.shared + + private var mCoreSuscriptions = Set() @Published var conversationsList: [ChatRoom] = [] @Published var unreadMessages: Int = 0 init() { computeChatRoomsList(filter: "") - updateUnreadMessagesCount() + addConversationDelegate() } func computeChatRoomsList(filter: String) { @@ -37,43 +41,128 @@ class ConversationsListViewModel: ObservableObject { let account = core.defaultAccount let chatRooms = account?.chatRooms != nil ? account!.chatRooms : core.chatRooms - chatRooms.forEach { chatRoom in - //let disabledBecauseNotSecured = (account?.isInSecureMode() == true && !chatRoom.hasCapability) ? Capabilities.Encrypted.toInt() : 0 + DispatchQueue.main.async { + self.conversationsList = [] + chatRooms.forEach { chatRoom in + //let disabledBecauseNotSecured = (account?.isInSecureMode() == true && !chatRoom.hasCapability) ? Capabilities.Encrypted.toInt() : 0 + + if filter.isEmpty { + //val model = ConversationModel(chatRoom, disabledBecauseNotSecured) + self.conversationsList.append(chatRoom) + } + /* + else { + val participants = chatRoom.participants + val found = participants.find { + // Search in address but also in contact name if exists + val model = + coreContext.contactsManager.getContactAvatarModelForAddress(it.address) + model.contactName?.contains( + filter, + ignoreCase = true + ) == true || it.address.asStringUriOnly().contains( + filter, + ignoreCase = true + ) + } + if ( + found != null || + chatRoom.peerAddress.asStringUriOnly().contains(filter, ignoreCase = true) || + chatRoom.subject.orEmpty().contains(filter, ignoreCase = true) + ) { + val model = ConversationModel(chatRoom, disabledBecauseNotSecured) + list.add(model) + count += 1 + } + } + */ + } - if filter.isEmpty { - //val model = ConversationModel(chatRoom, disabledBecauseNotSecured) - self.conversationsList.append(chatRoom) - } - /* - else { - val participants = chatRoom.participants - val found = participants.find { - // Search in address but also in contact name if exists - val model = - coreContext.contactsManager.getContactAvatarModelForAddress(it.address) - model.contactName?.contains( - filter, - ignoreCase = true - ) == true || it.address.asStringUriOnly().contains( - filter, - ignoreCase = true - ) - } - if ( - found != null || - chatRoom.peerAddress.asStringUriOnly().contains(filter, ignoreCase = true) || - chatRoom.subject.orEmpty().contains(filter, ignoreCase = true) - ) { - val model = ConversationModel(chatRoom, disabledBecauseNotSecured) - list.add(model) - count += 1 - } - } - */ + self.updateUnreadMessagesCount() } } } + func addConversationDelegate() { + coreContext.doOnCoreQueue { core in + self.mCoreSuscriptions.insert(core.publisher?.onChatRoomStateChanged?.postOnMainQueue { (cbValue: (_: Core, chatRoom: ChatRoom, state: ChatRoom.State)) in + //Log.info("[ConversationsListViewModel] Conversation [${LinphoneUtils.getChatRoomId(chatRoom)}] state changed [$state]") + switch cbValue.state { + case ChatRoom.State.Created: + self.computeChatRoomsList(filter: "") + case ChatRoom.State.Deleted: + self.computeChatRoomsList(filter: "") + //ToastViewModel.shared.toastMessage = "toast_conversation_deleted" + //ToastViewModel.shared.displayToast = true + default: + break + } + }) + + self.mCoreSuscriptions.insert(core.publisher?.onMessageSent?.postOnMainQueue { _ in + self.reorderChatRooms() + }) + + self.mCoreSuscriptions.insert(core.publisher?.onMessagesReceived?.postOnMainQueue { _ in + self.reorderChatRooms() + }) + } + } + + func reorderChatRooms() { + Log.info("[ConversationsListViewModel] Re-ordering conversations") + var sortedList: [ChatRoom] = [] + sortedList.append(contentsOf: conversationsList) + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + self.conversationsList = sortedList.sorted { $0.lastUpdateTime > $1.lastUpdateTime } + } + + updateUnreadMessagesCount() + } + + func updateUnreadMessagesCount() { + coreContext.doOnCoreQueue { core in + let account = core.defaultAccount + if account != nil { + let count = account?.unreadChatMessageCount != nil ? account!.unreadChatMessageCount : core.unreadChatMessageCount + + DispatchQueue.main.async { + self.unreadMessages = count + } + } else { + DispatchQueue.main.async { + self.unreadMessages = 0 + } + } + } + } + + func getContentTextMessage(message: ChatMessage) -> String { + var fromAddressFriend = message.fromAddress != nil + ? contactsManager.getFriendWithAddress(address: message.fromAddress!)?.name ?? nil + : nil + + if !message.isOutgoing && message.chatRoom != nil && !message.chatRoom!.hasCapability(mask: ChatRoom.Capabilities.OneToOne.rawValue) { + if fromAddressFriend == nil { + if message.fromAddress!.displayName != nil { + fromAddressFriend = message.fromAddress!.displayName! + ": " + } else if message.fromAddress!.username != nil { + fromAddressFriend = message.fromAddress!.username! + ": " + } else { + fromAddressFriend = "" + } + } else { + fromAddressFriend! += ": " + } + + } else { + fromAddressFriend = nil + } + + return (fromAddressFriend ?? "") + (message.contents.first(where: {$0.isText == true})?.utf8Text ?? (message.contents.first(where: {$0.isFile == true || $0.isFileTransfer == true})?.name ?? "")) + } + func getCallTime(startDate: time_t) -> String { let timeInterval = TimeInterval(startDate) @@ -97,16 +186,4 @@ class ConversationsListViewModel: ObservableObject { return formatter.string(from: myNSDate) } } - - func updateUnreadMessagesCount() { - coreContext.doOnCoreQueue { core in - let account = core.defaultAccount - if account != nil { - let count = account?.unreadChatMessageCount != nil ? account!.unreadChatMessageCount : core.unreadChatMessageCount - self.unreadMessages = count - } else { - self.unreadMessages = 0 - } - } - } }