Fix avatar refresh after image download

This commit is contained in:
Benoit Martins 2024-06-03 17:25:46 +02:00
parent 088f3a7506
commit 1b879a5c61
10 changed files with 126 additions and 132 deletions

View file

@ -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()
}
}
}

View file

@ -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 {

View file

@ -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")

View file

@ -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
}
}
}

View file

@ -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()
}
}

View file

@ -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 {

View file

@ -34,21 +34,21 @@ struct ConversationsListFragment: View {
List {
ForEach(0..<conversationsListViewModel.conversationsList.count, id: \.self) { index in
HStack {
Avatar(contactAvatarModel: conversationsListViewModel.conversationsList[index].avatarModel, avatarSize: 50)
Avatar(contactAvatarModel: conversationsListViewModel.conversationsList[index].avatarModel, avatarSize: 50)
VStack(spacing: 0) {
Spacer()
VStack(spacing: 0) {
Spacer()
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].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)

View file

@ -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<Boolean>()
//self.lastMessage: ChatMessage? = null
self.avatarModel = ContactAvatarModel(friend: nil, name: chatRoom.subject ?? "", address: chatRoom.peerAddress?.asStringUriOnly() ?? "", withPresence: false)
getContentTextMessage()
getChatRoomSubject()

View file

@ -205,5 +205,7 @@ class ConversationsListViewModel: ObservableObject {
conversationsList.forEach { conversationModel in
conversationModel.refreshAvatarModel()
}
reorderChatRooms()
}
}

View file

@ -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: {})