diff --git a/Linphone/Contacts/ContactsManager.swift b/Linphone/Contacts/ContactsManager.swift index 2c8246828..c624f58a1 100644 --- a/Linphone/Contacts/ContactsManager.swift +++ b/Linphone/Contacts/ContactsManager.swift @@ -100,6 +100,7 @@ final class ContactsManager: ObservableObject { CNContactOrganizationNameKey, CNContactImageDataAvailableKey, CNContactImageDataKey, CNContactThumbnailImageDataKey] let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor]) do { + var contactCounter = 0 try store.enumerateContacts(with: request, usingBlock: { (contact, _) in DispatchQueue.main.sync { let newContact = Contact( @@ -109,7 +110,7 @@ final class ContactsManager: ObservableObject { organizationName: contact.organizationName, jobTitle: "", displayName: contact.nickname, - sipAddresses: contact.instantMessageAddresses.map { $0.value.service == "SIP" ? $0.value.username : "" }, + sipAddresses: contact.instantMessageAddresses.map { $0.value.service.lowercased() == "SIP".lowercased() ? $0.value.username : "" }, phoneNumbers: contact.phoneNumbers.map { PhoneNumber(numLabel: $0.label ?? "", num: $0.value.stringValue)}, imageData: "" ) @@ -125,8 +126,21 @@ final class ContactsManager: ObservableObject { : contact.givenName, lastName: contact.familyName), name: contact.givenName + contact.familyName, prefix: ((imageThumbnail == nil) ? "-default" : ""), - contact: newContact, linphoneFriend: false, existingFriend: nil) + contact: newContact, linphoneFriend: false, existingFriend: nil) { + if (self.friendList?.friends.count ?? 0) + (self.linphoneFriendList?.friends.count ?? 0) == contactCounter { + self.linphoneFriendList?.updateSubscriptions() + self.friendList?.updateSubscriptions() + + MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + + self.friendListSuscription = self.friendList?.publisher?.onPresenceReceived?.postOnMainQueue { (cbValue: (friendList: FriendList, friends: [Friend])) in + MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + self.friendListSuscription = nil + } + } + } } + contactCounter += 1 }) } catch let error { @@ -137,16 +151,6 @@ final class ContactsManager: ObservableObject { print("\(#function) - access denied") } } - - self.linphoneFriendList?.updateSubscriptions() - self.friendList?.updateSubscriptions() - - self.friendListSuscription = self.friendList?.publisher?.onPresenceReceived?.postOnMainQueue { (cbValue: (friendList: FriendList, friends: [Friend])) in - MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) - self.friendListSuscription = nil - } - - MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) } } @@ -178,7 +182,7 @@ final class ContactsManager: ObservableObject { return IBImgViewUserProfile } - func saveImage(image: UIImage, name: String, prefix: String, contact: Contact, linphoneFriend: Bool, existingFriend: Friend?) { + func saveImage(image: UIImage, name: String, prefix: String, contact: Contact, linphoneFriend: Bool, existingFriend: Friend?, completion: @escaping () -> Void) { guard let data = image.jpegData(compressionQuality: 1) ?? image.pngData() else { return } @@ -192,6 +196,7 @@ final class ContactsManager: ObservableObject { _ = self.friendList?.addLocalFriend(linphoneFriend: resultFriend!) } } + completion() } } } diff --git a/Linphone/Core/CoreContext.swift b/Linphone/Core/CoreContext.swift index 2bc9c37ca..fb3b23a08 100644 --- a/Linphone/Core/CoreContext.swift +++ b/Linphone/Core/CoreContext.swift @@ -168,6 +168,7 @@ final class CoreContext: ObservableObject { if cbVal.state == .Ok { self.loggingInProgress = false self.loggedIn = true + ContactsManager.shared.fetchContacts() } else if cbVal.state == .Progress { self.loggingInProgress = true } else { diff --git a/Linphone/LinphoneApp.swift b/Linphone/LinphoneApp.swift index 2082758b3..00bef0fa1 100644 --- a/Linphone/LinphoneApp.swift +++ b/Linphone/LinphoneApp.swift @@ -143,7 +143,6 @@ struct LinphoneApp: App { if newPhase == .active { Log.info("Entering foreground") coreContext.onEnterForeground() - ContactsManager.shared.fetchContacts() } else if newPhase == .inactive { } else if newPhase == .background { Log.info("Entering background") diff --git a/Linphone/TelecomManager/TelecomManager.swift b/Linphone/TelecomManager/TelecomManager.swift index 62bbc397d..a8bfc30bd 100644 --- a/Linphone/TelecomManager/TelecomManager.swift +++ b/Linphone/TelecomManager/TelecomManager.swift @@ -443,8 +443,9 @@ class TelecomManager: ObservableObject { } else { DispatchQueue.main.async { self.remoteConfVideo = false + let remoteConfVideoTmp = call.currentParams!.videoEnabled && call.currentParams!.videoDirection == .SendRecv || call.currentParams!.videoDirection == .RecvOnly DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - self.remoteConfVideo = call.currentParams!.videoEnabled && call.currentParams!.videoDirection == .SendRecv || call.currentParams!.videoDirection == .RecvOnly + self.remoteConfVideo = remoteConfVideoTmp } } } diff --git a/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift b/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift index 3af2c475b..d6afa15f0 100644 --- a/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift @@ -526,29 +526,29 @@ struct EditContactFragment: View { name: editContactViewModel.firstName + editContactViewModel.lastName, prefix: ((selectedImage == nil) ? "-default" : ""), - contact: newContact, linphoneFriend: true, existingFriend: editContactViewModel.selectedEditFriend) + contact: newContact, linphoneFriend: true, existingFriend: editContactViewModel.selectedEditFriend) { + MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + + if editContactViewModel.selectedEditFriend != nil && editContactViewModel.selectedEditFriend!.name != editContactViewModel.firstName + " " + editContactViewModel.lastName { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + let result = ContactsManager.shared.lastSearch.firstIndex(where: { + $0.friend!.name == newContact.firstName + " " + newContact.lastName + }) + contactViewModel.indexDisplayedFriend = result + } + } + + delayColorDismiss() + if editContactViewModel.selectedEditFriend == nil { + withAnimation { + isShowEditContactFragment.toggle() + } + } else { + dismiss() + } + editContactViewModel.resetValues() + } } - - MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) - - if editContactViewModel.selectedEditFriend != nil && editContactViewModel.selectedEditFriend!.name != editContactViewModel.firstName + " " + editContactViewModel.lastName { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - let result = ContactsManager.shared.lastSearch.firstIndex(where: { - $0.friend!.name == newContact.firstName + " " + newContact.lastName - }) - contactViewModel.indexDisplayedFriend = result - } - } - - delayColorDismiss() - if editContactViewModel.selectedEditFriend == nil { - withAnimation { - isShowEditContactFragment.toggle() - } - } else { - dismiss() - } - editContactViewModel.resetValues() } } diff --git a/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift b/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift index f8383011e..59ec6c20c 100644 --- a/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift +++ b/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift @@ -117,7 +117,6 @@ class ContactAvatarModel: ObservableObject { } } - static func getAvatarModelFromAddress(address: Address, completion: @escaping (ContactAvatarModel) -> Void) { ContactsManager.shared.getFriendWithAddressInCoreQueue(address: address) { resultFriend in if let addressFriend = resultFriend { diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift index 5e3fb392c..9ef536ca9 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift @@ -34,21 +34,21 @@ struct ConversationsListFragment: View { List { ForEach(0.. 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].subject) - .foregroundStyle(Color.grayMain2c800) - .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].lastMessageText) + Text(conversationsListViewModel.conversationsList[index].lastMessageText) .foregroundStyle(Color.grayMain2c400) .if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in view.default_text_style_700(styleSize: 14) @@ -56,79 +56,79 @@ struct ConversationsListFragment: View { .default_text_style(styleSize: 14) .frame(maxWidth: .infinity, alignment: .leading) .lineLimit(1) + + Spacer() + } + + Spacer() + + VStack(alignment: .trailing, spacing: 0) { + Spacer() + + HStack { + if !conversationsListViewModel.conversationsList[index].encryptionEnabled { + Image("warning-circle") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.redDanger500) + .frame(width: 18, height: 18, alignment: .trailing) + } - Spacer() + Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastUpdateTime)) + .foregroundStyle(Color.grayMain2c400) + .default_text_style(styleSize: 14) + .lineLimit(1) } Spacer() - VStack(alignment: .trailing, spacing: 0) { - Spacer() + HStack { + if conversationsListViewModel.conversationsList[index].isMuted == false + && !(!conversationsListViewModel.conversationsList[index].lastMessageText.isEmpty + && conversationsListViewModel.conversationsList[index].lastMessageIsOutgoing == true) + && conversationsListViewModel.conversationsList[index].unreadMessagesCount == 0 { + Text("") + .frame(width: 18, height: 18, alignment: .trailing) + } - HStack { - if !conversationsListViewModel.conversationsList[index].encryptionEnabled { - Image("warning-circle") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.redDanger500) - .frame(width: 18, height: 18, alignment: .trailing) - } - - Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastUpdateTime)) - .foregroundStyle(Color.grayMain2c400) - .default_text_style(styleSize: 14) + if conversationsListViewModel.conversationsList[index].isMuted { + Image("bell-slash") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.orangeMain500) + .frame(width: 18, height: 18, alignment: .trailing) + } + + if !conversationsListViewModel.conversationsList[index].lastMessageText.isEmpty + && conversationsListViewModel.conversationsList[index].lastMessageIsOutgoing == true { + let imageName = LinphoneUtils.getChatIconState(chatState: conversationsListViewModel.conversationsList[index].lastMessageState) + Image(imageName) + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.orangeMain500) + .frame(width: 18, height: 18, alignment: .trailing) + } + + if conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0 { + HStack { + Text( + conversationsListViewModel.conversationsList[index].unreadMessagesCount < 99 + ? String(conversationsListViewModel.conversationsList[index].unreadMessagesCount) + : "99+" + ) + .foregroundStyle(.white) + .default_text_style(styleSize: 10) .lineLimit(1) + } + .frame(width: 18, height: 18) + .background(Color.redDanger500) + .cornerRadius(50) } - - Spacer() - - HStack { - if conversationsListViewModel.conversationsList[index].isMuted == false - && !(!conversationsListViewModel.conversationsList[index].lastMessageText.isEmpty - && conversationsListViewModel.conversationsList[index].lastMessageIsOutgoing == true) - && conversationsListViewModel.conversationsList[index].unreadMessagesCount == 0 { - Text("") - .frame(width: 18, height: 18, alignment: .trailing) - } - - if conversationsListViewModel.conversationsList[index].isMuted { - Image("bell-slash") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.orangeMain500) - .frame(width: 18, height: 18, alignment: .trailing) - } - - if !conversationsListViewModel.conversationsList[index].lastMessageText.isEmpty - && conversationsListViewModel.conversationsList[index].lastMessageIsOutgoing == true { - let imageName = LinphoneUtils.getChatIconState(chatState: conversationsListViewModel.conversationsList[index].lastMessageState) - Image(imageName) - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.orangeMain500) - .frame(width: 18, height: 18, alignment: .trailing) - } - - if conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0 { - HStack { - Text( - conversationsListViewModel.conversationsList[index].unreadMessagesCount < 99 - ? String(conversationsListViewModel.conversationsList[index].unreadMessagesCount) - : "99+" - ) - .foregroundStyle(.white) - .default_text_style(styleSize: 10) - .lineLimit(1) - } - .frame(width: 18, height: 18) - .background(Color.redDanger500) - .cornerRadius(50) - } - } - - Spacer() } - .padding(.trailing, 10) + + Spacer() + } + .padding(.trailing, 10) } .frame(height: 50) .buttonStyle(.borderless) diff --git a/Linphone/UI/Main/Conversations/Model/ConversationModel.swift b/Linphone/UI/Main/Conversations/Model/ConversationModel.swift index 60238fa3f..cb50b7d8c 100644 --- a/Linphone/UI/Main/Conversations/Model/ConversationModel.swift +++ b/Linphone/UI/Main/Conversations/Model/ConversationModel.swift @@ -39,19 +39,14 @@ class ConversationModel: ObservableObject { @Published var subject: String @Published var isComposing: Bool @Published var lastUpdateTime: time_t - //@Published var composingLabel: String @Published var isMuted: Bool @Published var isEphemeral: Bool @Published var encryptionEnabled: Bool @Published var lastMessageText: String @Published var lastMessageIsOutgoing: Bool @Published var lastMessageState: Int - //@Published var dateTime: String @Published var unreadMessagesCount: Int @Published var avatarModel: ContactAvatarModel - //@Published var isBeingDeleted: Bool - - //private let lastMessage: ChatMessage? = nil init(chatRoom: ChatRoom) { self.chatRoom = chatRoom @@ -72,8 +67,6 @@ class ConversationModel: ObservableObject { self.isComposing = chatRoom.isRemoteComposing - //self.composingLabel = chatRoom.compo - self.isMuted = chatRoom.muted self.isEphemeral = chatRoom.ephemeralEnabled @@ -86,15 +79,9 @@ class ConversationModel: ObservableObject { self.lastMessageState = 0 - //self.dateTime = chatRoom.date - self.unreadMessagesCount = 0 - self.avatarModel = ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false) - - //self.isBeingDeleted = MutableLiveData() - - //self.lastMessage: ChatMessage? = null + self.avatarModel = ContactAvatarModel(friend: nil, name: chatRoom.subject ?? "", address: chatRoom.peerAddress?.asStringUriOnly() ?? "", withPresence: false) getContentTextMessage() getChatRoomSubject() diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift index 9721912c0..7ed96c4e2 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift @@ -205,5 +205,7 @@ class ConversationsListViewModel: ObservableObject { conversationsList.forEach { conversationModel in conversationModel.refreshAvatarModel() } + + reorderChatRooms() } } diff --git a/Linphone/Utils/EditContactController.swift b/Linphone/Utils/EditContactController.swift index 4734b5562..a7c4c722b 100644 --- a/Linphone/Utils/EditContactController.swift +++ b/Linphone/Utils/EditContactController.swift @@ -54,9 +54,9 @@ struct EditContactView: UIViewControllerRepresentable { prefix: ((imageThumbnail == nil) ? "-default" : ""), contact: newContact, linphoneFriend: false, - existingFriend: ContactsManager.shared.getFriendWithContact(contact: newContact)) - - MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + existingFriend: ContactsManager.shared.getFriendWithContact(contact: newContact)) { + MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + } } } viewController.dismiss(animated: true, completion: {})