diff --git a/Linphone/Contacts/ContactsManager.swift b/Linphone/Contacts/ContactsManager.swift index 7c27db878..6a7eeab6f 100644 --- a/Linphone/Contacts/ContactsManager.swift +++ b/Linphone/Contacts/ContactsManager.swift @@ -46,11 +46,12 @@ final class ContactsManager: ObservableObject { private var coreDelegate: CoreDelegate? private var friendListDelegate: FriendListDelegate? + private var magicSearchDelegate: MagicSearchDelegate? private init() {} func fetchContacts() { - coreContext.doOnCoreQueue { core in + self.coreContext.doOnCoreQueue { core in if core.globalState == GlobalState.Shutdown || core.globalState == GlobalState.Off { print("\(#function) - Core is being stopped or already destroyed, abort") } else { @@ -91,12 +92,12 @@ final class ContactsManager: ObservableObject { } } - MagicSearchSingleton.shared.searchForContactsWithoutCoreThread(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) - let store = CNContactStore() store.requestAccess(for: .contacts) { (granted, error) in if let error = error { print("\(#function) - failed to request access", error) + self.addFriendListDelegate() + self.addCoreDelegate(core: core) return } if granted { @@ -105,10 +106,16 @@ final class ContactsManager: ObservableObject { CNContactPostalAddressesKey, CNContactIdentifierKey, CNInstantMessageAddressUsernameKey, CNContactInstantMessageAddressesKey, CNContactOrganizationNameKey, CNContactImageDataAvailableKey, CNContactImageDataKey, CNContactThumbnailImageDataKey] + let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor]) + + let dispatchGroup = DispatchGroup() + do { - var contactCounter = 0 try store.enumerateContacts(with: request, usingBlock: { (contact, _) in + + dispatchGroup.enter() + let newContact = Contact( identifier: contact.identifier, firstName: contact.givenName, @@ -129,51 +136,7 @@ final class ContactsManager: ObservableObject { name: contact.givenName + contact.familyName, prefix: "", contact: newContact, linphoneFriend: false, existingFriend: nil) { - if (self.friendList?.friends.count ?? 0) == contactCounter { - // Every contact properly added, proceed - self.linphoneFriendList?.updateSubscriptions() - self.friendList?.updateSubscriptions() - - if let friendListDelegate = self.friendListDelegate { - self.friendList?.removeDelegate(delegate: friendListDelegate) - } - - self.friendListDelegate = FriendListDelegateStub(onNewSipAddressDiscovered: { (_: FriendList, linphoneFriend: Friend, sipUri: String) in - var addedAvatarListModel: [ContactAvatarModel] = [] - linphoneFriend.phoneNumbers.forEach { _ in - let address = try? Factory.Instance.createAddress(addr: sipUri) - if address != nil { - linphoneFriend.edit() - linphoneFriend.addAddress(address: address!) - linphoneFriend.done() - - let addressTmp = linphoneFriend.address?.clone()?.asStringUriOnly() ?? "" - addedAvatarListModel.append( - ContactAvatarModel( - friend: linphoneFriend, - name: linphoneFriend.name ?? "", - address: addressTmp, - withPresence: true - ) - ) - - DispatchQueue.main.async { - NotificationCenter.default.post( - name: NSNotification.Name("ContactAdded"), - object: nil, - userInfo: ["address": addressTmp] - ) - } - } - } - - DispatchQueue.main.async { - self.avatarListModel += addedAvatarListModel - self.avatarListModel = self.avatarListModel.sorted { $0.name < $1.name } - } - }) - self.friendList?.addDelegate(delegate: self.friendListDelegate!) - } + dispatchGroup.leave() } } } else { @@ -183,70 +146,30 @@ final class ContactsManager: ObservableObject { name: contact.givenName + contact.familyName, prefix: "-default", contact: newContact, linphoneFriend: false, existingFriend: nil) { - if (self.friendList?.friends.count ?? 0) == contactCounter { - // Every contact properly added, proceed - self.linphoneFriendList?.updateSubscriptions() - self.friendList?.updateSubscriptions() - - if let friendListDelegate = self.friendListDelegate { - self.friendList?.removeDelegate(delegate: friendListDelegate) - } - - self.friendListDelegate = FriendListDelegateStub(onNewSipAddressDiscovered: { (_: FriendList, linphoneFriend: Friend, sipUri: String) in - var addedAvatarListModel: [ContactAvatarModel] = [] - linphoneFriend.phoneNumbers.forEach { _ in - let address = try? Factory.Instance.createAddress(addr: sipUri) - if address != nil { - linphoneFriend.edit() - linphoneFriend.addAddress(address: address!) - linphoneFriend.done() - - let addressTmp = linphoneFriend.address?.clone()?.asStringUriOnly() ?? "" - addedAvatarListModel.append( - ContactAvatarModel( - friend: linphoneFriend, - name: linphoneFriend.name ?? "", - address: addressTmp, - withPresence: true - ) - ) - - DispatchQueue.main.async { - NotificationCenter.default.post( - name: NSNotification.Name("ContactAdded"), - object: nil, - userInfo: ["address": addressTmp] - ) - } - } - } - - DispatchQueue.main.async { - self.avatarListModel += addedAvatarListModel - self.avatarListModel = self.avatarListModel.sorted { $0.name < $1.name } - } - }) - self.friendList?.addDelegate(delegate: self.friendListDelegate!) - } + dispatchGroup.leave() } } } - - if !(contact.givenName.isEmpty && contact.familyName.isEmpty) { - contactCounter += 1 - } }) + dispatchGroup.notify(queue: .main) { + self.addFriendListDelegate() + self.addCoreDelegate(core: core) + MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + } } catch let error { print("\(#function) - Failed to enumerate contact", error) + self.addFriendListDelegate() + self.addCoreDelegate(core: core) + MagicSearchSingleton.shared.searchForContactsWithoutCoreThread(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) } - } else { print("\(#function) - access denied") + self.addFriendListDelegate() + self.addCoreDelegate(core: core) + MagicSearchSingleton.shared.searchForContactsWithoutCoreThread(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) } } - - self.addCoreDelegate(core: core) } } @@ -459,6 +382,106 @@ final class ContactsManager: ObservableObject { } } + func addFriendListDelegate() { + self.linphoneFriendList?.updateSubscriptions() + self.friendList?.updateSubscriptions() + CoreContext.shared.mCore.friendsLists.forEach { friendList in + friendList.updateSubscriptions() + } + + if let friendListDelegate = self.friendListDelegate { + CoreContext.shared.mCore.friendsLists.forEach { friendList in + friendList.removeDelegate(delegate: friendListDelegate) + } + } + + self.friendListDelegate = FriendListDelegateStub( + onContactCreated: { (friendList: FriendList, linphoneFriend: Friend) in + Log.info("\(ContactsManager.TAG) FriendListDelegateStub onContactCreated") + }, + onContactDeleted: { (friendList: FriendList, linphoneFriend: Friend) in + Log.info("\(ContactsManager.TAG) FriendListDelegateStub onContactDeleted") + }, + onContactUpdated: { (friendList: FriendList, newFriend: Friend, oldFriend: Friend) in + Log.info("\(ContactsManager.TAG) FriendListDelegateStub onContactUpdated") + }, + onSyncStatusChanged: { (friendList: FriendList, status: FriendList.SyncStatus?, message: String?) in + Log.info("\(ContactsManager.TAG) FriendListDelegateStub onSyncStatusChanged") + if status == .Successful { + friendList.friends.forEach { friend in + let addressTmp = friend.address?.clone()?.asStringUriOnly() ?? "" + + let newContact = Contact( + identifier: UUID().uuidString, + firstName: friend.name ?? addressTmp, + lastName: "", + organizationName: "", + jobTitle: "", + displayName: friend.address?.displayName ?? "", + sipAddresses: friend.addresses.map { $0.asStringUriOnly() }, + phoneNumbers: [], + imageData: "" + ) + + self.textToImageInMainThread(firstName: friend.name ?? addressTmp, lastName: "") { image in + self.saveImage( + image: image, + name: friend.name ?? addressTmp, + prefix: "-default", + contact: newContact, linphoneFriend: false, existingFriend: friend) { + + } + } + } + } + + MagicSearchSingleton.shared.searchForContactsWithoutCoreThread(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + }, + onPresenceReceived: { (friendList: FriendList, friends: [Friend?]) in + Log.info("\(ContactsManager.TAG) FriendListDelegateStub onPresenceReceived \(friends.count)") + }, + onNewSipAddressDiscovered: { (_: FriendList, linphoneFriend: Friend, sipUri: String) in + Log.info("\(ContactsManager.TAG) FriendListDelegateStub onNewSipAddressDiscovered \(linphoneFriend.name ?? "")") + var addedAvatarListModel: [ContactAvatarModel] = [] + linphoneFriend.phoneNumbers.forEach { _ in + let address = try? Factory.Instance.createAddress(addr: sipUri) + if address != nil { + linphoneFriend.edit() + linphoneFriend.addAddress(address: address!) + linphoneFriend.done() + + let addressTmp = linphoneFriend.address?.clone()?.asStringUriOnly() ?? "" + addedAvatarListModel.append( + ContactAvatarModel( + friend: linphoneFriend, + name: linphoneFriend.name ?? "", + address: addressTmp, + withPresence: true + ) + ) + + DispatchQueue.main.async { + NotificationCenter.default.post( + name: NSNotification.Name("ContactAdded"), + object: nil, + userInfo: ["address": addressTmp] + ) + } + } + } + + DispatchQueue.main.async { + self.avatarListModel += addedAvatarListModel + self.avatarListModel = self.avatarListModel.sorted { $0.name < $1.name } + } + } + ) + + CoreContext.shared.mCore.friendsLists.forEach { friendList in + friendList.addDelegate(delegate: self.friendListDelegate!) + } + } + func addCoreDelegate(core: Core) { self.coreDelegate = CoreDelegateStub( onFriendListCreated: { (_: Core, friendList: FriendList) in diff --git a/Linphone/Core/CoreContext.swift b/Linphone/Core/CoreContext.swift index f01e2f2ac..37535c9be 100644 --- a/Linphone/Core/CoreContext.swift +++ b/Linphone/Core/CoreContext.swift @@ -282,6 +282,9 @@ final class CoreContext: ObservableObject { switch state { case .Ok: + DispatchQueue.main.async { + NotificationCenter.default.post(name: NSNotification.Name("CoreStarted"), object: nil) + } ContactsManager.shared.fetchContacts() if self.mCore.consolidatedPresence != ConsolidatedPresence.Online { self.updatePresence(core: self.mCore, presence: ConsolidatedPresence.Online) diff --git a/Linphone/UI/Main/ContentView.swift b/Linphone/UI/Main/ContentView.swift index 6068dcb9e..7f5c6bc84 100644 --- a/Linphone/UI/Main/ContentView.swift +++ b/Linphone/UI/Main/ContentView.swift @@ -82,15 +82,18 @@ struct ContentView: View { private let avatarSize = 45.0 @State private var imagePath: URL? + @State private var imageTmp: Image? var body: some View { - let pub = NotificationCenter.default + let contactLoaded = NotificationCenter.default .publisher(for: NSNotification.Name("ContactLoaded")) - let pub2 = NotificationCenter.default + let contactAdded = NotificationCenter.default .publisher(for: NSNotification.Name("ContactAdded")) .compactMap { $0.userInfo?["address"] as? String } let imageChanged = NotificationCenter.default .publisher(for: NSNotification.Name("ImageChanged")) + let coreStarted = NotificationCenter.default + .publisher(for: NSNotification.Name("CoreStarted")) GeometryReader { geometry in VStack(spacing: 0) { if (telecomManager.callInProgress && !fullscreenVideo && ((!telecomManager.callDisplayed && callViewModel.callsCounter == 1) || callViewModel.callsCounter > 1)) || isShowConversationFragment { @@ -316,7 +319,8 @@ struct ContentView: View { VStack(spacing: 0) { if searchIsActive == false { HStack { - if (accountProfileViewModel.accountModelIndex ?? 0) < CoreContext.shared.accounts.count { + if let accountModelIndex = accountProfileViewModel.accountModelIndex, + accountModelIndex < CoreContext.shared.accounts.count { AsyncImage(url: imagePath) { image in switch image { case .empty: @@ -328,13 +332,31 @@ struct ContentView: View { .aspectRatio(contentMode: .fill) .frame(width: avatarSize, height: avatarSize) .clipShape(Circle()) + .onAppear { + imageTmp = image + } case .failure: - Image(uiImage: contactsManager.textToImage( - firstName: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex ?? 0].avatarModel?.name ?? "", - lastName: "")) - .resizable() - .frame(width: avatarSize, height: avatarSize) - .clipShape(Circle()) + if CoreContext.shared.accounts[accountModelIndex].avatarModel != nil { + let tmpImage = contactsManager.textToImage( + firstName: CoreContext.shared.accounts[accountModelIndex].avatarModel!.name, + lastName: "") + Image(uiImage: tmpImage) + .resizable() + .frame(width: avatarSize, height: avatarSize) + .clipShape(Circle()) + .onAppear { + accountProfileViewModel.saveImage(image: tmpImage, name: CoreContext.shared.accounts[accountModelIndex].avatarModel!.name, prefix: "-default") + } + } else if let cachedImage = imageTmp { + cachedImage + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: avatarSize, height: avatarSize) + .clipShape(Circle()) + } else { + ProgressView() + .frame(width: avatarSize, height: avatarSize) + } @unknown default: EmptyView() } @@ -343,17 +365,13 @@ struct ContentView: View { openMenu() } .onAppear { - if let accountModelIndex = accountProfileViewModel.accountModelIndex, - accountModelIndex < CoreContext.shared.accounts.count { - let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath() - if !(imagePathTmp.lastPathComponent.isEmpty || imagePathTmp.lastPathComponent == "Error" || imagePathTmp.lastPathComponent == "ImageError.png") { - imagePath = imagePathTmp - } + let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath() + if !(imagePathTmp.lastPathComponent.isEmpty || imagePathTmp.lastPathComponent == "Error" || imagePathTmp.lastPathComponent == "ImageError.png") { + imagePath = imagePathTmp } } - .onChange(of: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex ?? 0].usernaneAvatar) { _ in - if let accountModelIndex = accountProfileViewModel.accountModelIndex, - accountModelIndex < CoreContext.shared.accounts.count { + .onChange(of: CoreContext.shared.accounts[accountModelIndex].usernaneAvatar) { username in + if !username.isEmpty { let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath() if !(imagePathTmp.lastPathComponent.isEmpty || imagePathTmp.lastPathComponent == "Error" || imagePathTmp.lastPathComponent == "ImageError.png") { sharedMainViewModel.changeDefaultAvatar(defaultAvatarURL: imagePathTmp) @@ -362,8 +380,7 @@ struct ContentView: View { } } .onReceive(imageChanged) { _ in - if let accountModelIndex = accountProfileViewModel.accountModelIndex, - accountModelIndex < CoreContext.shared.accounts.count { + if !CoreContext.shared.accounts[accountModelIndex].usernaneAvatar.isEmpty { let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath() sharedMainViewModel.changeDefaultAvatar(defaultAvatarURL: imagePathTmp) imagePath = imagePathTmp @@ -1366,13 +1383,16 @@ struct ContentView: View { self.index = 2 } } - .onReceive(pub) { _ in + .onReceive(contactLoaded) { _ in conversationsListViewModel.updateChatRoomsList() historyListViewModel.refreshHistoryAvatarModel() } - .onReceive(pub2) { address in + .onReceive(contactAdded) { address in conversationsListViewModel.updateChatRoom(address: address) } + .onReceive(coreStarted) { _ in + accountProfileViewModel.setAvatarModel() + } } .overlay { if isMenuOpen { @@ -1396,7 +1416,6 @@ struct ContentView: View { orientation = UIDevice.current.orientation if newPhase == .active { conversationsListViewModel.computeChatRoomsList(filter: "") - accountProfileViewModel.setAvatarModel() } } } diff --git a/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift b/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift index 71b303f3b..d78c9ed41 100644 --- a/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift +++ b/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift @@ -34,36 +34,38 @@ class AccountProfileViewModel: ObservableObject { func saveChangesWhenLeaving() { if accountModelIndex != nil { CoreContext.shared.doOnCoreQueue { _ in - let displayNameAccountModel = CoreContext.shared.accounts[self.accountModelIndex!].displayNameAvatar - let newParams = CoreContext.shared.accounts[self.accountModelIndex!].account.params?.clone() - if (displayNameAccountModel != newParams?.identityAddress?.displayName) - && (newParams?.identityAddress?.displayName != nil || !displayNameAccountModel.isEmpty) { - if let newIdentityAddress = newParams?.identityAddress?.clone() { - try? newIdentityAddress.setDisplayname(newValue: displayNameAccountModel) - try? newParams?.setIdentityaddress(newValue: newIdentityAddress) - } - - if self.getImagePath().lastPathComponent.contains("-default") || self.getImagePath().lastPathComponent == "Documents" { - let usernameTmp = CoreContext.shared.accounts[self.accountModelIndex!].usernaneAvatar + if self.accountModelIndex! < CoreContext.shared.accounts.count { + let displayNameAccountModel = CoreContext.shared.accounts[self.accountModelIndex!].displayNameAvatar + let newParams = CoreContext.shared.accounts[self.accountModelIndex!].account.params?.clone() + if (displayNameAccountModel != newParams?.identityAddress?.displayName) + && (newParams?.identityAddress?.displayName != nil || !displayNameAccountModel.isEmpty) { + if let newIdentityAddress = newParams?.identityAddress?.clone() { + try? newIdentityAddress.setDisplayname(newValue: displayNameAccountModel) + try? newParams?.setIdentityaddress(newValue: newIdentityAddress) + } - DispatchQueue.main.async { - self.saveImage( - image: ContactsManager.shared.textToImage( - firstName: displayNameAccountModel.isEmpty ? usernameTmp : displayNameAccountModel, lastName: ""), - name: usernameTmp, - prefix: "-default") + if self.getImagePath().lastPathComponent.contains("-default") || self.getImagePath().lastPathComponent == "Documents" { + let usernameTmp = CoreContext.shared.accounts[self.accountModelIndex!].usernaneAvatar + + DispatchQueue.main.async { + self.saveImage( + image: ContactsManager.shared.textToImage( + firstName: displayNameAccountModel.isEmpty ? usernameTmp : displayNameAccountModel, lastName: ""), + name: usernameTmp, + prefix: "-default") + } } } + + if self.dialPlanSelected != nil + && (self.dialPlanSelected!.countryCallingCode != newParams?.internationalPrefix || self.dialPlanSelected!.isoCountryCode != newParams?.internationalPrefixIsoCountryCode) { + newParams?.internationalPrefix = self.dialPlanSelected?.countryCallingCode + newParams?.internationalPrefixIsoCountryCode = self.dialPlanSelected?.isoCountryCode + newParams?.useInternationalPrefixForCallsAndChats = true + } + + CoreContext.shared.accounts[self.accountModelIndex!].account.params = newParams } - - if self.dialPlanSelected != nil - && (self.dialPlanSelected!.countryCallingCode != newParams?.internationalPrefix || self.dialPlanSelected!.isoCountryCode != newParams?.internationalPrefixIsoCountryCode) { - newParams?.internationalPrefix = self.dialPlanSelected?.countryCallingCode - newParams?.internationalPrefixIsoCountryCode = self.dialPlanSelected?.isoCountryCode - newParams?.useInternationalPrefixForCallsAndChats = true - } - - CoreContext.shared.accounts[self.accountModelIndex!].account.params = newParams } } } @@ -118,7 +120,7 @@ class AccountProfileViewModel: ObservableObject { return } - let photoAvatarModelKey = "photo_avatar_model" + CoreContext.shared.accounts[self.accountModelIndex!].usernaneAvatar + let photoAvatarModelKey = CoreContext.shared.accounts[self.accountModelIndex!].usernaneAvatar ContactsManager.shared.awaitDataWrite(data: data, name: name, prefix: prefix) { _, result in UserDefaults.standard.set(result, forKey: photoAvatarModelKey) diff --git a/Linphone/UI/Main/Viewmodel/AccountModel.swift b/Linphone/UI/Main/Viewmodel/AccountModel.swift index 03581dcb1..7536bc98b 100644 --- a/Linphone/UI/Main/Viewmodel/AccountModel.swift +++ b/Linphone/UI/Main/Viewmodel/AccountModel.swift @@ -98,47 +98,55 @@ class AccountModel: ObservableObject { let preferences = UserDefaults.standard - let photoAvatarModelKey = "photo_avatar_model" + usernaneAvatarTmp + let photoAvatarModelKey = usernaneAvatarTmp - if preferences.object(forKey: photoAvatarModelKey) == nil { - preferences.set(photoAvatarModelKey, forKey: photoAvatarModelKey) - } else { - photoAvatarModelTmp = preferences.string(forKey: photoAvatarModelKey)! - } - - DispatchQueue.main.async { [self] in - switch state { - case .Cleared, .None: - humanReadableRegistrationState = "drawer_menu_account_connection_status_cleared".localized() - summary = "manage_account_status_cleared_summary".localized() - registrationStateAssociatedUIColor = .orangeWarning600 - case .Progress: - humanReadableRegistrationState = "drawer_menu_account_connection_status_progress".localized() - summary = "manage_account_status_progress_summary".localized() - registrationStateAssociatedUIColor = .greenSuccess500 - case .Failed: - humanReadableRegistrationState = "drawer_menu_account_connection_status_failed".localized() - summary = "manage_account_status_failed_summary".localized() - registrationStateAssociatedUIColor = .redDanger500 - case .Ok: - humanReadableRegistrationState = "drawer_menu_account_connection_status_connected".localized() - summary = "manage_account_status_connected_summary".localized() - registrationStateAssociatedUIColor = .greenSuccess500 - case .Refreshing: - humanReadableRegistrationState = "drawer_menu_account_connection_status_refreshing".localized() - summary = "manage_account_status_progress_summary".localized() - registrationStateAssociatedUIColor = .grayMain2c500 + if !photoAvatarModelKey.isEmpty { + if preferences.object(forKey: photoAvatarModelKey) == nil { + DispatchQueue.main.async { + self.saveImage( + image: ContactsManager.shared.textToImage( + firstName: usernaneAvatarTmp, lastName: ""), + name: usernaneAvatarTmp, + prefix: "-default") + } + } else { + photoAvatarModelTmp = preferences.string(forKey: photoAvatarModelKey)! } - isRegistrered = state == .Ok - isDefaultAccount = isDefault - self.displayName = displayName - address.map {self.address = $0} - - photoAvatarModel = photoAvatarModelTmp - displayNameAvatar = displayNameTmp - usernaneAvatar = usernaneAvatarTmp - imagePathAvatar = getImagePath() + DispatchQueue.main.async { [self] in + switch state { + case .Cleared, .None: + humanReadableRegistrationState = "drawer_menu_account_connection_status_cleared".localized() + summary = "manage_account_status_cleared_summary".localized() + registrationStateAssociatedUIColor = .orangeWarning600 + case .Progress: + humanReadableRegistrationState = "drawer_menu_account_connection_status_progress".localized() + summary = "manage_account_status_progress_summary".localized() + registrationStateAssociatedUIColor = .greenSuccess500 + case .Failed: + humanReadableRegistrationState = "drawer_menu_account_connection_status_failed".localized() + summary = "manage_account_status_failed_summary".localized() + registrationStateAssociatedUIColor = .redDanger500 + case .Ok: + humanReadableRegistrationState = "drawer_menu_account_connection_status_connected".localized() + summary = "manage_account_status_connected_summary".localized() + registrationStateAssociatedUIColor = .greenSuccess500 + case .Refreshing: + humanReadableRegistrationState = "drawer_menu_account_connection_status_refreshing".localized() + summary = "manage_account_status_progress_summary".localized() + registrationStateAssociatedUIColor = .grayMain2c500 + } + + isRegistrered = state == .Ok + isDefaultAccount = isDefault + self.displayName = displayName + address.map {self.address = $0} + + photoAvatarModel = photoAvatarModelTmp + displayNameAvatar = displayNameTmp + usernaneAvatar = usernaneAvatarTmp + imagePathAvatar = getImagePath() + } } } @@ -248,6 +256,28 @@ class AccountModel: ObservableObject { core.removeAccount(account: self.account) } } + + func saveImage(image: UIImage, name: String, prefix: String) { + guard let data = image.jpegData(compressionQuality: 1) ?? image.pngData() else { + return + } + + let photoAvatarModelKey = name + + ContactsManager.shared.awaitDataWrite(data: data, name: name, prefix: prefix) { _, result in + UserDefaults.standard.set(result, forKey: photoAvatarModelKey) + + self.photoAvatarModel = "" + self.imagePathAvatar = nil + NotificationCenter.default.post(name: NSNotification.Name("ImageChanged"), object: nil) + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + self.photoAvatarModel = result + self.imagePathAvatar = self.getImagePath() + NotificationCenter.default.post(name: NSNotification.Name("ImageChanged"), object: nil) + } + } + } } class AccountDeviceModel: ObservableObject {