mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-04-17 20:08:31 +00:00
Add trusted devices list
This commit is contained in:
parent
cf97da11b1
commit
d5d1600b4e
15 changed files with 729 additions and 255 deletions
21
Linphone/Assets.xcassets/arrow-right.imageset/Contents.json
vendored
Normal file
21
Linphone/Assets.xcassets/arrow-right.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "arrow-right.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Linphone/Assets.xcassets/arrow-right.imageset/arrow-right.svg
vendored
Normal file
1
Linphone/Assets.xcassets/arrow-right.imageset/arrow-right.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 269 B |
|
|
@ -1,7 +1,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public enum AppGitInfo {
|
public enum AppGitInfo {
|
||||||
public static let branch = "master"
|
public static let branch = "feature/trust_list"
|
||||||
public static let commit = "304651d77"
|
public static let commit = "692a308d7"
|
||||||
public static let tag = "6.1.0-alpha"
|
public static let tag = "6.1.0-alpha"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,8 +172,15 @@
|
||||||
"contact_details_numbers_and_addresses_title" = "Phone numbers & SIP addresses";
|
"contact_details_numbers_and_addresses_title" = "Phone numbers & SIP addresses";
|
||||||
"contact_details_remove_from_favourites" = "Remove from favourites";
|
"contact_details_remove_from_favourites" = "Remove from favourites";
|
||||||
"contact_details_share" = "Share";
|
"contact_details_share" = "Share";
|
||||||
"contact_dialog_delete_message" = "This contact will be definitively removed.";
|
"contact_details_trust_title" = "Trust";
|
||||||
|
"contact_details_no_device_found" = "No device found…";
|
||||||
|
"contact_details_trusted_devices_count" = "Number of trusted devices:";
|
||||||
|
"contact_dialog_increase_trust_level_title" = "Increase trust level";
|
||||||
|
"contact_dialog_increase_trust_level_message" = "You're about to make a call to %1$@'s device %2$@.\nDo you want to make the call?";
|
||||||
|
"contact_dialog_devices_trust_help_title" = "Trust level";
|
||||||
|
"contact_dialog_devices_trust_help_message" = "Check all of your contact devices to make sure your communications will be secured an unaltered.\nWhen all will be verified, you'll reach maximum trust level.";
|
||||||
"contact_dialog_delete_title" = "Delete %@?";
|
"contact_dialog_delete_title" = "Delete %@?";
|
||||||
|
"contact_dialog_delete_message" = "This contact will be definitively removed.";
|
||||||
"contact_dialog_pick_phone_number_or_sip_address_title" = "Choose a number or a SIP address";
|
"contact_dialog_pick_phone_number_or_sip_address_title" = "Choose a number or a SIP address";
|
||||||
"contact_edit_title" = "Edit contact";
|
"contact_edit_title" = "Edit contact";
|
||||||
"contact_editor_company" = "Company";
|
"contact_editor_company" = "Company";
|
||||||
|
|
@ -182,6 +189,8 @@
|
||||||
"contact_editor_first_name" = "First name";
|
"contact_editor_first_name" = "First name";
|
||||||
"contact_editor_job_title" = "Job title";
|
"contact_editor_job_title" = "Job title";
|
||||||
"contact_editor_last_name" = "Last name";
|
"contact_editor_last_name" = "Last name";
|
||||||
|
"contact_make_call_check_device_trust" = "Verify";
|
||||||
|
"contact_device_without_name" = "Unnamed device";
|
||||||
"contact_message_action" = "Message";
|
"contact_message_action" = "Message";
|
||||||
"contact_new_title" = "New contact";
|
"contact_new_title" = "New contact";
|
||||||
"contact_video_call_action" = "Video call";
|
"contact_video_call_action" = "Video call";
|
||||||
|
|
@ -288,8 +297,10 @@
|
||||||
"dialog_continue" = "Continue";
|
"dialog_continue" = "Continue";
|
||||||
"dialog_deny" = "Deny";
|
"dialog_deny" = "Deny";
|
||||||
"dialog_install" = "Install";
|
"dialog_install" = "Install";
|
||||||
|
"dialog_do_not_show_anymore" = "Do not show this dialog anymore";
|
||||||
"dialog_no" = "No";
|
"dialog_no" = "No";
|
||||||
"dialog_confirm" = "Confirm";
|
"dialog_confirm" = "Confirm";
|
||||||
|
"dialog_understood" = "Understood";
|
||||||
"dialog_yes" = "Yes";
|
"dialog_yes" = "Yes";
|
||||||
"drawer_menu_account_connection_status_cleared" = "Disabled";
|
"drawer_menu_account_connection_status_cleared" = "Disabled";
|
||||||
"drawer_menu_account_connection_status_connected" = "Connected";
|
"drawer_menu_account_connection_status_connected" = "Connected";
|
||||||
|
|
|
||||||
|
|
@ -172,8 +172,15 @@
|
||||||
"contact_details_numbers_and_addresses_title" = "Coordonnées";
|
"contact_details_numbers_and_addresses_title" = "Coordonnées";
|
||||||
"contact_details_remove_from_favourites" = "Retirer des favoris";
|
"contact_details_remove_from_favourites" = "Retirer des favoris";
|
||||||
"contact_details_share" = "Partager";
|
"contact_details_share" = "Partager";
|
||||||
"contact_dialog_delete_message" = "Ce contact sera définitivement supprimé.";
|
"contact_details_trust_title" = "Confiance";
|
||||||
|
"contact_details_no_device_found" = "Aucun appareil trouvé";
|
||||||
|
"contact_details_trusted_devices_count" = "Appareils du contact :";
|
||||||
|
"contact_dialog_increase_trust_level_title" = "Vérifier l'appareil ?";
|
||||||
|
"contact_dialog_increase_trust_level_message" = "Voulez-vous appeler l’appareil %2$@ de %1$@ ?\nVoulez-vous passer l’appel ?";
|
||||||
|
"contact_dialog_devices_trust_help_title" = "Niveau de confiance";
|
||||||
|
"contact_dialog_devices_trust_help_message" = "Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission.\nQuand tous seront vérifiés, vous atteindrez le niveau de confiance maximal.";
|
||||||
"contact_dialog_delete_title" = "Supprimer %@ ?";
|
"contact_dialog_delete_title" = "Supprimer %@ ?";
|
||||||
|
"contact_dialog_delete_message" = "Ce contact sera définitivement supprimé.";
|
||||||
"contact_dialog_pick_phone_number_or_sip_address_title" = "Choisissez un numéro ou adresse SIP";
|
"contact_dialog_pick_phone_number_or_sip_address_title" = "Choisissez un numéro ou adresse SIP";
|
||||||
"contact_edit_title" = "Modifier contact";
|
"contact_edit_title" = "Modifier contact";
|
||||||
"contact_editor_company" = "Entreprise";
|
"contact_editor_company" = "Entreprise";
|
||||||
|
|
@ -182,6 +189,8 @@
|
||||||
"contact_editor_first_name" = "Prénom";
|
"contact_editor_first_name" = "Prénom";
|
||||||
"contact_editor_job_title" = "Poste";
|
"contact_editor_job_title" = "Poste";
|
||||||
"contact_editor_last_name" = "Nom de famille";
|
"contact_editor_last_name" = "Nom de famille";
|
||||||
|
"contact_make_call_check_device_trust" = "Vérifier";
|
||||||
|
"contact_device_without_name" = "Appareil sans nom";
|
||||||
"contact_message_action" = "Message";
|
"contact_message_action" = "Message";
|
||||||
"contact_new_title" = "Nouveau contact";
|
"contact_new_title" = "Nouveau contact";
|
||||||
"contact_video_call_action" = "Appel vidéo";
|
"contact_video_call_action" = "Appel vidéo";
|
||||||
|
|
@ -288,8 +297,10 @@
|
||||||
"dialog_continue" = "Continuer";
|
"dialog_continue" = "Continuer";
|
||||||
"dialog_deny" = "Refuser";
|
"dialog_deny" = "Refuser";
|
||||||
"dialog_install" = "Installer";
|
"dialog_install" = "Installer";
|
||||||
|
"dialog_do_not_show_anymore" = "Ne plus me montrer ce message";
|
||||||
"dialog_no" = "Non";
|
"dialog_no" = "Non";
|
||||||
"dialog_confirm" = "Confirmer";
|
"dialog_confirm" = "Confirmer";
|
||||||
|
"dialog_understood" = "J'ai compris";
|
||||||
"dialog_yes" = "Oui";
|
"dialog_yes" = "Oui";
|
||||||
"drawer_menu_account_connection_status_cleared" = "Désactivé";
|
"drawer_menu_account_connection_status_cleared" = "Désactivé";
|
||||||
"drawer_menu_account_connection_status_connected" = "Connecté";
|
"drawer_menu_account_connection_status_connected" = "Connecté";
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,10 @@ struct ContactFragment: View {
|
||||||
|
|
||||||
@Binding var isShowDeletePopup: Bool
|
@Binding var isShowDeletePopup: Bool
|
||||||
@Binding var isShowDismissPopup: Bool
|
@Binding var isShowDismissPopup: Bool
|
||||||
|
@Binding var isShowTrustLevelPopup: Bool
|
||||||
@Binding var isShowSipAddressesPopup: Bool
|
@Binding var isShowSipAddressesPopup: Bool
|
||||||
@Binding var isShowSipAddressesPopupType: Int
|
@Binding var isShowSipAddressesPopupType: Int
|
||||||
|
@Binding var isShowIncreaseTrustLevelPopup: Bool
|
||||||
@Binding var isShowEditContactFragmentInContactDetails: Bool
|
@Binding var isShowEditContactFragmentInContactDetails: Bool
|
||||||
|
|
||||||
@State private var showingSheet = false
|
@State private var showingSheet = false
|
||||||
|
|
@ -68,19 +70,11 @@ struct ContactFragment: View {
|
||||||
showingSheet: $showingSheet,
|
showingSheet: $showingSheet,
|
||||||
showShareSheet: $showShareSheet,
|
showShareSheet: $showShareSheet,
|
||||||
isShowDismissPopup: $isShowDismissPopup,
|
isShowDismissPopup: $isShowDismissPopup,
|
||||||
|
isShowTrustLevelPopup: $isShowTrustLevelPopup,
|
||||||
isShowSipAddressesPopup: $isShowSipAddressesPopup,
|
isShowSipAddressesPopup: $isShowSipAddressesPopup,
|
||||||
isShowSipAddressesPopupType: $isShowSipAddressesPopupType,
|
isShowSipAddressesPopupType: $isShowSipAddressesPopupType,
|
||||||
|
isShowIncreaseTrustLevelPopup: $isShowIncreaseTrustLevelPopup,
|
||||||
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
|
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
|
||||||
ContactFragment(
|
|
||||||
isShowDeletePopup: .constant(false),
|
|
||||||
isShowDismissPopup: .constant(false),
|
|
||||||
isShowSipAddressesPopup: .constant(false),
|
|
||||||
isShowSipAddressesPopupType: .constant(0),
|
|
||||||
isShowEditContactFragmentInContactDetails: .constant(false)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,19 @@ struct ContactInnerActionsFragment: View {
|
||||||
@EnvironmentObject var contactAvatarModel: ContactAvatarModel
|
@EnvironmentObject var contactAvatarModel: ContactAvatarModel
|
||||||
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
|
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
|
||||||
|
|
||||||
|
@State private var trustIsOpen = true
|
||||||
@State private var informationIsOpen = true
|
@State private var informationIsOpen = true
|
||||||
|
|
||||||
@Binding var showingSheet: Bool
|
@Binding var showingSheet: Bool
|
||||||
@Binding var showShareSheet: Bool
|
@Binding var showShareSheet: Bool
|
||||||
@Binding var isShowDeletePopup: Bool
|
@Binding var isShowDeletePopup: Bool
|
||||||
@Binding var isShowDismissPopup: Bool
|
@Binding var isShowDismissPopup: Bool
|
||||||
|
@Binding var isShowTrustLevelPopup: Bool
|
||||||
|
@Binding var isShowIncreaseTrustLevelPopup: Bool
|
||||||
@Binding var isShowEditContactFragmentInContactDetails: Bool
|
@Binding var isShowEditContactFragmentInContactDetails: Bool
|
||||||
|
|
||||||
|
let geometry: GeometryProxy
|
||||||
|
|
||||||
var actionEditButton: () -> Void
|
var actionEditButton: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
@ -180,12 +185,14 @@ struct ContactInnerActionsFragment: View {
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.zIndex(-1)
|
.zIndex(-1)
|
||||||
.transition(.move(edge: .top))
|
.transition(.move(edge: .top))
|
||||||
|
.background(Color.gray100)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
HStack {}
|
HStack {}
|
||||||
.frame(height: 20)
|
.frame(height: 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if !contactAvatarModel.organization.isEmpty || !contactAvatarModel.jobTitle.isEmpty {
|
if !contactAvatarModel.organization.isEmpty || !contactAvatarModel.jobTitle.isEmpty {
|
||||||
VStack {
|
VStack {
|
||||||
if !contactAvatarModel.organization.isEmpty {
|
if !contactAvatarModel.organization.isEmpty {
|
||||||
|
|
@ -213,17 +220,188 @@ struct ContactInnerActionsFragment: View {
|
||||||
.transition(.move(edge: .top))
|
.transition(.move(edge: .top))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Trust Fragment
|
HStack(alignment: .center) {
|
||||||
|
Button {
|
||||||
|
isShowTrustLevelPopup = true
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Text("contact_details_trust_title")
|
||||||
|
.default_text_style_800(styleSize: 15)
|
||||||
|
|
||||||
|
Image("question")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.grayMain2c600)
|
||||||
|
.frame(width: 22, height: 22)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Image(trustIsOpen ? "caret-up" : "caret-down")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.grayMain2c600)
|
||||||
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
|
.padding(.all, 10)
|
||||||
|
}
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
.padding(.horizontal, 16)
|
||||||
|
.background(Color.gray100)
|
||||||
|
.onTapGesture {
|
||||||
|
withAnimation {
|
||||||
|
trustIsOpen.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Medias Fragment
|
if trustIsOpen {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
if !contactsListViewModel.devices.isEmpty {
|
||||||
|
Text("contact_details_trusted_devices_count")
|
||||||
|
.default_text_style_700(styleSize: 14)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.top, 20)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
|
||||||
|
let radius = geometry.size.height * 0.5
|
||||||
|
let barWidth = min(geometry.size.width - 70, SharedMainViewModel.shared.maxWidth - 70)
|
||||||
|
|
||||||
|
ZStack(alignment: .leading) {
|
||||||
|
Rectangle()
|
||||||
|
.foregroundColor(Color.blueInfo500.opacity(0.2))
|
||||||
|
.frame(width: barWidth, height: 30)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: radius))
|
||||||
|
|
||||||
|
if contactsListViewModel.trustedDevicesPercentage >= 15 {
|
||||||
|
Rectangle()
|
||||||
|
.foregroundColor(Color.blueInfo500)
|
||||||
|
.frame(width: ((contactsListViewModel.trustedDevicesPercentage / 100) * barWidth) - 6, height: 25)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: radius))
|
||||||
|
.padding(.horizontal, 3)
|
||||||
|
} else if contactsListViewModel.trustedDevicesPercentage > 0 {
|
||||||
|
Rectangle()
|
||||||
|
.foregroundColor(Color.blueInfo500)
|
||||||
|
.frame(width: ((10 / 100) * barWidth) - 6, height: 25)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: radius))
|
||||||
|
.padding(.horizontal, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contactsListViewModel.trustedDevicesPercentage >= 30 {
|
||||||
|
Text(String(Int(contactsListViewModel.trustedDevicesPercentage)) + "%")
|
||||||
|
.default_text_style_white_700(styleSize: 14)
|
||||||
|
.frame(width: (contactsListViewModel.trustedDevicesPercentage / 100) * barWidth, height: 25, alignment: .center)
|
||||||
|
} else {
|
||||||
|
Text(String(Int(contactsListViewModel.trustedDevicesPercentage)) + "%")
|
||||||
|
.foregroundStyle(contactsListViewModel.trustedDevicesPercentage == 0 ? Color.redDanger500 : Color.blueInfo500)
|
||||||
|
.default_text_style_white_700(styleSize: 14)
|
||||||
|
.frame(width: barWidth, height: 25, alignment: .center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(width: barWidth, height: 30)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
|
||||||
|
ForEach(contactsListViewModel.devices) { device in
|
||||||
|
HStack {
|
||||||
|
Text(device.name)
|
||||||
|
.default_text_style(styleSize: 14)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
if !device.trusted {
|
||||||
|
Button {
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceName = device.name
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceAddress = device.address
|
||||||
|
isShowIncreaseTrustLevelPopup = true
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Image("warning-circle")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.orangeMain500)
|
||||||
|
.frame(width: 25, height: 25)
|
||||||
|
.padding(.all, 6)
|
||||||
|
|
||||||
|
Text("contact_make_call_check_device_trust")
|
||||||
|
.foregroundStyle(Color.orangeMain500)
|
||||||
|
.default_text_style(styleSize: 14)
|
||||||
|
.lineLimit(1)
|
||||||
|
.padding(.leading, -5)
|
||||||
|
.padding(.trailing, 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background(Color.orangeMain100)
|
||||||
|
.cornerRadius(25)
|
||||||
|
} else {
|
||||||
|
ZStack {
|
||||||
|
Button {
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Image("warning-circle")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.orangeMain500)
|
||||||
|
.frame(width: 25, height: 25)
|
||||||
|
.padding(.all, 6)
|
||||||
|
|
||||||
|
Text("contact_make_call_check_device_trust")
|
||||||
|
.foregroundStyle(Color.orangeMain500)
|
||||||
|
.default_text_style(styleSize: 14)
|
||||||
|
.lineLimit(1)
|
||||||
|
.padding(.leading, -5)
|
||||||
|
.padding(.trailing, 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background(Color.orangeMain100)
|
||||||
|
.cornerRadius(25)
|
||||||
|
.hidden()
|
||||||
|
|
||||||
|
Image("trusted")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 28, height: 28)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(height: 40)
|
||||||
|
}
|
||||||
|
.background(.white)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text("contact_details_no_device_found")
|
||||||
|
.default_text_style_700(styleSize: 14)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.top, 15)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
.background(.white)
|
||||||
|
.cornerRadius(15)
|
||||||
|
.padding(.horizontal)
|
||||||
|
.zIndex(-2)
|
||||||
|
.transition(.move(edge: .top))
|
||||||
|
}
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
Text("contact_details_actions_title")
|
Text("contact_details_actions_title")
|
||||||
.default_text_style_800(styleSize: 16)
|
.default_text_style_800(styleSize: 16)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
Image("caret-up")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.grayMain2c600)
|
||||||
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
|
.padding(.all, 10)
|
||||||
|
.hidden()
|
||||||
}
|
}
|
||||||
.padding(.vertical, 10)
|
.padding(.top, 20)
|
||||||
|
.padding(.bottom, 10)
|
||||||
.padding(.horizontal, 16)
|
.padding(.horizontal, 16)
|
||||||
.background(Color.gray100)
|
.background(Color.gray100)
|
||||||
|
|
||||||
|
|
@ -372,18 +550,6 @@ struct ContactInnerActionsFragment: View {
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.zIndex(-1)
|
.zIndex(-1)
|
||||||
.transition(.move(edge: .top))
|
.transition(.move(edge: .top))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
|
||||||
ContactInnerActionsFragment(
|
|
||||||
showingSheet: .constant(false),
|
|
||||||
showShareSheet: .constant(false),
|
|
||||||
isShowDeletePopup: .constant(false),
|
|
||||||
isShowDismissPopup: .constant(false),
|
|
||||||
isShowEditContactFragmentInContactDetails: .constant(false),
|
|
||||||
actionEditButton: {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// swiftlint:enable type_body_length
|
// swiftlint:enable type_body_length
|
||||||
|
|
|
||||||
|
|
@ -39,57 +39,47 @@ struct ContactInnerFragment: View {
|
||||||
@Binding var showingSheet: Bool
|
@Binding var showingSheet: Bool
|
||||||
@Binding var showShareSheet: Bool
|
@Binding var showShareSheet: Bool
|
||||||
@Binding var isShowDismissPopup: Bool
|
@Binding var isShowDismissPopup: Bool
|
||||||
|
@Binding var isShowTrustLevelPopup: Bool
|
||||||
@Binding var isShowSipAddressesPopup: Bool
|
@Binding var isShowSipAddressesPopup: Bool
|
||||||
@Binding var isShowSipAddressesPopupType: Int
|
@Binding var isShowSipAddressesPopupType: Int
|
||||||
|
@Binding var isShowIncreaseTrustLevelPopup: Bool
|
||||||
@Binding var isShowEditContactFragmentInContactDetails: Bool
|
@Binding var isShowEditContactFragmentInContactDetails: Bool
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
ZStack {
|
GeometryReader { geometry in
|
||||||
VStack(spacing: 1) {
|
ZStack {
|
||||||
Rectangle()
|
VStack(spacing: 1) {
|
||||||
.foregroundColor(Color.orangeMain500)
|
Rectangle()
|
||||||
.edgesIgnoringSafeArea(.top)
|
.foregroundColor(Color.orangeMain500)
|
||||||
.frame(height: 0)
|
.edgesIgnoringSafeArea(.top)
|
||||||
|
.frame(height: 0)
|
||||||
HStack {
|
|
||||||
if !(orientation == .landscapeLeft || orientation == .landscapeRight
|
HStack {
|
||||||
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) {
|
if !(orientation == .landscapeLeft || orientation == .landscapeRight
|
||||||
Image("caret-left")
|
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) {
|
||||||
.renderingMode(.template)
|
Image("caret-left")
|
||||||
.resizable()
|
.renderingMode(.template)
|
||||||
.foregroundStyle(Color.orangeMain500)
|
.resizable()
|
||||||
.frame(width: 25, height: 25, alignment: .leading)
|
.foregroundStyle(Color.orangeMain500)
|
||||||
.padding(.all, 10)
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
.padding(.top, 2)
|
.padding(.all, 10)
|
||||||
.padding(.leading, -10)
|
.padding(.top, 2)
|
||||||
.onTapGesture {
|
.padding(.leading, -10)
|
||||||
withAnimation {
|
.onTapGesture {
|
||||||
SharedMainViewModel.shared.displayedFriend = nil
|
withAnimation {
|
||||||
|
SharedMainViewModel.shared.displayedFriend = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Spacer()
|
||||||
Spacer()
|
|
||||||
|
if !contactAvatarModel.isReadOnly {
|
||||||
if !contactAvatarModel.isReadOnly {
|
if !contactAvatarModel.editable {
|
||||||
if !contactAvatarModel.editable {
|
Button(action: {
|
||||||
Button(action: {
|
editNativeContact()
|
||||||
editNativeContact()
|
}, label: {
|
||||||
}, label: {
|
|
||||||
Image("pencil-simple")
|
|
||||||
.renderingMode(.template)
|
|
||||||
.resizable()
|
|
||||||
.foregroundStyle(Color.orangeMain500)
|
|
||||||
.frame(width: 25, height: 25, alignment: .leading)
|
|
||||||
.padding(.all, 10)
|
|
||||||
.padding(.top, 2)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
NavigationLink(destination: EditContactFragment(
|
|
||||||
contactAvatarModel: contactAvatarModel,
|
|
||||||
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
|
|
||||||
isShowDismissPopup: $isShowDismissPopup)) {
|
|
||||||
Image("pencil-simple")
|
Image("pencil-simple")
|
||||||
.renderingMode(.template)
|
.renderingMode(.template)
|
||||||
.resizable()
|
.resizable()
|
||||||
|
|
@ -97,151 +87,81 @@ struct ContactInnerFragment: View {
|
||||||
.frame(width: 25, height: 25, alignment: .leading)
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
.padding(.all, 10)
|
.padding(.all, 10)
|
||||||
.padding(.top, 2)
|
.padding(.top, 2)
|
||||||
}
|
})
|
||||||
.simultaneousGesture(
|
} else {
|
||||||
TapGesture().onEnded {
|
NavigationLink(destination: EditContactFragment(
|
||||||
isShowEditContactFragmentInContactDetails = true
|
contactAvatarModel: contactAvatarModel,
|
||||||
|
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
|
||||||
|
isShowDismissPopup: $isShowDismissPopup)) {
|
||||||
|
Image("pencil-simple")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.orangeMain500)
|
||||||
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
|
.padding(.all, 10)
|
||||||
|
.padding(.top, 2)
|
||||||
}
|
}
|
||||||
)
|
.simultaneousGesture(
|
||||||
|
TapGesture().onEnded {
|
||||||
|
isShowEditContactFragmentInContactDetails = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.frame(maxWidth: .infinity)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(height: 50)
|
||||||
.frame(height: 50)
|
.padding(.horizontal)
|
||||||
.padding(.horizontal)
|
.padding(.bottom, 4)
|
||||||
.padding(.bottom, 4)
|
.background(.white)
|
||||||
.background(.white)
|
|
||||||
|
ScrollView {
|
||||||
ScrollView {
|
|
||||||
VStack(spacing: 0) {
|
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
if SharedMainViewModel.shared.displayedFriend != nil {
|
VStack(spacing: 0) {
|
||||||
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 100)
|
if SharedMainViewModel.shared.displayedFriend != nil {
|
||||||
|
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 100)
|
||||||
Text(contactAvatarModel.name)
|
|
||||||
.foregroundStyle(Color.grayMain2c700)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.default_text_style(styleSize: 14)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.padding(.top, 10)
|
|
||||||
|
|
||||||
Text(contactAvatarModel.lastPresenceInfo)
|
|
||||||
.foregroundStyle(contactAvatarModel.lastPresenceInfo == "Online"
|
|
||||||
? Color.greenSuccess500
|
|
||||||
: Color.orangeWarning600)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.default_text_style_300(styleSize: 12)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(minHeight: 150)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.padding(.top, 10)
|
|
||||||
.background(Color.gray100)
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
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: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
|
||||||
telecomManager.doCallOrJoinConf(address: address, isVideo: false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
isShowSipAddressesPopupType = 0
|
|
||||||
isShowSipAddressesPopup = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, label: {
|
|
||||||
VStack {
|
|
||||||
HStack(alignment: .center) {
|
|
||||||
Image("phone")
|
|
||||||
.renderingMode(.template)
|
|
||||||
.resizable()
|
|
||||||
.foregroundStyle(Color.grayMain2c600)
|
|
||||||
.frame(width: 25, height: 25)
|
|
||||||
}
|
|
||||||
.padding(16)
|
|
||||||
.background(Color.grayMain2c200)
|
|
||||||
.cornerRadius(40)
|
|
||||||
|
|
||||||
Text("contact_call_action")
|
Text(contactAvatarModel.name)
|
||||||
|
.foregroundStyle(Color.grayMain2c700)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
.default_text_style(styleSize: 14)
|
.default_text_style(styleSize: 14)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding(.top, 10)
|
||||||
|
|
||||||
|
Text(contactAvatarModel.lastPresenceInfo)
|
||||||
|
.foregroundStyle(contactAvatarModel.lastPresenceInfo == "Online"
|
||||||
|
? Color.greenSuccess500
|
||||||
|
: Color.orangeWarning600)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.default_text_style_300(styleSize: 12)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
.frame(minHeight: 150)
|
||||||
if !AppServices.corePreferences.disableChatFeature {
|
.frame(maxWidth: .infinity)
|
||||||
Spacer()
|
.padding(.top, 10)
|
||||||
|
.background(Color.gray100)
|
||||||
Button(action: {
|
|
||||||
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: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
|
||||||
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(Color.grayMain2c600)
|
|
||||||
.frame(width: 25, height: 25)
|
|
||||||
}
|
|
||||||
.padding(16)
|
|
||||||
.background(Color.grayMain2c200)
|
|
||||||
.cornerRadius(40)
|
|
||||||
|
|
||||||
Text("contact_message_action")
|
|
||||||
.default_text_style(styleSize: 14)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if !SharedMainViewModel.shared.disableVideoCall {
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
CoreContext.shared.doOnCoreQueue { core in
|
CoreContext.shared.doOnCoreQueue { core in
|
||||||
if contactAvatarModel.addresses.count == 1 {
|
if contactAvatarModel.addresses.count == 1 {
|
||||||
do {
|
do {
|
||||||
let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address)
|
let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address)
|
||||||
telecomManager.doCallOrJoinConf(address: address, isVideo: true)
|
telecomManager.doCallOrJoinConf(address: address, isVideo: false)
|
||||||
} catch {
|
} catch {
|
||||||
Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ")
|
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 {
|
} else if contactAvatarModel.addresses.count < 1 && contactAvatarModel.phoneNumbersWithLabel.count == 1 {
|
||||||
if let firstPhoneNumbersWithLabel = contactAvatarModel.phoneNumbersWithLabel.first, let address = core.interpretUrl(url: firstPhoneNumbersWithLabel.phoneNumber, applyInternationalPrefix: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
if let firstPhoneNumbersWithLabel = contactAvatarModel.phoneNumbersWithLabel.first, let address = core.interpretUrl(url: firstPhoneNumbersWithLabel.phoneNumber, applyInternationalPrefix: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
||||||
telecomManager.doCallOrJoinConf(address: address, isVideo: true)
|
telecomManager.doCallOrJoinConf(address: address, isVideo: false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
isShowSipAddressesPopupType = 2
|
isShowSipAddressesPopupType = 0
|
||||||
isShowSipAddressesPopup = true
|
isShowSipAddressesPopup = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +169,7 @@ struct ContactInnerFragment: View {
|
||||||
}, label: {
|
}, label: {
|
||||||
VStack {
|
VStack {
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
Image("video-camera")
|
Image("phone")
|
||||||
.renderingMode(.template)
|
.renderingMode(.template)
|
||||||
.resizable()
|
.resizable()
|
||||||
.foregroundStyle(Color.grayMain2c600)
|
.foregroundStyle(Color.grayMain2c600)
|
||||||
|
|
@ -259,44 +179,134 @@ struct ContactInnerFragment: View {
|
||||||
.background(Color.grayMain2c200)
|
.background(Color.grayMain2c200)
|
||||||
.cornerRadius(40)
|
.cornerRadius(40)
|
||||||
|
|
||||||
Text("contact_video_call_action")
|
Text("contact_call_action")
|
||||||
.default_text_style(styleSize: 14)
|
.default_text_style(styleSize: 14)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if !AppServices.corePreferences.disableChatFeature {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
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: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
||||||
|
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(Color.grayMain2c600)
|
||||||
|
.frame(width: 25, height: 25)
|
||||||
|
}
|
||||||
|
.padding(16)
|
||||||
|
.background(Color.grayMain2c200)
|
||||||
|
.cornerRadius(40)
|
||||||
|
|
||||||
|
Text("contact_message_action")
|
||||||
|
.default_text_style(styleSize: 14)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
if !SharedMainViewModel.shared.disableVideoCall {
|
||||||
|
Button(action: {
|
||||||
|
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: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
||||||
|
telecomManager.doCallOrJoinConf(address: address, isVideo: true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
isShowSipAddressesPopupType = 2
|
||||||
|
isShowSipAddressesPopup = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, label: {
|
||||||
|
VStack {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Image("video-camera")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.grayMain2c600)
|
||||||
|
.frame(width: 25, height: 25)
|
||||||
|
}
|
||||||
|
.padding(16)
|
||||||
|
.background(Color.grayMain2c200)
|
||||||
|
.cornerRadius(40)
|
||||||
|
|
||||||
|
Text("contact_video_call_action")
|
||||||
|
.default_text_style(styleSize: 14)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.top, 20)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.background(Color.gray100)
|
||||||
|
|
||||||
|
ContactInnerActionsFragment(
|
||||||
|
showingSheet: $showingSheet,
|
||||||
|
showShareSheet: $showShareSheet,
|
||||||
|
isShowDeletePopup: $isShowDeletePopup,
|
||||||
|
isShowDismissPopup: $isShowDismissPopup,
|
||||||
|
isShowTrustLevelPopup: $isShowTrustLevelPopup,
|
||||||
|
isShowIncreaseTrustLevelPopup: $isShowIncreaseTrustLevelPopup,
|
||||||
|
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails,
|
||||||
|
geometry: geometry,
|
||||||
|
actionEditButton: editNativeContact
|
||||||
|
)
|
||||||
|
.onAppear {
|
||||||
|
contactsListViewModel.fetchDevicesAndTrust()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.top, 20)
|
.frame(maxWidth: SharedMainViewModel.shared.maxWidth)
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.background(Color.gray100)
|
|
||||||
|
|
||||||
ContactInnerActionsFragment(
|
|
||||||
showingSheet: $showingSheet,
|
|
||||||
showShareSheet: $showShareSheet,
|
|
||||||
isShowDeletePopup: $isShowDeletePopup,
|
|
||||||
isShowDismissPopup: $isShowDismissPopup,
|
|
||||||
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails,
|
|
||||||
actionEditButton: editNativeContact
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.frame(maxWidth: SharedMainViewModel.shared.maxWidth)
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.background(Color.gray100)
|
||||||
}
|
}
|
||||||
.background(Color.gray100)
|
.background(.white)
|
||||||
}
|
.navigationBarHidden(true)
|
||||||
.background(.white)
|
.onRotate { newOrientation in
|
||||||
.navigationBarHidden(true)
|
orientation = newOrientation
|
||||||
.onRotate { newOrientation in
|
}
|
||||||
orientation = newOrientation
|
.fullScreenCover(isPresented: $presentingEditContact) {
|
||||||
}
|
NavigationView {
|
||||||
.fullScreenCover(isPresented: $presentingEditContact) {
|
EditContactView(contact: $cnContact)
|
||||||
NavigationView {
|
.navigationBarTitle("contact_edit_title")
|
||||||
EditContactView(contact: $cnContact)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.navigationBarTitle("contact_edit_title")
|
.edgesIgnoringSafeArea(.vertical)
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
}
|
||||||
.edgesIgnoringSafeArea(.vertical)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -321,15 +331,3 @@ struct ContactInnerFragment: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
|
||||||
ContactInnerFragment(
|
|
||||||
isShowDeletePopup: .constant(false),
|
|
||||||
showingSheet: .constant(false),
|
|
||||||
showShareSheet: .constant(false),
|
|
||||||
isShowDismissPopup: .constant(false),
|
|
||||||
isShowSipAddressesPopup: .constant(false),
|
|
||||||
isShowSipAddressesPopupType: .constant(0),
|
|
||||||
isShowEditContactFragmentInContactDetails: .constant(false)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
34
Linphone/UI/Main/Contacts/Model/ContactDeviceModel.swift
Normal file
34
Linphone/UI/Main/Contacts/Model/ContactDeviceModel.swift
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of Linphone
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import linphonesw
|
||||||
|
|
||||||
|
class ContactDeviceModel: ObservableObject, Identifiable {
|
||||||
|
let id = UUID()
|
||||||
|
var name: String
|
||||||
|
var address: Address
|
||||||
|
var trusted: Bool
|
||||||
|
|
||||||
|
init(name: String, address: Address, trusted: Bool) {
|
||||||
|
self.name = name
|
||||||
|
self.address = address
|
||||||
|
self.trusted = trusted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,8 @@ import SwiftUI
|
||||||
|
|
||||||
// swiftlint:disable line_length
|
// swiftlint:disable line_length
|
||||||
class ContactsListViewModel: ObservableObject {
|
class ContactsListViewModel: ObservableObject {
|
||||||
|
static let TAG = "[ConversationForwardMessageViewModel]"
|
||||||
|
|
||||||
@Published var selectedEditFriend: ContactAvatarModel?
|
@Published var selectedEditFriend: ContactAvatarModel?
|
||||||
|
|
||||||
var stringToCopy: String = ""
|
var stringToCopy: String = ""
|
||||||
|
|
@ -31,22 +33,28 @@ class ContactsListViewModel: ObservableObject {
|
||||||
var selectedFriendToShare: ContactAvatarModel?
|
var selectedFriendToShare: ContactAvatarModel?
|
||||||
var selectedFriendToDelete: ContactAvatarModel?
|
var selectedFriendToDelete: ContactAvatarModel?
|
||||||
|
|
||||||
|
@Published var devices: [ContactDeviceModel] = []
|
||||||
|
@Published var trustedDevicesPercentage: Double = 0.0
|
||||||
|
|
||||||
@Published var displayedConversation: ConversationModel?
|
@Published var displayedConversation: ConversationModel?
|
||||||
|
|
||||||
|
private var coreDelegate: CoreDelegate?
|
||||||
private var contactChatRoomDelegate: ChatRoomDelegate?
|
private var contactChatRoomDelegate: ChatRoomDelegate?
|
||||||
|
|
||||||
private let nativeAddressBookFriendList = "Native address-book"
|
private let nativeAddressBookFriendList = "Native address-book"
|
||||||
let linphoneAddressBookFriendList = "Linphone address-book"
|
let linphoneAddressBookFriendList = "Linphone address-book"
|
||||||
let tempRemoteAddressBookFriendList = "TempRemoteDirectoryContacts address-book"
|
let tempRemoteAddressBookFriendList = "TempRemoteDirectoryContacts address-book"
|
||||||
|
|
||||||
init() {}
|
init() {
|
||||||
|
addCoreDelegate()
|
||||||
|
}
|
||||||
|
|
||||||
func createOneToOneChatRoomWith(remote: Address) {
|
func createOneToOneChatRoomWith(remote: Address) {
|
||||||
CoreContext.shared.doOnCoreQueue { core in
|
CoreContext.shared.doOnCoreQueue { core in
|
||||||
let account = core.defaultAccount
|
let account = core.defaultAccount
|
||||||
if account == nil {
|
if account == nil {
|
||||||
Log.error(
|
Log.error(
|
||||||
"\(ConversationForwardMessageViewModel.TAG) No default account found, can't create conversation with \(remote.asStringUriOnly())"
|
"\(Self.TAG) No default account found, can't create conversation with \(remote.asStringUriOnly())"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -211,6 +219,30 @@ class ContactsListViewModel: ObservableObject {
|
||||||
chatRoom.addDelegate(delegate: contactChatRoomDelegate!)
|
chatRoom.addDelegate(delegate: contactChatRoomDelegate!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addCoreDelegate() {
|
||||||
|
CoreContext.shared.doOnCoreQueue { core in
|
||||||
|
if let coreDelegate = self.coreDelegate {
|
||||||
|
core.removeDelegate(delegate: coreDelegate)
|
||||||
|
self.coreDelegate = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.coreDelegate = CoreDelegateStub(
|
||||||
|
onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||||
|
if call.state == Call.State.End && SharedMainViewModel.shared.displayedFriend != nil {
|
||||||
|
// Updates trust if need be
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.fetchDevicesAndTrust()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.coreDelegate != nil {
|
||||||
|
core.addDelegate(delegate: self.coreDelegate!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func deleteSelectedContact() {
|
func deleteSelectedContact() {
|
||||||
CoreContext.shared.doOnCoreQueue { core in
|
CoreContext.shared.doOnCoreQueue { core in
|
||||||
if self.selectedFriendToDelete != nil && self.selectedFriendToDelete!.friend != nil {
|
if self.selectedFriendToDelete != nil && self.selectedFriendToDelete!.friend != nil {
|
||||||
|
|
@ -266,5 +298,44 @@ class ContactsListViewModel: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchDevicesAndTrust() {
|
||||||
|
if let friend = SharedMainViewModel.shared.displayedFriend?.friend {
|
||||||
|
var devicesList: [ContactDeviceModel] = []
|
||||||
|
|
||||||
|
let friendDevices = friend.devices
|
||||||
|
if friendDevices.isEmpty {
|
||||||
|
Log.info("\(Self.TAG) No device found for friend [\(friend.name ?? "")]")
|
||||||
|
} else {
|
||||||
|
let devicesCount = friendDevices.count
|
||||||
|
var trustedDevicesCount = 0
|
||||||
|
|
||||||
|
for device in friendDevices {
|
||||||
|
let trusted = device.securityLevel == .EndToEndEncryptedAndVerified
|
||||||
|
|
||||||
|
if let address = device.address {
|
||||||
|
devicesList.append(
|
||||||
|
ContactDeviceModel(
|
||||||
|
name: device.displayName ?? NSLocalizedString("contact_device_without_name", comment: ""),
|
||||||
|
address: address,
|
||||||
|
trusted: trusted
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if trusted {
|
||||||
|
trustedDevicesCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !devicesList.isEmpty {
|
||||||
|
let percentage = trustedDevicesCount * 100 / devicesCount
|
||||||
|
trustedDevicesPercentage = Double(percentage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
devices = devicesList
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// swiftlint:enable line_length
|
// swiftlint:enable line_length
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,9 @@ struct ContentView: View {
|
||||||
@State var isShowStartConversationFragment = false
|
@State var isShowStartConversationFragment = false
|
||||||
@State var isShowDismissPopup = false
|
@State var isShowDismissPopup = false
|
||||||
@State var isShowSendCancelMeetingNotificationPopup = false
|
@State var isShowSendCancelMeetingNotificationPopup = false
|
||||||
|
@State var isShowTrustLevelPopup = false
|
||||||
|
@State var isShowIncreaseTrustLevelPopup = false
|
||||||
|
@State var increaseTrustLevelPopupAcceptedTmp = false
|
||||||
@State var isShowStartCallGroupPopup = false
|
@State var isShowStartCallGroupPopup = false
|
||||||
@State var isShowDeleteMessagePopup = false
|
@State var isShowDeleteMessagePopup = false
|
||||||
@State var isShowSipAddressesPopup = false
|
@State var isShowSipAddressesPopup = false
|
||||||
|
|
@ -1013,8 +1016,10 @@ struct ContentView: View {
|
||||||
ContactFragment(
|
ContactFragment(
|
||||||
isShowDeletePopup: $isShowDeleteContactPopup,
|
isShowDeletePopup: $isShowDeleteContactPopup,
|
||||||
isShowDismissPopup: $isShowDismissPopup,
|
isShowDismissPopup: $isShowDismissPopup,
|
||||||
|
isShowTrustLevelPopup: $isShowTrustLevelPopup,
|
||||||
isShowSipAddressesPopup: $isShowSipAddressesPopup,
|
isShowSipAddressesPopup: $isShowSipAddressesPopup,
|
||||||
isShowSipAddressesPopupType: $isShowSipAddressesPopupType,
|
isShowSipAddressesPopupType: $isShowSipAddressesPopupType,
|
||||||
|
isShowIncreaseTrustLevelPopup: $isShowIncreaseTrustLevelPopup,
|
||||||
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
|
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
|
||||||
)
|
)
|
||||||
.environmentObject(contactsListVM)
|
.environmentObject(contactsListVM)
|
||||||
|
|
@ -1389,6 +1394,131 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isShowTrustLevelPopup {
|
||||||
|
if let displayedFriend = sharedMainViewModel.displayedFriend {
|
||||||
|
PopupView(
|
||||||
|
isShowPopup: $isShowTrustLevelPopup,
|
||||||
|
title: Text("contact_dialog_devices_trust_help_title"),
|
||||||
|
content: Text("contact_dialog_devices_trust_help_message"),
|
||||||
|
additionalContent: {
|
||||||
|
HStack {
|
||||||
|
let avatarSize = 50.0
|
||||||
|
let avatar = Avatar(contactAvatarModel: displayedFriend, avatarSize: avatarSize, hidePresence: true)
|
||||||
|
|
||||||
|
avatar
|
||||||
|
|
||||||
|
Image("arrow-right")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.grayMain2c600)
|
||||||
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
|
.padding(.all, 10)
|
||||||
|
|
||||||
|
ZStack {
|
||||||
|
avatar
|
||||||
|
|
||||||
|
Circle()
|
||||||
|
.stroke(Color.blueInfo500, lineWidth: 2)
|
||||||
|
.frame(width: avatarSize, height: avatarSize)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
Image("trusted")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||||
|
.padding(.trailing, 1)
|
||||||
|
.padding(.bottom, 1)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(width: avatarSize, height: avatarSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
},
|
||||||
|
titleFirstButton: nil,
|
||||||
|
actionFirstButton: {},
|
||||||
|
titleSecondButton: Text("dialog_understood"),
|
||||||
|
actionSecondButton: { self.isShowTrustLevelPopup.toggle() },
|
||||||
|
titleThirdButton: nil,
|
||||||
|
actionThirdButton: {}
|
||||||
|
)
|
||||||
|
.background(.black.opacity(0.65))
|
||||||
|
.zIndex(3)
|
||||||
|
.onTapGesture {
|
||||||
|
self.isShowTrustLevelPopup.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isShowIncreaseTrustLevelPopup {
|
||||||
|
if let displayedFriend = sharedMainViewModel.displayedFriend {
|
||||||
|
PopupView(
|
||||||
|
isShowPopup: $isShowIncreaseTrustLevelPopup,
|
||||||
|
title: Text("contact_dialog_increase_trust_level_title"),
|
||||||
|
content: Text(String(format: String(localized: "contact_dialog_increase_trust_level_message"), displayedFriend.name, SharedMainViewModel.shared.increaseTrustLevelPopupDeviceName)),
|
||||||
|
additionalContent: {
|
||||||
|
if !SharedMainViewModel.shared.increaseTrustLevelPopupAccepted {
|
||||||
|
HStack {
|
||||||
|
Button(action: {
|
||||||
|
increaseTrustLevelPopupAcceptedTmp.toggle()
|
||||||
|
}, label: {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: increaseTrustLevelPopupAcceptedTmp ? "checkmark.square.fill" : "square")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.orangeMain500)
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
|
||||||
|
Text("dialog_do_not_show_anymore")
|
||||||
|
.tint(Color.grayMain2c600)
|
||||||
|
.default_text_style(styleSize: 15)
|
||||||
|
}
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
titleFirstButton: nil,
|
||||||
|
actionFirstButton: {},
|
||||||
|
titleSecondButton: Text("contact_call_action"),
|
||||||
|
actionSecondButton: {
|
||||||
|
if increaseTrustLevelPopupAcceptedTmp == true {
|
||||||
|
SharedMainViewModel.shared.changeIncreaseTrustLevelPopupAccepted()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let deviceAddress = SharedMainViewModel.shared.increaseTrustLevelPopupDeviceAddress {
|
||||||
|
TelecomManager.shared.doCallOrJoinConf(address: deviceAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.isShowIncreaseTrustLevelPopup.toggle()
|
||||||
|
self.increaseTrustLevelPopupAcceptedTmp = false
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceName = ""
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceAddress = nil
|
||||||
|
},
|
||||||
|
titleThirdButton: Text("dialog_cancel"),
|
||||||
|
actionThirdButton: {
|
||||||
|
self.isShowIncreaseTrustLevelPopup.toggle()
|
||||||
|
self.increaseTrustLevelPopupAcceptedTmp = false
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceName = ""
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceAddress = nil
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.background(.black.opacity(0.65))
|
||||||
|
.zIndex(3)
|
||||||
|
.onTapGesture {
|
||||||
|
self.isShowIncreaseTrustLevelPopup.toggle()
|
||||||
|
self.increaseTrustLevelPopupAcceptedTmp = false
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceName = ""
|
||||||
|
SharedMainViewModel.shared.increaseTrustLevelPopupDeviceAddress = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if isShowStartCallGroupPopup {
|
if isShowStartCallGroupPopup {
|
||||||
PopupView(
|
PopupView(
|
||||||
isShowPopup: $isShowStartCallGroupPopup,
|
isShowPopup: $isShowStartCallGroupPopup,
|
||||||
|
|
|
||||||
|
|
@ -885,7 +885,7 @@ struct ChatBubbleView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: geometryProxy.size.width - 150)
|
.frame(width: max(0, geometryProxy.size.width - 150))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Photos
|
import Photos
|
||||||
|
|
||||||
struct PopupView: View {
|
struct PopupView<AdditionalContent: View>: View {
|
||||||
|
|
||||||
var permissionManager = PermissionManager.shared
|
var permissionManager = PermissionManager.shared
|
||||||
|
|
||||||
|
|
@ -28,6 +28,8 @@ struct PopupView: View {
|
||||||
var title: Text
|
var title: Text
|
||||||
var content: Text?
|
var content: Text?
|
||||||
|
|
||||||
|
private let additionalContent: AdditionalContent
|
||||||
|
|
||||||
var titleFirstButton: Text?
|
var titleFirstButton: Text?
|
||||||
var actionFirstButton: () -> Void
|
var actionFirstButton: () -> Void
|
||||||
|
|
||||||
|
|
@ -37,6 +39,30 @@ struct PopupView: View {
|
||||||
var titleThirdButton: Text?
|
var titleThirdButton: Text?
|
||||||
var actionThirdButton: () -> Void
|
var actionThirdButton: () -> Void
|
||||||
|
|
||||||
|
init(
|
||||||
|
isShowPopup: Binding<Bool>,
|
||||||
|
title: Text,
|
||||||
|
content: Text? = nil,
|
||||||
|
@ViewBuilder additionalContent: () -> AdditionalContent = { EmptyView() },
|
||||||
|
titleFirstButton: Text? = nil,
|
||||||
|
actionFirstButton: @escaping () -> Void = {},
|
||||||
|
titleSecondButton: Text? = nil,
|
||||||
|
actionSecondButton: @escaping () -> Void = {},
|
||||||
|
titleThirdButton: Text? = nil,
|
||||||
|
actionThirdButton: @escaping () -> Void = {}
|
||||||
|
) {
|
||||||
|
self._isShowPopup = isShowPopup
|
||||||
|
self.title = title
|
||||||
|
self.content = content
|
||||||
|
self.additionalContent = additionalContent()
|
||||||
|
self.titleFirstButton = titleFirstButton
|
||||||
|
self.actionFirstButton = actionFirstButton
|
||||||
|
self.titleSecondButton = titleSecondButton
|
||||||
|
self.actionSecondButton = actionSecondButton
|
||||||
|
self.titleThirdButton = titleThirdButton
|
||||||
|
self.actionThirdButton = actionThirdButton
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geometry in
|
GeometryReader { geometry in
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
|
|
@ -52,6 +78,8 @@ struct PopupView: View {
|
||||||
.padding(.bottom, 20)
|
.padding(.bottom, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
additionalContent
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
if titleFirstButton != nil {
|
if titleFirstButton != nil {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
|
|
@ -116,16 +144,3 @@ struct PopupView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
|
||||||
PopupView(isShowPopup: .constant(true),
|
|
||||||
title: Text("Title"),
|
|
||||||
content: Text("Content"),
|
|
||||||
titleFirstButton: Text("Accept all"),
|
|
||||||
actionFirstButton: {},
|
|
||||||
titleSecondButton: Text("dialog_confirm"),
|
|
||||||
actionSecondButton: {},
|
|
||||||
titleThirdButton: Text("dialog_cancel"),
|
|
||||||
actionThirdButton: {})
|
|
||||||
.background(.black.opacity(0.65))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ class SharedMainViewModel: ObservableObject {
|
||||||
@Published var displayProfileMode = false
|
@Published var displayProfileMode = false
|
||||||
@Published var defaultAvatar: URL?
|
@Published var defaultAvatar: URL?
|
||||||
@Published var indexView: Int = 0
|
@Published var indexView: Int = 0
|
||||||
|
@Published var increaseTrustLevelPopupAccepted = false
|
||||||
|
@Published var increaseTrustLevelPopupDeviceName = ""
|
||||||
|
@Published var increaseTrustLevelPopupDeviceAddress: Address?
|
||||||
|
|
||||||
@Published var displayedFriend: ContactAvatarModel?
|
@Published var displayedFriend: ContactAvatarModel?
|
||||||
@Published var displayedCall: HistoryModel?
|
@Published var displayedCall: HistoryModel?
|
||||||
|
|
@ -64,6 +67,7 @@ class SharedMainViewModel: ObservableObject {
|
||||||
let displayProfileModeKey = "display_profile_mode"
|
let displayProfileModeKey = "display_profile_mode"
|
||||||
let defaultAvatarKey = "default_avatar"
|
let defaultAvatarKey = "default_avatar"
|
||||||
let indexViewKey = "index_view"
|
let indexViewKey = "index_view"
|
||||||
|
let increaseTrustLevelKey = "increase_trust_level"
|
||||||
|
|
||||||
var maxWidth = 600.0
|
var maxWidth = 600.0
|
||||||
|
|
||||||
|
|
@ -101,6 +105,12 @@ class SharedMainViewModel: ObservableObject {
|
||||||
defaultAvatar = defaultAvatarTmp
|
defaultAvatar = defaultAvatarTmp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if preferences.object(forKey: increaseTrustLevelKey) == nil {
|
||||||
|
preferences.set(increaseTrustLevelPopupAccepted, forKey: increaseTrustLevelKey)
|
||||||
|
} else {
|
||||||
|
increaseTrustLevelPopupAccepted = preferences.bool(forKey: increaseTrustLevelKey)
|
||||||
|
}
|
||||||
|
|
||||||
updateMissedCallsCount()
|
updateMissedCallsCount()
|
||||||
updateDisableVideoCall()
|
updateDisableVideoCall()
|
||||||
|
|
@ -146,6 +156,14 @@ class SharedMainViewModel: ObservableObject {
|
||||||
preferences.set(defaultAvatar, forKey: defaultAvatarKey)
|
preferences.set(defaultAvatar, forKey: defaultAvatarKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func changeIncreaseTrustLevelPopupAccepted() {
|
||||||
|
let preferences = UserDefaults.standard
|
||||||
|
|
||||||
|
increaseTrustLevelPopupAccepted = true
|
||||||
|
preferences.set(increaseTrustLevelPopupAccepted, forKey: increaseTrustLevelKey)
|
||||||
|
}
|
||||||
|
|
||||||
func changeIndexView(indexViewInt: Int) {
|
func changeIndexView(indexViewInt: Int) {
|
||||||
let preferences = UserDefaults.standard
|
let preferences = UserDefaults.standard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@
|
||||||
D7AEB9762F39E2A400298546 /* ConversationMediaListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB9752F39E2A300298546 /* ConversationMediaListViewModel.swift */; };
|
D7AEB9762F39E2A400298546 /* ConversationMediaListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB9752F39E2A300298546 /* ConversationMediaListViewModel.swift */; };
|
||||||
D7AEB9782F39E2C300298546 /* ConversationDocumentsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB9772F39E2C100298546 /* ConversationDocumentsListViewModel.swift */; };
|
D7AEB9782F39E2C300298546 /* ConversationDocumentsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB9772F39E2C100298546 /* ConversationDocumentsListViewModel.swift */; };
|
||||||
D7AEB97A2F39E83600298546 /* FileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB9792F39E83500298546 /* FileModel.swift */; };
|
D7AEB97A2F39E83600298546 /* FileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB9792F39E83500298546 /* FileModel.swift */; };
|
||||||
|
D7AEB9A02F3E219600298546 /* ContactDeviceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AEB99F2F3E218A00298546 /* ContactDeviceModel.swift */; };
|
||||||
D7B5066D2AEFA9B900CEB4E9 /* ContactInnerFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B5066C2AEFA9B900CEB4E9 /* ContactInnerFragment.swift */; };
|
D7B5066D2AEFA9B900CEB4E9 /* ContactInnerFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B5066C2AEFA9B900CEB4E9 /* ContactInnerFragment.swift */; };
|
||||||
D7B5678E2B28888F00DE63EB /* CallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B5678D2B28888F00DE63EB /* CallView.swift */; };
|
D7B5678E2B28888F00DE63EB /* CallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B5678D2B28888F00DE63EB /* CallView.swift */; };
|
||||||
D7B99E992B29B39000BE7BF2 /* CallViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B99E982B29B39000BE7BF2 /* CallViewModel.swift */; };
|
D7B99E992B29B39000BE7BF2 /* CallViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B99E982B29B39000BE7BF2 /* CallViewModel.swift */; };
|
||||||
|
|
@ -433,6 +434,7 @@
|
||||||
D7AEB9752F39E2A300298546 /* ConversationMediaListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationMediaListViewModel.swift; sourceTree = "<group>"; };
|
D7AEB9752F39E2A300298546 /* ConversationMediaListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationMediaListViewModel.swift; sourceTree = "<group>"; };
|
||||||
D7AEB9772F39E2C100298546 /* ConversationDocumentsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationDocumentsListViewModel.swift; sourceTree = "<group>"; };
|
D7AEB9772F39E2C100298546 /* ConversationDocumentsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationDocumentsListViewModel.swift; sourceTree = "<group>"; };
|
||||||
D7AEB9792F39E83500298546 /* FileModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileModel.swift; sourceTree = "<group>"; };
|
D7AEB9792F39E83500298546 /* FileModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileModel.swift; sourceTree = "<group>"; };
|
||||||
|
D7AEB99F2F3E218A00298546 /* ContactDeviceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDeviceModel.swift; sourceTree = "<group>"; };
|
||||||
D7B5066C2AEFA9B900CEB4E9 /* ContactInnerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactInnerFragment.swift; sourceTree = "<group>"; };
|
D7B5066C2AEFA9B900CEB4E9 /* ContactInnerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactInnerFragment.swift; sourceTree = "<group>"; };
|
||||||
D7B5678D2B28888F00DE63EB /* CallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallView.swift; sourceTree = "<group>"; };
|
D7B5678D2B28888F00DE63EB /* CallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallView.swift; sourceTree = "<group>"; };
|
||||||
D7B99E982B29B39000BE7BF2 /* CallViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewModel.swift; sourceTree = "<group>"; };
|
D7B99E982B29B39000BE7BF2 /* CallViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -822,6 +824,7 @@
|
||||||
D726E4372B1643FF0083C415 /* Model */ = {
|
D726E4372B1643FF0083C415 /* Model */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D7AEB99F2F3E218A00298546 /* ContactDeviceModel.swift */,
|
||||||
D726E4382B16440C0083C415 /* ContactAvatarModel.swift */,
|
D726E4382B16440C0083C415 /* ContactAvatarModel.swift */,
|
||||||
);
|
);
|
||||||
path = Model;
|
path = Model;
|
||||||
|
|
@ -1601,6 +1604,7 @@
|
||||||
D74DA0122C047F0700A8561D /* HistoryModel.swift in Sources */,
|
D74DA0122C047F0700A8561D /* HistoryModel.swift in Sources */,
|
||||||
66D382052CEB7E0A0063E1C5 /* ShortcutModel.swift in Sources */,
|
66D382052CEB7E0A0063E1C5 /* ShortcutModel.swift in Sources */,
|
||||||
D72250692ADFBF2D008FB426 /* SideMenu.swift in Sources */,
|
D72250692ADFBF2D008FB426 /* SideMenu.swift in Sources */,
|
||||||
|
D7AEB9A02F3E219600298546 /* ContactDeviceModel.swift in Sources */,
|
||||||
D703F7082DC8C605005B8F75 /* FilePicker.swift in Sources */,
|
D703F7082DC8C605005B8F75 /* FilePicker.swift in Sources */,
|
||||||
C6DC4E3F2C19C289009096FD /* SideMenuEntry.swift in Sources */,
|
C6DC4E3F2C19C289009096FD /* SideMenuEntry.swift in Sources */,
|
||||||
D714DE622C1C4636006C1F1D /* RegisterCodeConfirmationFragment.swift in Sources */,
|
D714DE622C1C4636006C1F1D /* RegisterCodeConfirmationFragment.swift in Sources */,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue