From bb4134ede05c1bf0c310bd620a36666c1bf8a88f Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Thu, 30 Oct 2025 10:59:46 +0100 Subject: [PATCH] Enable phone number calls in contact details --- .../ContactInnerActionsFragment.swift | 27 +++++- .../Fragments/ContactInnerFragment.swift | 97 +++++++++++-------- 2 files changed, 81 insertions(+), 43 deletions(-) diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift index f25d815c3..cdd0f4b98 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift @@ -81,6 +81,7 @@ struct ContactInnerActionsFragment: View { .lineLimit(1) .fixedSize(horizontal: false, vertical: true) } + Spacer() Image("phone") @@ -95,13 +96,13 @@ struct ContactInnerActionsFragment: View { } .background(.white) .onTapGesture { - do { - let address = try Factory.Instance.createAddress(addr: contactAvatarModel.addresses[index]) - withAnimation { + CoreContext.shared.doOnCoreQueue { core in + do { + let address = try Factory.Instance.createAddress(addr: contactAvatarModel.addresses[index]) telecomManager.doCallOrJoinConf(address: address) + } catch { + Log.error("[ContactInnerActionsFragment] unable to create address for a new outgoing call : \(contactAvatarModel.addresses[index]) \(error) ") } - } catch { - Log.error("[ContactInnerActionsFragment] unable to create address for a new outgoing call : \(contactAvatarModel.addresses[index]) \(error) ") } } .onLongPressGesture(minimumDuration: 0.2) { @@ -139,12 +140,28 @@ struct ContactInnerActionsFragment: View { .lineLimit(1) .fixedSize(horizontal: false, vertical: true) } + Spacer() + + Image("phone") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c600) + .frame(width: 25, height: 25) + .padding(.all, 10) } .padding(.vertical, 15) .padding(.horizontal, 20) } .background(.white) + .onTapGesture { + CoreContext.shared.doOnCoreQueue { core in + let address = core.interpretUrl(url: contactAvatarModel.phoneNumbersWithLabel[index].phoneNumber, applyInternationalPrefix: true) + if address != nil { + TelecomManager.shared.doCallOrJoinConf(address: address!) + } + } + } .onLongPressGesture(minimumDuration: 0.2) { contactsListViewModel.stringToCopy = entry.phoneNumber showingSheet.toggle() diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift index e57fc1105..c920aba7b 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift @@ -144,16 +144,24 @@ struct ContactInnerFragment: View { Spacer() Button(action: { - if contactAvatarModel.addresses.count <= 1 { - do { - let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address) - telecomManager.doCallOrJoinConf(address: address, isVideo: false) - } catch { - Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ") + CoreContext.shared.doOnCoreQueue { core in + if contactAvatarModel.addresses.count == 1 { + do { + let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address) + telecomManager.doCallOrJoinConf(address: address, isVideo: false) + } catch { + Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ") + } + } else if contactAvatarModel.addresses.count < 1 && contactAvatarModel.phoneNumbersWithLabel.count == 1 { + if let firstPhoneNumbersWithLabel = contactAvatarModel.phoneNumbersWithLabel.first, let address = core.interpretUrl(url: firstPhoneNumbersWithLabel.phoneNumber, applyInternationalPrefix: true) { + telecomManager.doCallOrJoinConf(address: address, isVideo: false) + } + } else { + DispatchQueue.main.async { + isShowSipAddressesPopupType = 0 + isShowSipAddressesPopup = true + } } - } else { - isShowSipAddressesPopupType = 0 - isShowSipAddressesPopup = true } }, label: { VStack { @@ -161,67 +169,81 @@ struct ContactInnerFragment: View { Image("phone") .renderingMode(.template) .resizable() - .foregroundStyle(contactAvatarModel.address.isEmpty ? Color.grayMain2c400 : Color.grayMain2c600) + .foregroundStyle(Color.grayMain2c600) .frame(width: 25, height: 25) } .padding(16) - .background(contactAvatarModel.address.isEmpty ? Color.grayMain2c100 : Color.grayMain2c200) + .background(Color.grayMain2c200) .cornerRadius(40) Text("contact_call_action") .default_text_style(styleSize: 14) } }) - .disabled(contactAvatarModel.address.isEmpty) if !CorePreferences.disableChatFeature { Spacer() Button(action: { - if contactAvatarModel.addresses.count <= 1 { - do { - let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address) - contactsListViewModel.createOneToOneChatRoomWith(remote: address) - } catch { - Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ") - } - } else { - isShowSipAddressesPopupType = 1 - isShowSipAddressesPopup = true - } + CoreContext.shared.doOnCoreQueue { core in + if contactAvatarModel.addresses.count == 1 { + do { + let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address) + contactsListViewModel.createOneToOneChatRoomWith(remote: address) + } catch { + Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ") + } + } else if contactAvatarModel.addresses.count < 1 && contactAvatarModel.phoneNumbersWithLabel.count == 1 { + if let firstPhoneNumbersWithLabel = contactAvatarModel.phoneNumbersWithLabel.first, let address = core.interpretUrl(url: firstPhoneNumbersWithLabel.phoneNumber, applyInternationalPrefix: true) { + contactsListViewModel.createOneToOneChatRoomWith(remote: address) + } + } else { + DispatchQueue.main.async { + isShowSipAddressesPopupType = 1 + isShowSipAddressesPopup = true + } + } + } }, label: { VStack { HStack(alignment: .center) { Image("chat-teardrop-text") .renderingMode(.template) .resizable() - .foregroundStyle(contactAvatarModel.address.isEmpty ? Color.grayMain2c400 : Color.grayMain2c600) + .foregroundStyle(Color.grayMain2c600) .frame(width: 25, height: 25) } .padding(16) - .background(contactAvatarModel.address.isEmpty ? Color.grayMain2c100 : Color.grayMain2c200) + .background(Color.grayMain2c200) .cornerRadius(40) Text("contact_message_action") .default_text_style(styleSize: 14) } }) - .disabled(contactAvatarModel.address.isEmpty) } Spacer() Button(action: { - if contactAvatarModel.addresses.count <= 1 { - do { - let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address) - telecomManager.doCallOrJoinConf(address: address, isVideo: true) - } catch { - Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ") + CoreContext.shared.doOnCoreQueue { core in + if contactAvatarModel.addresses.count == 1 { + do { + let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address) + telecomManager.doCallOrJoinConf(address: address, isVideo: true) + } catch { + Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ") + } + } else if contactAvatarModel.addresses.count < 1 && contactAvatarModel.phoneNumbersWithLabel.count == 1 { + if let firstPhoneNumbersWithLabel = contactAvatarModel.phoneNumbersWithLabel.first, let address = core.interpretUrl(url: firstPhoneNumbersWithLabel.phoneNumber, applyInternationalPrefix: true) { + telecomManager.doCallOrJoinConf(address: address, isVideo: true) + } + } else { + DispatchQueue.main.async { + isShowSipAddressesPopupType = 2 + isShowSipAddressesPopup = true + } } - } else { - isShowSipAddressesPopupType = 2 - isShowSipAddressesPopup = true } }, label: { VStack { @@ -229,18 +251,17 @@ struct ContactInnerFragment: View { Image("video-camera") .renderingMode(.template) .resizable() - .foregroundStyle(contactAvatarModel.address.isEmpty ? Color.grayMain2c400 : Color.grayMain2c600) + .foregroundStyle(Color.grayMain2c600) .frame(width: 25, height: 25) } .padding(16) - .background(contactAvatarModel.address.isEmpty ? Color.grayMain2c100 : Color.grayMain2c200) + .background(Color.grayMain2c200) .cornerRadius(40) Text("contact_video_call_action") .default_text_style(styleSize: 14) } }) - .disabled(contactAvatarModel.address.isEmpty) Spacer() }