diff --git a/Linphone/Contacts/ContactsManager.swift b/Linphone/Contacts/ContactsManager.swift index cc3c30db1..454090020 100644 --- a/Linphone/Contacts/ContactsManager.swift +++ b/Linphone/Contacts/ContactsManager.swift @@ -133,8 +133,9 @@ final class ContactsManager: ObservableObject { MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) - self.friendListSuscription = self.friendList?.publisher?.onNewSipAddressDiscovered?.postOnMainQueue { (cbValue: (friendList: FriendList, linphoneFriend: Friend, sipUri: String)) in + self.friendListSuscription = self.friendList?.publisher?.onNewSipAddressDiscovered?.postOnCoreQueue { (cbValue: (friendList: FriendList, linphoneFriend: Friend, sipUri: String)) in + var addedAvatarListModel : [ContactAvatarModel] = [] cbValue.linphoneFriend.phoneNumbers.forEach { phone in do { let address = core.interpretUrl(url: phone, applyInternationalPrefix: true) @@ -145,7 +146,7 @@ final class ContactsManager: ObservableObject { cbValue.linphoneFriend.addAddress(address: address!) cbValue.linphoneFriend.done() - self.avatarListModel.append( + addedAvatarListModel.append( ContactAvatarModel( friend: cbValue.linphoneFriend, name: cbValue.linphoneFriend.name ?? "", @@ -158,6 +159,10 @@ final class ContactsManager: ObservableObject { print("\(#function) - Failed to create friend phone number for \(phone):", error) } } + + DispatchQueue.main.async { + self.avatarListModel += addedAvatarListModel + } } } } diff --git a/Linphone/Core/CoreContext.swift b/Linphone/Core/CoreContext.swift index c3608d72f..b3bc8cc9b 100644 --- a/Linphone/Core/CoreContext.swift +++ b/Linphone/Core/CoreContext.swift @@ -117,19 +117,8 @@ final class CoreContext: ObservableObject { self.mCore.videoCaptureEnabled = true self.mCore.videoDisplayEnabled = true self.mCore.videoPreviewEnabled = false - self.mCore.fecEnabled = true - self.mCoreSuscriptions.insert(self.mCore.publisher?.onGlobalStateChanged?.postOnMainQueue { (cbVal: (core: Core, state: GlobalState, message: String)) in - if cbVal.state == GlobalState.On { - self.hasDefaultAccount = self.mCore.defaultAccount != nil ? true : false - self.coreIsStarted = true - } else if cbVal.state == GlobalState.Off { - self.hasDefaultAccount = false - self.coreIsStarted = false - } - }) - self.mCoreSuscriptions.insert(self.mCore.publisher?.onGlobalStateChanged?.postOnCoreQueue { (cbVal: (core: Core, state: GlobalState, message: String)) in if cbVal.state == GlobalState.On { #if DEBUG @@ -146,16 +135,28 @@ final class CoreContext: ObservableObject { self.actionsToPerformOnCoreQueueWhenCoreIsStarted.forEach {$0(cbVal.core)} self.actionsToPerformOnCoreQueueWhenCoreIsStarted.removeAll() + + DispatchQueue.main.async { + if cbVal.state == GlobalState.On { + self.hasDefaultAccount = self.mCore.defaultAccount != nil ? true : false + self.coreIsStarted = true + } else if cbVal.state == GlobalState.Off { + self.hasDefaultAccount = false + self.coreIsStarted = false + } + } } }) // Create a Core listener to listen for the callback we need // In this case, we want to know about the account registration status - self.mCoreSuscriptions.insert(self.mCore.publisher?.onConfiguringStatus?.postOnMainQueue { (cbVal: (core: Core, status: ConfiguringState, message: String)) in + self.mCoreSuscriptions.insert(self.mCore.publisher?.onConfiguringStatus?.postOnCoreQueue { (cbVal: (core: Core, status: ConfiguringState, message: String)) in Log.info("New configuration state is \(cbVal.status) = \(cbVal.message)\n") - if cbVal.status == ConfiguringState.Successful { - ToastViewModel.shared.toastMessage = "Successful" - ToastViewModel.shared.displayToast = true + DispatchQueue.main.async { + if cbVal.status == ConfiguringState.Successful { + ToastViewModel.shared.toastMessage = "Successful" + ToastViewModel.shared.displayToast = true + } } /* else { @@ -165,35 +166,21 @@ final class CoreContext: ObservableObject { */ }) - self.mCoreSuscriptions.insert(self.mCore.publisher?.onAccountRegistrationStateChanged?.postOnMainQueue { (cbVal: (core: Core, account: Account, state: RegistrationState, message: String)) in + self.mCoreSuscriptions.insert(self.mCore.publisher?.onAccountRegistrationStateChanged?.postOnCoreQueue { (cbVal: (core: Core, account: Account, state: RegistrationState, message: String)) in + // If account has been configured correctly, we will go through Progress and Ok states // Otherwise, we will be Failed. Log.info("New registration state is \(cbVal.state) for user id " + "\( String(describing: cbVal.account.params?.identityAddress?.asString())) = \(cbVal.message)\n") + if cbVal.state == .Ok { - self.loggingInProgress = false - self.loggedIn = true - let newParams = cbVal.account.params?.clone() newParams?.internationalPrefix = "33" newParams?.internationalPrefixIsoCountryCode = "FRA" newParams?.useInternationalPrefixForCallsAndChats = true - cbVal.account.params = newParams ContactsManager.shared.fetchContacts() - } else if cbVal.state == .Progress { - self.loggingInProgress = true - } else { - self.loggingInProgress = false - self.loggedIn = false - ToastViewModel.shared.toastMessage = "Registration failed" - ToastViewModel.shared.displayToast = true - } - }) - - self.mCoreSuscriptions.insert(self.mCore.publisher?.onAccountRegistrationStateChanged?.postOnCoreQueue { (cbVal: (core: Core, account: Account, state: RegistrationState, message: String)) in - if cbVal.state == .Ok { if self.mCore.consolidatedPresence != ConsolidatedPresence.Online { self.updatePresence(core: self.mCore, presence: ConsolidatedPresence.Online) } @@ -213,6 +200,20 @@ final class CoreContext: ObservableObject { } } TelecomManager.shared.onAccountRegistrationStateChanged(core: cbVal.core, account: cbVal.account, state: cbVal.state, message: cbVal.message) + + DispatchQueue.main.async { + if cbVal.state == .Ok { + self.loggingInProgress = false + self.loggedIn = true + } else if cbVal.state == .Progress { + self.loggingInProgress = true + } else { + self.loggingInProgress = false + self.loggedIn = false + ToastViewModel.shared.toastMessage = "Registration failed" + ToastViewModel.shared.displayToast = true + } + } }) self.mCoreSuscriptions.insert(self.mCore.publisher?.onCallStateChanged?.postOnCoreQueue { (cbVal: (core: Core, call: Call, state: Call.State, message: String)) in @@ -229,33 +230,36 @@ final class CoreContext: ObservableObject { }) self.mCore.addDelegate(delegate: self.mCorePushIncomingDelegate) - self.mCoreSuscriptions.insert(self.mCore.publisher?.onLogCollectionUploadStateChanged?.postOnMainQueue { (cbValue: (_: Core, _: Core.LogCollectionUploadState, info: String)) in + self.mCoreSuscriptions.insert(self.mCore.publisher?.onLogCollectionUploadStateChanged?.postOnCoreQueue { (cbValue: (_: Core, _: Core.LogCollectionUploadState, info: String)) in + if cbValue.info.starts(with: "https") { - UIPasteboard.general.setValue( - cbValue.info, - forPasteboardType: UTType.plainText.identifier - ) - DispatchQueue.main.async { + UIPasteboard.general.setValue( + cbValue.info, + forPasteboardType: UTType.plainText.identifier + ) ToastViewModel.shared.toastMessage = "Success_send_logs" ToastViewModel.shared.displayToast = true } } }) - self.mCoreSuscriptions.insert(self.mCore.publisher?.onTransferStateChanged?.postOnMainQueue { (cbValue: (_: Core, transfered: Call, callState: Call.State)) in + self.mCoreSuscriptions.insert(self.mCore.publisher?.onTransferStateChanged?.postOnCoreQueue { (cbValue: (_: Core, transfered: Call, callState: Call.State)) in Log.info( "[CoreContext] Transferred call \(cbValue.transfered.remoteAddress!.asStringUriOnly()) state changed \(cbValue.callState)" ) - if cbValue.callState == Call.State.Connected { - ToastViewModel.shared.toastMessage = "Success_toast_call_transfer_successful" - ToastViewModel.shared.displayToast = true - } else if cbValue.callState == Call.State.OutgoingProgress { - ToastViewModel.shared.toastMessage = "Success_toast_call_transfer_in_progress" - ToastViewModel.shared.displayToast = true - } else if cbValue.callState == Call.State.End || cbValue.callState == Call.State.Error { - ToastViewModel.shared.toastMessage = "Failed_toast_call_transfer_failed" - ToastViewModel.shared.displayToast = true + + DispatchQueue.main.async { + if cbValue.callState == Call.State.Connected { + ToastViewModel.shared.toastMessage = "Success_toast_call_transfer_successful" + ToastViewModel.shared.displayToast = true + } else if cbValue.callState == Call.State.OutgoingProgress { + ToastViewModel.shared.toastMessage = "Success_toast_call_transfer_in_progress" + ToastViewModel.shared.displayToast = true + } else if cbValue.callState == Call.State.End || cbValue.callState == Call.State.Error { + ToastViewModel.shared.toastMessage = "Failed_toast_call_transfer_failed" + ToastViewModel.shared.displayToast = true + } } }) diff --git a/Linphone/UI/Call/ViewModel/CallViewModel.swift b/Linphone/UI/Call/ViewModel/CallViewModel.swift index 275c6fcf5..b799b58d0 100644 --- a/Linphone/UI/Call/ViewModel/CallViewModel.swift +++ b/Linphone/UI/Call/ViewModel/CallViewModel.swift @@ -214,16 +214,20 @@ class CallViewModel: ObservableObject { } } - self.callSuscriptions.insert(self.currentCall!.publisher?.onEncryptionChanged?.postOnMainQueue {(cbVal: (call: Call, on: Bool, authenticationToken: String?)) in - _ = self.updateEncryption() - if self.currentCall != nil { - self.callMediaEncryptionModel.update(call: self.currentCall!) + self.callSuscriptions.insert(self.currentCall!.publisher?.onEncryptionChanged?.postOnCoreQueue {(cbVal: (call: Call, on: Bool, authenticationToken: String?)) in + DispatchQueue.main.async { + _ = self.updateEncryption() + if self.currentCall != nil { + self.callMediaEncryptionModel.update(call: self.currentCall!) + } } }) - self.callSuscriptions.insert(self.currentCall!.publisher?.onStatsUpdated?.postOnMainQueue {(cbVal: (call: Call, stats: CallStats)) in + self.callSuscriptions.insert(self.currentCall!.publisher?.onStatsUpdated?.postOnCoreQueue {(cbVal: (call: Call, stats: CallStats)) in if self.currentCall != nil { - self.callStatsModel.update(call: self.currentCall!, stats: cbVal.stats) + DispatchQueue.main.async { + self.callStatsModel.update(call: self.currentCall!, stats: cbVal.stats) + } } }) @@ -340,9 +344,11 @@ class CallViewModel: ObservableObject { func waitingForCreatedStateConference() { self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onStateChanged?.postOnMainQueue {(cbValue: (conference: Conference, state: Conference.State)) in + self.currentCall?.conference?.publisher?.onStateChanged?.postOnCoreQueue {(cbValue: (conference: Conference, state: Conference.State)) in if cbValue.state == .Created { - self.getConference() + DispatchQueue.main.async { + self.getConference() + } } } ) @@ -352,7 +358,7 @@ class CallViewModel: ObservableObject { func addConferenceCallBacks() { coreContext.doOnCoreQueue { core in self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onActiveSpeakerParticipantDevice?.postOnMainQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in + self.currentCall?.conference?.publisher?.onActiveSpeakerParticipantDevice?.postOnCoreQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in if cbValue.participantDevice.address != nil { let activeSpeakerParticipantBis = self.activeSpeakerParticipant @@ -410,7 +416,7 @@ class CallViewModel: ObservableObject { ) self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onParticipantDeviceAdded?.postOnMainQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in + self.currentCall?.conference?.publisher?.onParticipantDeviceAdded?.postOnCoreQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in if cbValue.participantDevice.address != nil { var participantListTmp: [ParticipantModel] = [] cbValue.conference.participantDeviceList.forEach({ participantDevice in @@ -488,7 +494,7 @@ class CallViewModel: ObservableObject { ) self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onParticipantDeviceRemoved?.postOnMainQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in + self.currentCall?.conference?.publisher?.onParticipantDeviceRemoved?.postOnCoreQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in if cbValue.participantDevice.address != nil { var participantListTmp: [ParticipantModel] = [] cbValue.conference.participantDeviceList.forEach({ participantDevice in @@ -522,20 +528,16 @@ class CallViewModel: ObservableObject { ) self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onParticipantDeviceIsMuted?.postOnMainQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice, isMuted: Bool)) in + self.currentCall?.conference?.publisher?.onParticipantDeviceIsMuted?.postOnCoreQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice, isMuted: Bool)) in if self.activeSpeakerParticipant != nil && self.activeSpeakerParticipant!.address.equal(address2: cbValue.participantDevice.address!) { - let isMutedTmp = cbValue.isMuted - DispatchQueue.main.async { - self.activeSpeakerParticipant!.isMuted = isMutedTmp + self.activeSpeakerParticipant!.isMuted = cbValue.isMuted } } self.participantList.forEach({ participantDevice in if participantDevice.address.equal(address2: cbValue.participantDevice.address!) { - let isMutedTmp = cbValue.isMuted - DispatchQueue.main.async { - participantDevice.isMuted = isMutedTmp + participantDevice.isMuted = cbValue.isMuted } } }) @@ -543,25 +545,21 @@ class CallViewModel: ObservableObject { ) self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onParticipantDeviceStateChanged?.postOnMainQueue {(cbValue: (conference: Conference, device: ParticipantDevice, state: ParticipantDevice.State)) in + self.currentCall?.conference?.publisher?.onParticipantDeviceStateChanged?.postOnCoreQueue {(cbValue: (conference: Conference, device: ParticipantDevice, state: ParticipantDevice.State)) in Log.info( "[CallViewModel] Participant device \(cbValue.device.address!.asStringUriOnly()) state changed \(cbValue.state)" ) if self.activeSpeakerParticipant != nil && self.activeSpeakerParticipant!.address.equal(address2: cbValue.device.address!) { - let activeSpeakerParticipantOnPauseTmp = cbValue.state == .OnHold - let activeSpeakerParticipantIsJoiningTmp = cbValue.state == .Joining || cbValue.state == .Alerting DispatchQueue.main.async { - self.activeSpeakerParticipant!.onPause = activeSpeakerParticipantOnPauseTmp - self.activeSpeakerParticipant!.isJoining = activeSpeakerParticipantIsJoiningTmp + self.activeSpeakerParticipant!.onPause = cbValue.state == .OnHold + self.activeSpeakerParticipant!.isJoining = cbValue.state == .Joining || cbValue.state == .Alerting } } self.participantList.forEach({ participantDevice in if participantDevice.address.equal(address2: cbValue.device.address!) { - let participantDeviceOnPauseTmp = cbValue.state == .OnHold - let participantDeviceIsJoiningTmp = cbValue.state == .Joining || cbValue.state == .Alerting DispatchQueue.main.async { - participantDevice.onPause = participantDeviceOnPauseTmp - participantDevice.isJoining = participantDeviceIsJoiningTmp + participantDevice.onPause = cbValue.state == .OnHold + participantDevice.isJoining = cbValue.state == .Joining || cbValue.state == .Alerting } } }) @@ -569,7 +567,7 @@ class CallViewModel: ObservableObject { ) self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onParticipantAdminStatusChanged?.postOnMainQueue {(cbValue: (conference: Conference, participant: Participant)) in + self.currentCall?.conference?.publisher?.onParticipantAdminStatusChanged?.postOnCoreQueue {(cbValue: (conference: Conference, participant: Participant)) in let isAdmin = cbValue.participant.isAdmin if self.myParticipantModel != nil && self.myParticipantModel!.address.clone()!.equal(address2: cbValue.participant.address!) { DispatchQueue.main.async { @@ -587,7 +585,7 @@ class CallViewModel: ObservableObject { ) self.mConferenceSuscriptions.insert( - self.currentCall?.conference?.publisher?.onParticipantDeviceIsSpeakingChanged?.postOnMainQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice, isSpeaking: Bool)) in + self.currentCall?.conference?.publisher?.onParticipantDeviceIsSpeakingChanged?.postOnCoreQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice, isSpeaking: Bool)) in let isSpeaking = cbValue.participantDevice.isSpeaking if self.myParticipantModel != nil && self.myParticipantModel!.address.clone()!.equal(address2: cbValue.participantDevice.address!) { DispatchQueue.main.async { diff --git a/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift b/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift index 59ec6c20c..e59eee351 100644 --- a/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift +++ b/Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift @@ -71,17 +71,19 @@ class ContactAvatarModel: ObservableObject { } func addSubscription() { - friendSuscription = self.friend?.publisher?.onPresenceReceived?.postOnMainQueue { (cbValue: (Friend)) in - self.presenceStatus = cbValue.consolidatedPresence - if cbValue.consolidatedPresence == .Online || cbValue.consolidatedPresence == .Busy { - if cbValue.consolidatedPresence == .Online || cbValue.presenceModel!.latestActivityTimestamp != -1 { - self.lastPresenceInfo = cbValue.consolidatedPresence == .Online ? - "Online" : self.getCallTime(startDate: cbValue.presenceModel!.latestActivityTimestamp) + friendSuscription = self.friend?.publisher?.onPresenceReceived?.postOnCoreQueue { (cbValue: (Friend)) in + DispatchQueue.main.async { + self.presenceStatus = cbValue.consolidatedPresence + if cbValue.consolidatedPresence == .Online || cbValue.consolidatedPresence == .Busy { + if cbValue.consolidatedPresence == .Online || cbValue.presenceModel!.latestActivityTimestamp != -1 { + self.lastPresenceInfo = cbValue.consolidatedPresence == .Online ? + "Online" : self.getCallTime(startDate: cbValue.presenceModel!.latestActivityTimestamp) + } else { + self.lastPresenceInfo = "Away" + } } else { - self.lastPresenceInfo = "Away" + self.lastPresenceInfo = "" } - } else { - self.lastPresenceInfo = "" } } } diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift index ffeb7deef..fc797a25f 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift @@ -51,7 +51,7 @@ class ConversationViewModel: ObservableObject { self.getNewMessages(eventLogs: [cbValue.eventLog]) }) - self.chatRoomSuscriptions.insert(self.displayedConversation?.chatRoom.publisher?.onChatMessagesReceived?.postOnMainQueue { (cbValue: (chatRoom: ChatRoom, eventLogs: [EventLog])) in + self.chatRoomSuscriptions.insert(self.displayedConversation?.chatRoom.publisher?.onChatMessagesReceived?.postOnCoreQueue { (cbValue: (chatRoom: ChatRoom, eventLogs: [EventLog])) in self.getNewMessages(eventLogs: cbValue.eventLogs) }) } diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift index 7ed96c4e2..2b9b18d07 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationsListViewModel.swift @@ -81,7 +81,7 @@ class ConversationsListViewModel: ObservableObject { func addConversationDelegate() { coreContext.doOnCoreQueue { core in - self.mCoreSuscriptions.insert(core.publisher?.onChatRoomStateChanged?.postOnMainQueue { (cbValue: (core: Core, chatRoom: ChatRoom, state: ChatRoom.State)) in + self.mCoreSuscriptions.insert(core.publisher?.onChatRoomStateChanged?.postOnCoreQueue { (cbValue: (core: Core, chatRoom: ChatRoom, state: ChatRoom.State)) in //Log.info("[ConversationsListViewModel] Conversation [${LinphoneUtils.getChatRoomId(chatRoom)}] state changed [$state]") switch cbValue.state { case ChatRoom.State.Created: @@ -96,11 +96,11 @@ class ConversationsListViewModel: ObservableObject { } }) - self.mCoreSuscriptions.insert(core.publisher?.onMessageSent?.postOnMainQueue { _ in + self.mCoreSuscriptions.insert(core.publisher?.onMessageSent?.postOnCoreQueue { _ in self.computeChatRoomsList(filter: "") }) - self.mCoreSuscriptions.insert(core.publisher?.onMessagesReceived?.postOnMainQueue { _ in + self.mCoreSuscriptions.insert(core.publisher?.onMessagesReceived?.postOnCoreQueue { _ in self.computeChatRoomsList(filter: "") }) } diff --git a/Linphone/Utils/MagicSearchSingleton.swift b/Linphone/Utils/MagicSearchSingleton.swift index cf23e5905..03b3e4c7b 100644 --- a/Linphone/Utils/MagicSearchSingleton.swift +++ b/Linphone/Utils/MagicSearchSingleton.swift @@ -54,7 +54,7 @@ final class MagicSearchSingleton: ObservableObject { self.magicSearch = try? core.createMagicSearch() self.magicSearch.limitedSearch = false - self.searchSubscription = self.magicSearch.publisher?.onSearchResultsReceived?.postOnMainQueue { (magicSearch: MagicSearch) in + self.searchSubscription = self.magicSearch.publisher?.onSearchResultsReceived?.postOnCoreQueue { (magicSearch: MagicSearch) in self.needUpdateLastSearchContacts = true var lastSearchFriend: [SearchResult] = [] @@ -68,36 +68,38 @@ final class MagicSearchSingleton: ObservableObject { } } - self.contactsManager.lastSearch = lastSearchFriend.sorted(by: { - $0.friend!.name!.lowercased().folding(options: .diacriticInsensitive, locale: .current) - < - $1.friend!.name!.lowercased().folding(options: .diacriticInsensitive, locale: .current) - }) - - self.contactsManager.lastSearchSuggestions = lastSearchSuggestions.sorted(by: { - $0.address!.asStringUriOnly() < $1.address!.asStringUriOnly() - }) - - self.contactsManager.avatarListModel.forEach { contactAvatarModel in - contactAvatarModel.removeAllSuscription() - } - - self.contactsManager.avatarListModel.removeAll() - - self.contactsManager.lastSearch.forEach { searchResult in - if searchResult.friend != nil { - self.contactsManager.avatarListModel.append( - ContactAvatarModel( - friend: searchResult.friend!, - name: searchResult.friend?.name ?? "", - address: searchResult.friend?.address?.clone()?.asStringUriOnly() ?? "", - withPresence: true - ) - ) + DispatchQueue.main.async { + self.contactsManager.lastSearch = lastSearchFriend.sorted(by: { + $0.friend!.name!.lowercased().folding(options: .diacriticInsensitive, locale: .current) + < + $1.friend!.name!.lowercased().folding(options: .diacriticInsensitive, locale: .current) + }) + + self.contactsManager.lastSearchSuggestions = lastSearchSuggestions.sorted(by: { + $0.address!.asStringUriOnly() < $1.address!.asStringUriOnly() + }) + + self.contactsManager.avatarListModel.forEach { contactAvatarModel in + contactAvatarModel.removeAllSuscription() } + + self.contactsManager.avatarListModel.removeAll() + + self.contactsManager.lastSearch.forEach { searchResult in + if searchResult.friend != nil { + self.contactsManager.avatarListModel.append( + ContactAvatarModel( + friend: searchResult.friend!, + name: searchResult.friend?.name ?? "", + address: searchResult.friend?.address?.clone()?.asStringUriOnly() ?? "", + withPresence: true + ) + ) + } + } + + NotificationCenter.default.post(name: NSNotification.Name("ContactLoaded"), object: nil) } - - NotificationCenter.default.post(name: NSNotification.Name("ContactLoaded"), object: nil) } } }