From 106e628e41a9ef8233f9735d29ae8b90bea13a4e Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Thu, 28 Aug 2025 18:26:06 +0200 Subject: [PATCH] Fix contacts list --- Linphone/Contacts/ContactsManager.swift | 62 +++++++++++++++---- .../Fragments/EditContactFragment.swift | 2 +- .../Contacts/Model/ContactAvatarModel.swift | 3 +- Linphone/Utils/EditContactController.swift | 2 +- Linphone/Utils/MagicSearchSingleton.swift | 25 +++++--- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/Linphone/Contacts/ContactsManager.swift b/Linphone/Contacts/ContactsManager.swift index 95288d183..04ec16a18 100644 --- a/Linphone/Contacts/ContactsManager.swift +++ b/Linphone/Contacts/ContactsManager.swift @@ -36,9 +36,11 @@ final class ContactsManager: ObservableObject { private let nativeAddressBookFriendList = "Native address-book" let linphoneAddressBookFriendList = "Linphone address-book" + let tempRemoteAddressBookFriendList = "TempRemoteDirectoryContacts address-book" var friendList: FriendList? var linphoneFriendList: FriendList? + var tempRemoteFriendList: FriendList? @Published var lastSearch: [SearchResult] = [] @Published var lastSearchSuggestions: [SearchResult] = [] @@ -96,6 +98,21 @@ final class ContactsManager: ObservableObject { core.addFriendList(list: linphoneFriendList) } } + + do { + self.tempRemoteFriendList = try core.getFriendListByName(name: self.tempRemoteAddressBookFriendList) ?? core.createFriendList() + } catch let error { + print("\(#function) - Failed to enumerate contacts: \(error)") + } + + if let tempRemoteFriendList = self.tempRemoteFriendList { + if tempRemoteFriendList.displayName == nil || tempRemoteFriendList.displayName!.isEmpty { + print("\(#function) - Friend list \(self.tempRemoteAddressBookFriendList) didn't exist yet, let's create it") + tempRemoteFriendList.databaseStorageEnabled = true + tempRemoteFriendList.displayName = self.tempRemoteAddressBookFriendList + core.addFriendList(list: tempRemoteFriendList) + } + } } let store = CNContactStore() @@ -142,7 +159,7 @@ final class ContactsManager: ObservableObject { image: image, name: contact.givenName + contact.familyName, prefix: "", - contact: newContact, linphoneFriend: false, existingFriend: nil) { + contact: newContact, linphoneFriend: self.nativeAddressBookFriendList, existingFriend: nil) { dispatchGroup.leave() } } @@ -152,7 +169,7 @@ final class ContactsManager: ObservableObject { image: image, name: contact.givenName + contact.familyName, prefix: "-default", - contact: newContact, linphoneFriend: false, existingFriend: nil) { + contact: newContact, linphoneFriend: self.nativeAddressBookFriendList, existingFriend: nil) { dispatchGroup.leave() } } @@ -237,7 +254,7 @@ final class ContactsManager: ObservableObject { return IBImgViewUserProfile } - func saveImage(image: UIImage, name: String, prefix: String, contact: Contact, linphoneFriend: Bool, existingFriend: Friend?, completion: @escaping () -> Void) { + func saveImage(image: UIImage, name: String, prefix: String, contact: Contact, linphoneFriend: String, existingFriend: Friend?, completion: @escaping () -> Void) { guard let data = image.jpegData(compressionQuality: 1) ?? image.pngData() else { return } @@ -245,10 +262,12 @@ final class ContactsManager: ObservableObject { awaitDataWrite(data: data, name: name, prefix: prefix) { _, result in self.saveFriend(result: result, contact: contact, existingFriend: existingFriend) { resultFriend in if resultFriend != nil { - if linphoneFriend && existingFriend == nil { - if let linphoneFL = self.linphoneFriendList { + if linphoneFriend != self.nativeAddressBookFriendList && existingFriend == nil { + if let linphoneFL = self.linphoneFriendList, linphoneFriend == linphoneFL.displayName { _ = linphoneFL.addFriend(linphoneFriend: resultFriend!) - } + } else if let linphoneFL = self.tempRemoteFriendList { + _ = linphoneFL.addFriend(linphoneFriend: resultFriend!) + } } else if existingFriend == nil { if let friendListTmp = self.friendList { _ = friendListTmp.addLocalFriend(linphoneFriend: resultFriend!) @@ -378,12 +397,17 @@ final class ContactsManager: ObservableObject { let sipUri = clonedAddress.asStringUriOnly() var friend: Friend? + if let friendList = self.friendList { friend = friendList.friends.first(where: { $0.addresses.contains(where: { $0.asStringUriOnly() == sipUri }) }) } if friend == nil, let linphoneFriendList = self.linphoneFriendList { friend = linphoneFriendList.friends.first(where: { $0.addresses.contains(where: { $0.asStringUriOnly() == sipUri }) }) - } + } + if friend == nil, let tempRemoteFriendList = self.tempRemoteFriendList { + friend = tempRemoteFriendList.friends.first(where: { $0.addresses.contains(where: { $0.asStringUriOnly() == sipUri }) }) + } + return friend } @@ -414,7 +438,18 @@ final class ContactsManager: ObservableObject { onSyncStatusChanged: { (friendList: FriendList, status: FriendList.SyncStatus?, message: String?) in Log.info("\(ContactsManager.TAG) FriendListDelegateStub onSyncStatusChanged") if status == .Successful { + if friendList.displayName != self.nativeAddressBookFriendList && friendList.displayName != self.linphoneAddressBookFriendList { + if let tempRemoteFriendList = self.tempRemoteFriendList { + tempRemoteFriendList.friends.forEach { friend in + _ = tempRemoteFriendList.removeFriend(linphoneFriend: friend) + } + } + } + + let dispatchGroup = DispatchGroup() + friendList.friends.forEach { friend in + dispatchGroup.enter() let addressTmp = friend.address?.clone()?.asStringUriOnly() ?? "" let newContact = Contact( @@ -434,14 +469,19 @@ final class ContactsManager: ObservableObject { image: image, name: friend.name ?? addressTmp, prefix: "-default", - contact: newContact, linphoneFriend: false, existingFriend: friend) { - + contact: newContact, linphoneFriend: friendList.displayName ?? "No Display Name", existingFriend: nil) { + dispatchGroup.leave() } } } + + dispatchGroup.notify(queue: .main) { + MagicSearchSingleton.shared.searchForContacts() + if let linphoneFL = self.tempRemoteFriendList { + linphoneFL.updateSubscriptions() + } + } } - - MagicSearchSingleton.shared.searchForContacts() }, onPresenceReceived: { (friendList: FriendList, friends: [Friend?]) in Log.info("\(ContactsManager.TAG) FriendListDelegateStub onPresenceReceived \(friends.count)") diff --git a/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift b/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift index 806114009..c9306e54d 100644 --- a/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift @@ -554,7 +554,7 @@ struct EditContactFragment: View { name: editContactViewModel.firstName + editContactViewModel.lastName, prefix: ((selectedImage == nil) ? "-default" : ""), - contact: newContact, linphoneFriend: true, existingFriend: editContactViewModel.selectedEditFriend?.friend) { + contact: newContact, linphoneFriend: "Linphone address-book", existingFriend: editContactViewModel.selectedEditFriend?.friend) { if let selectedFriendTmp = editContactViewModel.selectedEditFriend?.friend { let addressTmp = selectedFriendTmp.address?.clone()?.asStringUriOnly() ?? "" SharedMainViewModel.shared.displayedFriend?.resetContactAvatarModel( diff --git a/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift b/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift index 65957a71f..356c8c6e0 100644 --- a/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift +++ b/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift @@ -80,10 +80,11 @@ class ContactAvatarModel: ObservableObject, Identifiable { var presenceStatusTmp: ConsolidatedPresence = .Offline if let friend = friend, withPresence == true { + lastPresenceInfoTmp = "" presenceStatusTmp = friend.consolidatedPresence - + if friend.consolidatedPresence == .Online || friend.consolidatedPresence == .Busy { if friend.consolidatedPresence == .Online || friend.presenceModel?.latestActivityTimestamp != -1 { lastPresenceInfoTmp = (friend.consolidatedPresence == .Online) ? diff --git a/Linphone/Utils/EditContactController.swift b/Linphone/Utils/EditContactController.swift index e89745ced..1e6b970fe 100644 --- a/Linphone/Utils/EditContactController.swift +++ b/Linphone/Utils/EditContactController.swift @@ -53,7 +53,7 @@ struct EditContactView: UIViewControllerRepresentable { name: cnc.givenName + cnc.familyName, prefix: ((imageThumbnail == nil) ? "-default" : ""), contact: newContact, - linphoneFriend: false, + linphoneFriend: "Native address-book", existingFriend: ContactsManager.shared.getFriendWithContact(contact: newContact)) { MagicSearchSingleton.shared.searchForContacts() } diff --git a/Linphone/Utils/MagicSearchSingleton.swift b/Linphone/Utils/MagicSearchSingleton.swift index 08c9fd04b..3ec990ea3 100644 --- a/Linphone/Utils/MagicSearchSingleton.swift +++ b/Linphone/Utils/MagicSearchSingleton.swift @@ -42,6 +42,10 @@ final class MagicSearchSingleton: ObservableObject { var searchDelegate: MagicSearchDelegate? private var contactLoadedDebounceWorkItem: DispatchWorkItem? + + let nativeAddressBookFriendList = "Native address-book" + let linphoneAddressBookFriendList = "Linphone address-book" + let tempRemoteAddressBookFriendList = "TempRemoteDirectoryContacts address-book" func destroyMagicSearch() { magicSearch = nil @@ -67,7 +71,7 @@ final class MagicSearchSingleton: ObservableObject { var lastSearchSuggestions: [SearchResult] = [] magicSearch.lastSearch.forEach { searchResult in - if searchResult.friend != nil { + if searchResult.friend != nil && (searchResult.friend?.friendList?.displayName == self.nativeAddressBookFriendList || searchResult.friend?.friendList?.displayName == self.linphoneAddressBookFriendList || searchResult.friend?.friendList?.displayName == self.tempRemoteAddressBookFriendList) { if let address = searchResult.address, !lastSearchFriend.contains(where: { $0.address?.weakEqual(address2: address) ?? false }) { lastSearchFriend.append(searchResult) @@ -99,14 +103,17 @@ final class MagicSearchSingleton: ObservableObject { var addedAvatarListModel: [ContactAvatarModel] = [] sortedLastSearch.forEach { searchResult in if searchResult.friend != nil { - addedAvatarListModel.append( - ContactAvatarModel( - friend: searchResult.friend!, - name: searchResult.friend?.name ?? "", - address: searchResult.friend?.address?.clone()?.asStringUriOnly() ?? "", - withPresence: true - ) - ) + if (searchResult.friend?.friendList?.displayName == self.nativeAddressBookFriendList || searchResult.friend?.friendList?.displayName == self.linphoneAddressBookFriendList || searchResult.friend?.friendList?.displayName == self.tempRemoteAddressBookFriendList) { + + addedAvatarListModel.append( + ContactAvatarModel( + friend: searchResult.friend!, + name: searchResult.friend?.name ?? "", + address: searchResult.friend?.address?.clone()?.asStringUriOnly() ?? "", + withPresence: true + ) + ) + } } }