From 284b0433d85d54656b27efec9942bad20b9dfeb2 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 10 Dec 2024 18:29:42 +0100 Subject: [PATCH] Change Account profile --- Linphone/Localizable.xcstrings | 17 ++++ .../Viewmodel/RegisterViewModel.swift | 16 +++- Linphone/UI/Main/ContentView.swift | 1 + .../Fragments/AccountProfileFragment.swift | 89 ++++++++++++++++++- .../ViewModel/AccountProfileViewModel.swift | 65 +++++++++++++- 5 files changed, 180 insertions(+), 8 deletions(-) diff --git a/Linphone/Localizable.xcstrings b/Linphone/Localizable.xcstrings index 92b8da993..5f68bafe7 100644 --- a/Linphone/Localizable.xcstrings +++ b/Linphone/Localizable.xcstrings @@ -3797,6 +3797,23 @@ } } }, + "manage_account_details_title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Details" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Détails" + } + } + } + }, "manage_account_edit_picture" : { "localizations" : { "en" : { diff --git a/Linphone/UI/Assistant/Viewmodel/RegisterViewModel.swift b/Linphone/UI/Assistant/Viewmodel/RegisterViewModel.swift index 186a980d7..205d5f4d5 100644 --- a/Linphone/UI/Assistant/Viewmodel/RegisterViewModel.swift +++ b/Linphone/UI/Assistant/Viewmodel/RegisterViewModel.swift @@ -207,15 +207,25 @@ class RegisterViewModel: ObservableObject { func getDialPlansList() { coreContext.doOnCoreQueue { _ in let dialPlans = Factory.Instance.dialPlans + var dialPlansListTmp: [DialPlan] = [] + var dialPlansLabelListTmp: [String] = [] + var dialPlansShortLabelListTmp: [String] = [] + dialPlans.forEach { dialPlan in - self.dialPlansList.append(dialPlan) - self.dialPlansLabelList.append( + dialPlansListTmp.append(dialPlan) + dialPlansLabelListTmp.append( "\(dialPlan.flag) \(dialPlan.country) | +\(dialPlan.countryCallingCode)" ) - self.dialPlansShortLabelList.append( + dialPlansShortLabelListTmp.append( "\(dialPlan.flag) +\(dialPlan.countryCallingCode)" ) } + + DispatchQueue.main.async { + self.dialPlansList = dialPlansListTmp + self.dialPlansLabelList = dialPlansLabelListTmp + self.dialPlansShortLabelList = dialPlansShortLabelListTmp + } } } diff --git a/Linphone/UI/Main/ContentView.swift b/Linphone/UI/Main/ContentView.swift index ab0f56d36..6e6728ad6 100644 --- a/Linphone/UI/Main/ContentView.swift +++ b/Linphone/UI/Main/ContentView.swift @@ -1168,6 +1168,7 @@ struct ContentView: View { if isShowAccountProfileFragment { AccountProfileFragment( accountProfileViewModel: accountProfileViewModel, + registerViewModel: RegisterViewModel(), isShowAccountProfileFragment: $isShowAccountProfileFragment ) .zIndex(3) diff --git a/Linphone/UI/Main/Settings/Fragments/AccountProfileFragment.swift b/Linphone/UI/Main/Settings/Fragments/AccountProfileFragment.swift index 65afab9ba..a62224db6 100644 --- a/Linphone/UI/Main/Settings/Fragments/AccountProfileFragment.swift +++ b/Linphone/UI/Main/Settings/Fragments/AccountProfileFragment.swift @@ -18,6 +18,7 @@ */ import SwiftUI +import UniformTypeIdentifiers struct AccountProfileFragment: View { @@ -25,6 +26,7 @@ struct AccountProfileFragment: View { @ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared @ObservedObject var accountProfileViewModel: AccountProfileViewModel + @ObservedObject var registerViewModel: RegisterViewModel @Binding var isShowAccountProfileFragment: Bool @State var detailIsOpen: Bool = true @@ -33,6 +35,8 @@ struct AccountProfileFragment: View { @State private var selectedImage: UIImage? @State private var removedImage = false + @FocusState var isDisplayNameFocused: Bool + private let avatarSize = 100.0 var body: some View { @@ -53,6 +57,7 @@ struct AccountProfileFragment: View { .padding(.top, 4) .padding(.leading, -10) .onTapGesture { + accountProfileViewModel.saveChangesWhenLeaving() withAnimation { if isShowAccountProfileFragment { isShowAccountProfileFragment = false @@ -233,7 +238,7 @@ struct AccountProfileFragment: View { } HStack(alignment: .center) { - Text("conversation_info_participants_list_title") + Text("manage_account_details_title") .default_text_style_800(styleSize: 18) .frame(maxWidth: .infinity, alignment: .leading) @@ -258,7 +263,87 @@ struct AccountProfileFragment: View { if detailIsOpen { VStack(spacing: 0) { - + VStack(spacing: 30) { + HStack { + Text(String(localized: "sip_address") + ":") + .default_text_style_600(styleSize: 14) + + Text(accountProfileViewModel.avatarModel!.address) + .foregroundStyle(Color.grayMain2c700) + .default_text_style(styleSize: 14) + .frame(maxWidth: .infinity, alignment: .leading) + .lineLimit(1) + + Button(action: { + UIPasteboard.general.setValue( + accountProfileViewModel.avatarModel!.address, + forPasteboardType: UTType.plainText.identifier + ) + + ToastViewModel.shared.toastMessage = "Success_address_copied_into_clipboard" + ToastViewModel.shared.displayToast.toggle() + }, label: { + Image("copy") + .resizable() + .frame(width: 20, height: 20) + }) + } + + VStack(alignment: .leading) { + Text("sip_address_display_name") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + TextField(accountProfileViewModel.displayName, text: $accountProfileViewModel.displayName) + .default_text_style(styleSize: 15) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .background(.white) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isDisplayNameFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1) + ) + .focused($isDisplayNameFocused) + } + + VStack(alignment: .leading) { + Text("sip_address_display_name") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + Menu { + Picker("", selection: $accountProfileViewModel.dialPlanValueSelected) { + ForEach(registerViewModel.dialPlansLabelList, id: \.self) { dialPlan in + Text(dialPlan).tag(dialPlan) + } + } + } label: { + HStack { + Text(accountProfileViewModel.dialPlanValueSelected) + .default_text_style(styleSize: 15) + .frame(maxWidth: .infinity, alignment: .leading) + + Image("caret-down") + .resizable() + .frame(width: 20, height: 20) + } + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .background(.white) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.gray200, lineWidth: 1) + ) + } + } + } + .padding(.vertical, 30) + .padding(.horizontal, 20) } .background(.white) .cornerRadius(15) diff --git a/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift b/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift index 856914371..4c2ad177e 100644 --- a/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift +++ b/Linphone/UI/Main/Settings/ViewModel/AccountProfileViewModel.swift @@ -25,16 +25,69 @@ class AccountProfileViewModel: ObservableObject { @Published var avatarModel: ContactAvatarModel? @Published var photoAvatarModel: String? + @Published var displayName: String = "" + + @Published var dialPlanValueSelected: String = "🇫🇷 France | +33" + var dialPlanSelected: DialPlan? + var dialPlansList: [DialPlan] = [] init() {} + func saveChangesWhenLeaving() { + CoreContext.shared.doOnCoreQueue { core in + let newParams = core.defaultAccount!.params?.clone() + print("getImagePath 0 \(self.displayName) \(newParams?.identityAddress?.displayName ?? "NIL")") + if self.displayName != newParams?.identityAddress?.displayName { + if let newIdentityAddress = newParams?.identityAddress?.clone() { + try? newIdentityAddress.setDisplayname(newValue: self.displayName) + try? newParams?.setIdentityaddress(newValue: newIdentityAddress) + } + + print("getImagePath 1 \(self.getImagePath().lastPathComponent)") + + if self.getImagePath().lastPathComponent.contains("-default") { + print("getImagePath 2") + self.saveImage( + image: ContactsManager.shared.textToImage( + firstName: self.displayName.isEmpty ? core.defaultAccount!.displayName() : self.displayName, lastName: ""), + name: self.displayName.isEmpty ? core.defaultAccount!.displayName() : self.displayName, + prefix: "-default") + } + } + + /* + newParams?.internationalPrefix = self.dialPlanSelected?.countryCallingCode + newParams?.internationalPrefixIsoCountryCode = self.dialPlanSelected?.isoCountryCode + newParams?.useInternationalPrefixForCallsAndChats = true + */ + + core.defaultAccount!.params = newParams + } + } + func setAvatarModel() { CoreContext.shared.doOnCoreQueue { core in if core.defaultAccount != nil { - let displayNameTmp = core.defaultAccount!.displayName() - let contactAddressTmp = core.defaultAccount!.contactAddress?.asStringUriOnly() ?? "" + let displayNameTmp = core.defaultAccount!.params?.identityAddress?.displayName ?? "" + let contactAddressTmp = core.defaultAccount!.params?.identityAddress?.asStringUriOnly() ?? "" var photoAvatarModelTmp = "" + let prefix = core.defaultAccount!.params?.internationalPrefix ?? "" + let isoCountryCode = core.defaultAccount!.params?.internationalPrefixIsoCountryCode ?? "" + + var dialPlanValueSelectedTmp = "" + if !prefix.isEmpty || !isoCountryCode.isEmpty { + Log.info( + "$TAG Account \(core.defaultAccount!.params?.identityAddress?.asStringUriOnly() ?? "") prefix is \(prefix) \(isoCountryCode)" + ) + + self.dialPlansList = Factory.Instance.dialPlans + if let dialPlan = self.dialPlansList.first(where: { $0.isoCountryCode == isoCountryCode }) ?? + self.dialPlansList.first(where: { $0.countryCallingCode == prefix }) { + dialPlanValueSelectedTmp = "\(dialPlan.flag) \(dialPlan.country) | +\(dialPlan.countryCallingCode)" + } + } + let preferences = UserDefaults.standard if preferences.object(forKey: self.photoAvatarModelKey) == nil { @@ -44,13 +97,19 @@ class AccountProfileViewModel: ObservableObject { } DispatchQueue.main.async { - self.avatarModel = ContactAvatarModel(friend: nil, name: displayNameTmp, address: contactAddressTmp, withPresence: false) + self.avatarModel = ContactAvatarModel(friend: nil, name: displayNameTmp.isEmpty ? core.defaultAccount!.displayName() : displayNameTmp, address: contactAddressTmp, withPresence: false) self.photoAvatarModel = photoAvatarModelTmp + self.displayName = displayNameTmp + self.dialPlanValueSelected = dialPlanValueSelectedTmp } } } } + func changeDialPlan() { + + } + func saveImage(image: UIImage, name: String, prefix: String) { guard let data = image.jpegData(compressionQuality: 1) ?? image.pngData() else { return