mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Fix avatar and displayname in ConversationInfoFragment
This commit is contained in:
parent
fdd0925184
commit
b7446f6d26
7 changed files with 177 additions and 126 deletions
|
|
@ -79,10 +79,13 @@ struct ContentView: View {
|
|||
@State private var isShowLoginFragment: Bool = false
|
||||
|
||||
private let avatarSize = 45.0
|
||||
@State private var imagePath: URL?
|
||||
|
||||
var body: some View {
|
||||
let pub = NotificationCenter.default
|
||||
.publisher(for: NSNotification.Name("ContactLoaded"))
|
||||
let imageChanged = NotificationCenter.default
|
||||
.publisher(for: NSNotification.Name("ImageChanged"))
|
||||
GeometryReader { geometry in
|
||||
VStack(spacing: 0) {
|
||||
if (telecomManager.callInProgress && !fullscreenVideo && ((!telecomManager.callDisplayed && callViewModel.callsCounter == 1) || callViewModel.callsCounter > 1)) || isShowConversationFragment {
|
||||
|
|
@ -308,30 +311,41 @@ struct ContentView: View {
|
|||
VStack(spacing: 0) {
|
||||
if searchIsActive == false {
|
||||
HStack {
|
||||
AsyncImage(url: accountProfileViewModel.getImagePath()) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
case .success(let image):
|
||||
image
|
||||
if (accountProfileViewModel.accountModelIndex ?? 0) < CoreContext.shared.accounts.count {
|
||||
AsyncImage(url: imagePath) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex ?? 0].avatarModel?.name ?? "",
|
||||
lastName: ""))
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex ?? 0].avatarModel?.name ?? "",
|
||||
lastName: ""))
|
||||
.resizable()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
openMenu()
|
||||
}
|
||||
.onAppear {
|
||||
imagePath = CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].getImagePath()
|
||||
}
|
||||
.onChange(of: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].usernaneAvatar) { _ in
|
||||
imagePath = CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].getImagePath()
|
||||
}
|
||||
.onReceive(imageChanged) { _ in
|
||||
imagePath = CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].getImagePath()
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
openMenu()
|
||||
}
|
||||
|
||||
Text(String(localized: index == 0 ? "bottom_navigation_contacts_label" : (index == 1 ? "bottom_navigation_calls_label" : (index == 2 ? "bottom_navigation_conversations_label" : "bottom_navigation_meetings_label"))))
|
||||
|
|
@ -1338,6 +1352,9 @@ struct ContentView: View {
|
|||
.onChange(of: scenePhase) { newPhase in
|
||||
CoreContext.shared.enteredForeground = newPhase == .active
|
||||
orientation = UIDevice.current.orientation
|
||||
if newPhase == .active {
|
||||
accountProfileViewModel.setAvatarModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ struct ConversationInfoFragment: View {
|
|||
Avatar(contactAvatarModel: participantConversationModel, avatarSize: 50)
|
||||
} else {
|
||||
let avatarSize = 50.0
|
||||
AsyncImage(url: accountProfileViewModel.getImagePath()) { image in
|
||||
AsyncImage(url: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].imagePathAvatar) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ class ConversationModel: ObservableObject, Identifiable {
|
|||
|
||||
subjectTmp = self.chatRoom.participants.first!.address!.displayName != nil
|
||||
? self.chatRoom.participants.first!.address!.displayName!
|
||||
: (self.chatRoom.participants.first!.address!.username ?? self.chatRoom.participants.first!.address!.asStringUriOnly())
|
||||
: (self.chatRoom.participants.first!.address!.username ?? String(self.chatRoom.participants.first!.address!.asStringUriOnly().dropFirst(4)))
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ struct SideMenuAccountRow: View {
|
|||
|
||||
var body: some View {
|
||||
HStack {
|
||||
AsyncImage(url: accountProfileViewModel.getImagePath()) { image in
|
||||
AsyncImage(url: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].imagePathAvatar) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ struct AccountProfileFragment: View {
|
|||
&& !accountModel.photoAvatarModel!.isEmpty
|
||||
&& selectedImage == nil && !removedImage {
|
||||
|
||||
AsyncImage(url: accountProfileViewModel.getImagePath()) { image in
|
||||
AsyncImage(url: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!].imagePathAvatar) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
|
|
@ -265,39 +265,40 @@ struct AccountProfileFragment: View {
|
|||
}
|
||||
|
||||
if detailIsOpen {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 30) {
|
||||
HStack {
|
||||
Text(String(localized: "sip_address") + ":")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
Text(accountModel.avatarModel!.address)
|
||||
.foregroundStyle(Color.grayMain2c700)
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
|
||||
Button(action: {
|
||||
UIPasteboard.general.setValue(
|
||||
accountModel.avatarModel!.address,
|
||||
forPasteboardType: UTType.plainText.identifier
|
||||
)
|
||||
if accountModel.avatarModel != nil {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 30) {
|
||||
HStack {
|
||||
Text(String(localized: "sip_address") + ":")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
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)
|
||||
Text(accountModel.avatarModel!.address)
|
||||
.foregroundStyle(Color.grayMain2c700)
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
|
||||
Button(action: {
|
||||
UIPasteboard.general.setValue(
|
||||
accountModel.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)
|
||||
})
|
||||
}
|
||||
|
||||
TextField(accountModel.displayNameAvatar, text: Binding(
|
||||
VStack(alignment: .leading) {
|
||||
Text("sip_address_display_name")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField(accountModel.displayNameAvatar, text: Binding(
|
||||
get: { accountModel.displayNameAvatar },
|
||||
set: { newValue in
|
||||
accountModel.displayNameAvatar = newValue
|
||||
|
|
@ -315,66 +316,67 @@ struct AccountProfileFragment: View {
|
|||
.stroke(isDisplayNameFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isDisplayNameFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text("manage_account_international_prefix")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
.lineLimit(1)
|
||||
|
||||
Button(action: {
|
||||
isShowPopup = true
|
||||
}, label: {
|
||||
Image("question")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
.frame(width: 20, height: 20)
|
||||
})
|
||||
.padding(.bottom, -5)
|
||||
}
|
||||
Menu {
|
||||
Picker("", selection: $accountProfileViewModel.dialPlanValueSelected) {
|
||||
ForEach(registerViewModel.dialPlansLabelList, id: \.self) { dialPlan in
|
||||
Text(dialPlan).tag(dialPlan)
|
||||
}
|
||||
}
|
||||
.onChange(of: accountProfileViewModel.dialPlanValueSelected) { newValue in
|
||||
accountProfileViewModel.updateDialPlan(newDialPlan: newValue)
|
||||
}
|
||||
} label: {
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text(accountProfileViewModel.dialPlanValueSelected)
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Text("manage_account_international_prefix")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
.lineLimit(1)
|
||||
|
||||
Image("caret-down")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
Button(action: {
|
||||
isShowPopup = true
|
||||
}, label: {
|
||||
Image("question")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
.frame(width: 20, height: 20)
|
||||
})
|
||||
.padding(.bottom, -5)
|
||||
}
|
||||
Menu {
|
||||
Picker("", selection: $accountProfileViewModel.dialPlanValueSelected) {
|
||||
ForEach(registerViewModel.dialPlansLabelList, id: \.self) { dialPlan in
|
||||
Text(dialPlan).tag(dialPlan)
|
||||
}
|
||||
}
|
||||
.onChange(of: accountProfileViewModel.dialPlanValueSelected) { newValue in
|
||||
accountProfileViewModel.updateDialPlan(newDialPlan: newValue)
|
||||
}
|
||||
} 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)
|
||||
)
|
||||
}
|
||||
.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)
|
||||
}
|
||||
.padding(.vertical, 30)
|
||||
.padding(.horizontal, 20)
|
||||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
.padding(.horizontal)
|
||||
.zIndex(-1)
|
||||
.transition(.move(edge: .top))
|
||||
}
|
||||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
.padding(.horizontal)
|
||||
.zIndex(-1)
|
||||
.transition(.move(edge: .top))
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
|
|
@ -383,7 +385,7 @@ struct AccountProfileFragment: View {
|
|||
Toggle("", isOn: $flag)
|
||||
.labelsHidden()
|
||||
|
||||
Text("drawer_menu_account_connection_status_connected")
|
||||
Text(accountModel.humanReadableRegistrationState)
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.bottom, -5)
|
||||
|
|
@ -403,6 +405,7 @@ struct AccountProfileFragment: View {
|
|||
.cornerRadius(15)
|
||||
.padding(.all)
|
||||
|
||||
/*
|
||||
HStack(alignment: .center) {
|
||||
Text("manage_account_details_title")
|
||||
.default_text_style_800(styleSize: 18)
|
||||
|
|
@ -456,6 +459,7 @@ struct AccountProfileFragment: View {
|
|||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
.padding(.all)
|
||||
*/
|
||||
}
|
||||
.frame(maxWidth: sharedMainViewModel.maxWidth)
|
||||
}
|
||||
|
|
@ -487,11 +491,13 @@ struct AccountProfileFragment: View {
|
|||
|
||||
func saveImage() {
|
||||
let accountModel = CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex ?? 0]
|
||||
let usernameTmp = CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex ?? 0].usernaneAvatar
|
||||
|
||||
accountProfileViewModel.saveImage(
|
||||
image: selectedImage
|
||||
?? ContactsManager.shared.textToImage(
|
||||
firstName: accountModel.avatarModel!.name, lastName: ""),
|
||||
name: accountModel.avatarModel!.name,
|
||||
name: usernameTmp,
|
||||
prefix: ((selectedImage == nil) ? "-default" : ""))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,13 @@ class AccountProfileViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
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 ? CoreContext.shared.accounts[self.accountModelIndex!].account.displayName() : displayNameAccountModel, lastName: ""),
|
||||
name: displayNameAccountModel.isEmpty ? CoreContext.shared.accounts[self.accountModelIndex!].account.displayName() : displayNameAccountModel,
|
||||
firstName: displayNameAccountModel.isEmpty ? usernameTmp : displayNameAccountModel, lastName: ""),
|
||||
name: usernameTmp,
|
||||
prefix: "-default")
|
||||
}
|
||||
}
|
||||
|
|
@ -67,10 +69,8 @@ class AccountProfileViewModel: ObservableObject {
|
|||
func setAvatarModel() {
|
||||
if accountModelIndex != nil {
|
||||
CoreContext.shared.doOnCoreQueue { _ in
|
||||
let photoAvatarAccountModel = CoreContext.shared.accounts[self.accountModelIndex!].photoAvatarModel
|
||||
let displayNameTmp = CoreContext.shared.accounts[self.accountModelIndex!].account.params?.identityAddress?.displayName ?? ""
|
||||
let contactAddressTmp = CoreContext.shared.accounts[self.accountModelIndex!].account.params?.identityAddress?.asStringUriOnly() ?? ""
|
||||
var photoAvatarModelTmp = ""
|
||||
|
||||
let prefix = CoreContext.shared.accounts[self.accountModelIndex!].account.params?.internationalPrefix ?? ""
|
||||
let isoCountryCode = CoreContext.shared.accounts[self.accountModelIndex!].account.params?.internationalPrefixIsoCountryCode ?? ""
|
||||
|
|
@ -88,17 +88,8 @@ class AccountProfileViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
let preferences = UserDefaults.standard
|
||||
|
||||
let accountDisplayName = CoreContext.shared.accounts[self.accountModelIndex!].account.displayName()
|
||||
|
||||
let photoAvatarModelKey = "photo_avatar_model" + CoreContext.shared.accounts[self.accountModelIndex!].address
|
||||
if preferences.object(forKey: photoAvatarModelKey) == nil {
|
||||
preferences.set(photoAvatarAccountModel ?? "", forKey: photoAvatarModelKey)
|
||||
} else {
|
||||
photoAvatarModelTmp = preferences.string(forKey: photoAvatarModelKey)!
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
CoreContext.shared.accounts[self.accountModelIndex!].avatarModel = ContactAvatarModel(
|
||||
friend: nil,
|
||||
|
|
@ -107,8 +98,6 @@ class AccountProfileViewModel: ObservableObject {
|
|||
withPresence: false
|
||||
)
|
||||
|
||||
CoreContext.shared.accounts[self.accountModelIndex!].photoAvatarModel = photoAvatarModelTmp
|
||||
CoreContext.shared.accounts[self.accountModelIndex!].displayNameAvatar = displayNameTmp
|
||||
self.dialPlanValueSelected = dialPlanValueSelectedTmp
|
||||
}
|
||||
}
|
||||
|
|
@ -127,11 +116,20 @@ class AccountProfileViewModel: ObservableObject {
|
|||
return
|
||||
}
|
||||
|
||||
let photoAvatarModelKey = "photo_avatar_model" + CoreContext.shared.accounts[self.accountModelIndex ?? 0].address
|
||||
let photoAvatarModelKey = "photo_avatar_model" + CoreContext.shared.accounts[self.accountModelIndex!].usernaneAvatar
|
||||
|
||||
ContactsManager.shared.awaitDataWrite(data: data, name: name, prefix: prefix) { _, result in
|
||||
UserDefaults.standard.set(result, forKey: photoAvatarModelKey)
|
||||
CoreContext.shared.accounts[self.accountModelIndex ?? 0].photoAvatarModel = result
|
||||
|
||||
CoreContext.shared.accounts[self.accountModelIndex ?? 0].photoAvatarModel = ""
|
||||
CoreContext.shared.accounts[self.accountModelIndex ?? 0].imagePathAvatar = nil
|
||||
NotificationCenter.default.post(name: NSNotification.Name("ImageChanged"), object: nil)
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
CoreContext.shared.accounts[self.accountModelIndex ?? 0].photoAvatarModel = result
|
||||
CoreContext.shared.accounts[self.accountModelIndex ?? 0].imagePathAvatar = CoreContext.shared.accounts[self.accountModelIndex ?? 0].getImagePath()
|
||||
NotificationCenter.default.post(name: NSNotification.Name("ImageChanged"), object: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ class AccountModel: ObservableObject {
|
|||
@Published var avatarModel: ContactAvatarModel?
|
||||
@Published var photoAvatarModel: String?
|
||||
@Published var displayNameAvatar: String = ""
|
||||
@Published var usernaneAvatar: String = ""
|
||||
@Published var imagePathAvatar: URL?
|
||||
|
||||
private var accountDelegate: AccountDelegate?
|
||||
private var coreDelegate: CoreDelegate?
|
||||
|
|
@ -78,6 +80,21 @@ class AccountModel: ObservableObject {
|
|||
}
|
||||
let displayName = account.displayName()
|
||||
let address = account.params?.identityAddress?.asString()
|
||||
|
||||
let displayNameTmp = account.params?.identityAddress?.displayName ?? ""
|
||||
let usernaneAvatarTmp = account.contactAddress?.username ?? ""
|
||||
var photoAvatarModelTmp = ""
|
||||
|
||||
let preferences = UserDefaults.standard
|
||||
|
||||
let photoAvatarModelKey = "photo_avatar_model" + 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:
|
||||
|
|
@ -99,6 +116,11 @@ class AccountModel: ObservableObject {
|
|||
isDefaultAccount = isDefault
|
||||
self.displayName = displayName
|
||||
address.map {self.address = $0}
|
||||
|
||||
photoAvatarModel = photoAvatarModelTmp
|
||||
displayNameAvatar = displayNameTmp
|
||||
usernaneAvatar = usernaneAvatarTmp
|
||||
imagePathAvatar = getImagePath()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,4 +136,12 @@ class AccountModel: ObservableObject {
|
|||
self.account.refreshRegister()
|
||||
}
|
||||
}
|
||||
|
||||
func getImagePath() -> URL {
|
||||
let imagePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(
|
||||
photoAvatarModel ?? "Error"
|
||||
)
|
||||
|
||||
return imagePath
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue