diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationForwardMessageFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationForwardMessageFragment.swift index d25e456e9..d1f281302 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationForwardMessageFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationForwardMessageFragment.swift @@ -284,6 +284,7 @@ struct ConversationForwardMessageFragment: View { Text(String(contactsManager.lastSearchSuggestions[index].address!.asStringUriOnly().dropFirst(4))) .default_text_style(styleSize: 16) + .lineLimit(1) .frame(maxWidth: .infinity, alignment: .leading) .foregroundStyle(Color.orangeMain500) } else { diff --git a/Linphone/UI/Main/Conversations/Fragments/StartConversationFragment.swift b/Linphone/UI/Main/Conversations/Fragments/StartConversationFragment.swift index 44eac247f..8f766df96 100644 --- a/Linphone/UI/Main/Conversations/Fragments/StartConversationFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/StartConversationFragment.swift @@ -276,6 +276,7 @@ struct StartConversationFragment: View { Text(String(contactsManager.lastSearchSuggestions[index].address!.asStringUriOnly().dropFirst(4))) .default_text_style(styleSize: 16) + .lineLimit(1) .frame(maxWidth: .infinity, alignment: .leading) .foregroundStyle(Color.orangeMain500) } else { diff --git a/Linphone/UI/Main/History/Fragments/StartCallFragment.swift b/Linphone/UI/Main/History/Fragments/StartCallFragment.swift index 0b7f3878f..ac89ffe72 100644 --- a/Linphone/UI/Main/History/Fragments/StartCallFragment.swift +++ b/Linphone/UI/Main/History/Fragments/StartCallFragment.swift @@ -410,6 +410,7 @@ struct StartCallFragment: View { Text(String(contactsManager.lastSearchSuggestions[index].address!.asStringUriOnly().dropFirst(4))) .default_text_style(styleSize: 16) + .lineLimit(1) .frame(maxWidth: .infinity, alignment: .leading) .foregroundStyle(Color.orangeMain500) } else { diff --git a/Linphone/UI/Main/Meetings/Fragments/AddParticipantsFragment.swift b/Linphone/UI/Main/Meetings/Fragments/AddParticipantsFragment.swift index 21ebdf789..600181212 100644 --- a/Linphone/UI/Main/Meetings/Fragments/AddParticipantsFragment.swift +++ b/Linphone/UI/Main/Meetings/Fragments/AddParticipantsFragment.swift @@ -294,6 +294,7 @@ struct AddParticipantsFragment: View { Text(String(contactsManager.lastSearchSuggestions[index].address!.asStringUriOnly().dropFirst(4))) .default_text_style(styleSize: 16) + .lineLimit(1) .lineLimit(1) .frame(maxWidth: .infinity, alignment: .leading) .foregroundStyle(Color.orangeMain500) diff --git a/Linphone/Utils/MagicSearchSingleton.swift b/Linphone/Utils/MagicSearchSingleton.swift index b03422a45..56f06947d 100644 --- a/Linphone/Utils/MagicSearchSingleton.swift +++ b/Linphone/Utils/MagicSearchSingleton.swift @@ -40,6 +40,8 @@ final class MagicSearchSingleton: ObservableObject { private var domainDefaultAccount = "" var searchDelegate: MagicSearchDelegate? + + private var contactLoadedDebounceWorkItem: DispatchWorkItem? func destroyMagicSearch() { magicSearch = nil @@ -59,13 +61,17 @@ final class MagicSearchSingleton: ObservableObject { var lastSearchFriend: [SearchResult] = [] var lastSearchSuggestions: [SearchResult] = [] - magicSearch.lastSearch.forEach { searchResult in - if searchResult.friend != nil { - lastSearchFriend.append(searchResult) - } else { - lastSearchSuggestions.append(searchResult) - } - } + magicSearch.lastSearch.forEach { searchResult in + if let friend = searchResult.friend, + let address = searchResult.address, + !lastSearchFriend.contains(where: { $0.address?.weakEqual(address2: address) ?? false }) { + + lastSearchFriend.append(searchResult) + } else { + lastSearchSuggestions.append(searchResult) + } + } + lastSearchSuggestions.sort(by: { $0.address!.asStringUriOnly() < $1.address!.asStringUriOnly() }) @@ -99,20 +105,37 @@ final class MagicSearchSingleton: ObservableObject { self.contactsManager.avatarListModel.forEach { contactAvatarModel in contactAvatarModel.removeFriendDelegate() } - - DispatchQueue.main.async { - self.contactsManager.lastSearch = sortedLastSearch - self.contactsManager.lastSearchSuggestions = lastSearchSuggestions - - self.contactsManager.avatarListModel.removeAll() - self.contactsManager.avatarListModel += addedAvatarListModel - - NotificationCenter.default.post(name: NSNotification.Name("ContactLoaded"), object: nil) - } + + self.updateContacts(sortedLastSearch: sortedLastSearch, lastSearchSuggestions: lastSearchSuggestions, addedAvatarListModel: addedAvatarListModel) }) self.magicSearch.addDelegate(delegate: self.searchDelegate!) } } + + func updateContacts( + sortedLastSearch: [SearchResult], + lastSearchSuggestions: [SearchResult], + addedAvatarListModel: [ContactAvatarModel] + ) { + DispatchQueue.main.async { + self.contactsManager.lastSearch = sortedLastSearch + self.contactsManager.lastSearchSuggestions = lastSearchSuggestions + + self.contactsManager.avatarListModel.removeAll() + self.contactsManager.avatarListModel += addedAvatarListModel + + // Cancel previous debounce task + self.contactLoadedDebounceWorkItem?.cancel() + + // Schedule new debounce task + let workItem = DispatchWorkItem { + NotificationCenter.default.post(name: NSNotification.Name("ContactLoaded"), object: nil) + } + + self.contactLoadedDebounceWorkItem = workItem + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: workItem) + } + } func searchForContacts() { coreContext.doOnCoreQueue { _ in