forked from mirrors/linphone-iphone
Change ZRTP SAS UI
This commit is contained in:
parent
8875e2ba54
commit
4b46322264
13 changed files with 900 additions and 191 deletions
21
Linphone/Assets.xcassets/lock-key.imageset/Contents.json
vendored
Normal file
21
Linphone/Assets.xcassets/lock-key.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "lock-key.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Linphone/Assets.xcassets/lock-key.imageset/lock-key.svg
vendored
Normal file
1
Linphone/Assets.xcassets/lock-key.imageset/lock-key.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="M128,112a28,28,0,0,0-8,54.83V184a8,8,0,0,0,16,0V166.83A28,28,0,0,0,128,112Zm0,40a12,12,0,1,1,12-12A12,12,0,0,1,128,152Zm80-72H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 417 B |
21
Linphone/Assets.xcassets/security.imageset/Contents.json
vendored
Normal file
21
Linphone/Assets.xcassets/security.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "security.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Linphone/Assets.xcassets/security.imageset/security.svg
vendored
Normal file
6
Linphone/Assets.xcassets/security.imageset/security.svg
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Sécurité">
|
||||||
|
<path id="Vector" d="M23 2.52647V9.2355C23 19.4652 14.3123 22.8591 12.5729 23.4356C12.2014 23.5614 11.7986 23.5614 11.4271 23.4356C9.68542 22.8591 1 19.4652 1 9.2355V2.52647C1 2.04205 1.19315 1.57747 1.53697 1.23493C1.88079 0.892387 2.3471 0.699951 2.83333 0.699951H21.1667C21.6529 0.699951 22.1192 0.892387 22.463 1.23493C22.8068 1.57747 23 2.04205 23 2.52647Z" fill="#364860"/>
|
||||||
|
<path id="Vector_2" d="M20.3333 1.59998H3.66667C3.22464 1.59998 2.80072 1.77557 2.48816 2.08813C2.17559 2.40069 2 2.82461 2 3.26664V9.38852C2 18.7229 9.89792 21.8198 11.4792 22.3458C11.8169 22.4607 12.1831 22.4607 12.5208 22.3458C14.1042 21.8198 22 18.7229 22 9.38852V3.26664C22 2.82461 21.8244 2.40069 21.5118 2.08813C21.1993 1.77557 20.7754 1.59998 20.3333 1.59998ZM16.7563 8.85623L10.9229 14.6896C10.8455 14.767 10.7536 14.8285 10.6525 14.8704C10.5513 14.9124 10.4428 14.934 10.3333 14.934C10.2238 14.934 10.1154 14.9124 10.0142 14.8704C9.91305 14.8285 9.82114 14.767 9.74375 14.6896L7.24375 12.1896C7.08738 12.0332 6.99954 11.8211 6.99954 11.6C6.99954 11.3788 7.08738 11.1668 7.24375 11.0104C7.40012 10.854 7.6122 10.7662 7.83333 10.7662C8.05447 10.7662 8.26655 10.854 8.42292 11.0104L10.3333 12.9208L15.5771 7.67706C15.6545 7.59963 15.7464 7.53822 15.8476 7.49631C15.9487 7.45441 16.0572 7.43285 16.1667 7.43285C16.2762 7.43285 16.3846 7.45441 16.4857 7.49631C16.5869 7.53822 16.6788 7.59963 16.7563 7.67706C16.8337 7.75448 16.8951 7.8464 16.937 7.94756C16.9789 8.04872 17.0005 8.15715 17.0005 8.26664C17.0005 8.37614 16.9789 8.48456 16.937 8.58572C16.8951 8.68688 16.8337 8.7788 16.7563 8.85623Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
21
Linphone/Assets.xcassets/shield-warning.imageset/Contents.json
vendored
Normal file
21
Linphone/Assets.xcassets/shield-warning.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "shield-warning.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Linphone/Assets.xcassets/shield-warning.imageset/shield-warning.svg
vendored
Normal file
1
Linphone/Assets.xcassets/shield-warning.imageset/shield-warning.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="M120,136V96a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,48a12,12,0,1,0-12-12A12,12,0,0,0,128,184ZM224,56v56c0,52.72-25.52,84.67-46.93,102.19-23.06,18.86-46,25.27-47,25.53a8,8,0,0,1-4.2,0c-1-.26-23.91-6.67-47-25.53C57.52,196.67,32,164.72,32,112V56A16,16,0,0,1,48,40H208A16,16,0,0,1,224,56Zm-16,0L48,56l0,56c0,37.3,13.82,67.51,41.07,89.81A128.25,128.25,0,0,0,128,223.62a129.3,129.3,0,0,0,39.41-22.2C194.34,179.16,208,149.07,208,112Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 546 B |
|
|
@ -204,9 +204,6 @@
|
||||||
},
|
},
|
||||||
"Appel" : {
|
"Appel" : {
|
||||||
|
|
||||||
},
|
|
||||||
"Appel chiffré de bout en bout" : {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"assistant_account_create" : {
|
"assistant_account_create" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|
@ -421,6 +418,278 @@
|
||||||
},
|
},
|
||||||
"Call transfer failed!" : {
|
"Call transfer failed!" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"call_action_hang_up" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Hang up"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Raccrocher"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_security_alert_message" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "This call confidentiality may be compromise!"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "La confidentialité de votre appel peut être compromise !"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_security_alert_title" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Security alert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Alerte de sécurité"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_security_alert_try_again" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Try again"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Réessayer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_validate_trust_letters_do_not_match" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Nothing matches"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Aucune correspondance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_validate_trust_local_code_label" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Your code:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Votre code :"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_validate_trust_message" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "For your safety, we need to authenticate your correspondent device.
Please exchange your codes:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Pour garantir le chiffrement, nous avons besoin d’authentifier l’appareil de votre correspondant.
Veuillez échanger vos codes :"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_validate_trust_remote_code_label" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Correspondent code:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Code correspondant :"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_validate_trust_title" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Validate the device"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Vérification de sécurité"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_dialog_zrtp_validate_trust_warning_message" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "For your safety, we need to re-authenticate your correspondent device.
Please re-exchange your codes:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Pour garantir le chiffrement, nous avons besoin de réauthentifier l’appareil de votre correspondant.
Veuillez ré-échanger vos codes :"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_not_encrypted" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Call is not encrypted"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Appel non chiffré"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_srtp_point_to_point_encrypted" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Point-to-point encrypted by SRTP"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Appel chiffré de point à point"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_waiting_for_encryption_info" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Waiting for encryption…"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "En attente du chiffrement…"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_zrtp_end_to_end_encrypted" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "End-to-end encrypted by ZRTP"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Appel chiffré de bout en bout"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_zrtp_sas_validation_required" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Validation required"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "needs_review",
|
||||||
|
"value" : "Vérification nécessaire"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"call_zrtp_sas_validation_skip" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Skip"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Passer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Calls" : {
|
"Calls" : {
|
||||||
|
|
||||||
|
|
@ -889,21 +1158,9 @@
|
||||||
},
|
},
|
||||||
"Joining..." : {
|
"Joining..." : {
|
||||||
|
|
||||||
},
|
|
||||||
"Key" : {
|
|
||||||
"extractionState" : "manual"
|
|
||||||
},
|
|
||||||
"Key 1" : {
|
|
||||||
"extractionState" : "manual"
|
|
||||||
},
|
|
||||||
"Key 2" : {
|
|
||||||
"extractionState" : "manual"
|
|
||||||
},
|
},
|
||||||
"Last name" : {
|
"Last name" : {
|
||||||
|
|
||||||
},
|
|
||||||
"Letters don't match!" : {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"Linphone" : {
|
"Linphone" : {
|
||||||
|
|
||||||
|
|
@ -1101,9 +1358,6 @@
|
||||||
},
|
},
|
||||||
"Resuming" : {
|
"Resuming" : {
|
||||||
|
|
||||||
},
|
|
||||||
"Say %@ and click on the letters given by your correspondent:" : {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"Say something..." : {
|
"Say something..." : {
|
||||||
|
|
||||||
|
|
@ -1283,9 +1537,6 @@
|
||||||
},
|
},
|
||||||
"Username error" : {
|
"Username error" : {
|
||||||
|
|
||||||
},
|
|
||||||
"Validate the device" : {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"Vidéo" : {
|
"Vidéo" : {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,12 @@ extension ProviderDelegate: CXProviderDelegate {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if UIApplication.shared.applicationState != .active {
|
if UIApplication.shared.applicationState != .active {
|
||||||
TelecomManager.shared.backgroundContextCall = call
|
TelecomManager.shared.backgroundContextCall = call
|
||||||
TelecomManager.shared.backgroundContextCameraIsEnabled = call?.params?.videoEnabled == true || call?.callLog?.wasConference() == true
|
if call?.callLog != nil {
|
||||||
|
TelecomManager.shared.backgroundContextCameraIsEnabled = call?.params?.videoEnabled == true || call?.callLog?.wasConference() == true
|
||||||
|
} else {
|
||||||
|
TelecomManager.shared.backgroundContextCameraIsEnabled = call?.params?.videoEnabled == true
|
||||||
|
}
|
||||||
|
|
||||||
if #available(iOS 16.0, *) {
|
if #available(iOS 16.0, *) {
|
||||||
if call?.cameraEnabled == true {
|
if call?.cameraEnabled == true {
|
||||||
call?.cameraEnabled = AVCaptureSession().isMultitaskingCameraAccessSupported
|
call?.cameraEnabled = AVCaptureSession().isMultitaskingCameraAccessSupported
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ class TelecomManager: ObservableObject {
|
||||||
@Published var callInProgress: Bool = false
|
@Published var callInProgress: Bool = false
|
||||||
@Published var callDisplayed: Bool = true
|
@Published var callDisplayed: Bool = true
|
||||||
@Published var callStarted: Bool = false
|
@Published var callStarted: Bool = false
|
||||||
|
@Published var isNotVerifiedCounter: Int = 0
|
||||||
@Published var outgoingCallStarted: Bool = false
|
@Published var outgoingCallStarted: Bool = false
|
||||||
@Published var remoteConfVideo: Bool = false
|
@Published var remoteConfVideo: Bool = false
|
||||||
@Published var isRecordingByRemote: Bool = false
|
@Published var isRecordingByRemote: Bool = false
|
||||||
|
|
@ -269,6 +270,7 @@ class TelecomManager: ObservableObject {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.outgoingCallStarted = true
|
self.outgoingCallStarted = true
|
||||||
self.callStarted = true
|
self.callStarted = true
|
||||||
|
self.isNotVerifiedCounter = 0
|
||||||
if self.callInProgress == false {
|
if self.callInProgress == false {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
self.callInProgress = true
|
self.callInProgress = true
|
||||||
|
|
@ -316,6 +318,7 @@ class TelecomManager: ObservableObject {
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.callStarted = true
|
self.callStarted = true
|
||||||
|
self.isNotVerifiedCounter = 0
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Log.error("accept call failed \(error)")
|
Log.error("accept call failed \(error)")
|
||||||
|
|
|
||||||
|
|
@ -177,11 +177,19 @@ struct CallView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
if callViewModel.zrtpPopupDisplayed == true {
|
if callViewModel.zrtpPopupDisplayed == true {
|
||||||
ZRTPPopup(callViewModel: callViewModel)
|
if idiom != .pad
|
||||||
.background(.black.opacity(0.65))
|
&& (orientation == .landscapeLeft
|
||||||
.onTapGesture {
|
|| orientation == .landscapeRight
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height)
|
||||||
}
|
&& buttonSize != 45 {
|
||||||
|
ZRTPPopup(callViewModel: callViewModel, resizeView: 1.5)
|
||||||
|
.background(.black.opacity(0.65))
|
||||||
|
.frame(maxHeight: geo.size.height)
|
||||||
|
} else {
|
||||||
|
ZRTPPopup(callViewModel: callViewModel, resizeView: buttonSize == 45 ? 1.5 : 1)
|
||||||
|
.background(.black.opacity(0.65))
|
||||||
|
.frame(maxHeight: geo.size.height)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if telecomManager.remainingCall {
|
if telecomManager.remainingCall {
|
||||||
|
|
@ -226,7 +234,7 @@ struct CallView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(callViewModel.displayName)
|
Text(callViewModel.displayName)
|
||||||
.default_text_style_white_800(styleSize: 16)
|
.default_text_style_white_800(styleSize: 16)
|
||||||
|
|
||||||
if !telecomManager.outgoingCallStarted && telecomManager.callInProgress {
|
if !telecomManager.outgoingCallStarted && telecomManager.callInProgress {
|
||||||
Text("|")
|
Text("|")
|
||||||
|
|
@ -281,26 +289,114 @@ struct CallView: View {
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
|
|
||||||
if callViewModel.isMediaEncrypted {
|
if !telecomManager.outgoingCallStarted && telecomManager.callInProgress {
|
||||||
HStack {
|
if callViewModel.isMediaEncrypted && callViewModel.isRemoteDeviceTrusted && callViewModel.isZrtp {
|
||||||
Image("lock_simple")
|
HStack {
|
||||||
.resizable()
|
Image("lock-key")
|
||||||
.frame(width: 15, height: 15, alignment: .leading)
|
.renderingMode(.template)
|
||||||
.padding(.leading, 50)
|
.resizable()
|
||||||
.padding(.top, 35)
|
.foregroundStyle(Color.blueInfo500)
|
||||||
|
.frame(width: 15, height: 15, alignment: .leading)
|
||||||
Text("Appel chiffré de bout en bout")
|
.padding(.leading, 50)
|
||||||
.foregroundStyle(Color.blueInfo500)
|
.padding(.top, 35)
|
||||||
.default_text_style_white(styleSize: 12)
|
|
||||||
.padding(.top, 35)
|
Text("call_zrtp_end_to_end_encrypted")
|
||||||
|
.foregroundStyle(Color.blueInfo500)
|
||||||
Spacer()
|
.default_text_style_white(styleSize: 12)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
mediaEncryptedSheet = true
|
||||||
|
}
|
||||||
|
.frame(height: 40)
|
||||||
|
.zIndex(1)
|
||||||
|
} else if callViewModel.isMediaEncrypted && !callViewModel.isZrtp {
|
||||||
|
HStack {
|
||||||
|
Image("lock_simple")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.blueInfo500)
|
||||||
|
.frame(width: 15, height: 15, alignment: .leading)
|
||||||
|
.padding(.leading, 50)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Text("call_srtp_point_to_point_encrypted")
|
||||||
|
.foregroundStyle(Color.blueInfo500)
|
||||||
|
.default_text_style_white(styleSize: 12)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
mediaEncryptedSheet = true
|
||||||
|
}
|
||||||
|
.frame(height: 40)
|
||||||
|
.zIndex(1)
|
||||||
|
} else if callViewModel.isMediaEncrypted && (!callViewModel.isRemoteDeviceTrusted && callViewModel.isZrtp) || callViewModel.cacheMismatch {
|
||||||
|
HStack {
|
||||||
|
Image("warning-circle")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(Color.orangeWarning600)
|
||||||
|
.frame(width: 15, height: 15, alignment: .leading)
|
||||||
|
.padding(.leading, 50)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Text("call_zrtp_sas_validation_required")
|
||||||
|
.foregroundStyle(Color.orangeWarning600)
|
||||||
|
.default_text_style_white(styleSize: 12)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
mediaEncryptedSheet = true
|
||||||
|
}
|
||||||
|
.frame(height: 40)
|
||||||
|
.zIndex(1)
|
||||||
|
} else if callViewModel.isNotEncrypted {
|
||||||
|
HStack {
|
||||||
|
Image("lock_simple")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
.frame(width: 15, height: 15, alignment: .leading)
|
||||||
|
.padding(.leading, 50)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Text("call_not_encrypted")
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
.default_text_style_white(styleSize: 12)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
mediaEncryptedSheet = true
|
||||||
|
}
|
||||||
|
.frame(height: 40)
|
||||||
|
.zIndex(1)
|
||||||
|
} else {
|
||||||
|
HStack {
|
||||||
|
ProgressView()
|
||||||
|
.controlSize(.mini)
|
||||||
|
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||||
|
.frame(width: 15, height: 15, alignment: .leading)
|
||||||
|
.padding(.leading, 50)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Text("call_waiting_for_encryption_info")
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
.default_text_style_white(styleSize: 12)
|
||||||
|
.padding(.top, 35)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(height: 40)
|
||||||
|
.zIndex(1)
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
|
||||||
mediaEncryptedSheet = true
|
|
||||||
}
|
|
||||||
.frame(height: 40)
|
|
||||||
.zIndex(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,123 +27,367 @@ struct ZRTPPopup: View {
|
||||||
|
|
||||||
@ObservedObject var callViewModel: CallViewModel
|
@ObservedObject var callViewModel: CallViewModel
|
||||||
|
|
||||||
|
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||||
|
@State private var orientation = UIDevice.current.orientation
|
||||||
|
|
||||||
|
var resizeView: CGFloat
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
if callViewModel.isNotVerified {
|
||||||
|
alertZRTP
|
||||||
|
} else {
|
||||||
|
popupZRTP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var popupZRTP: some View {
|
||||||
GeometryReader { geometry in
|
GeometryReader { geometry in
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("Validate the device")
|
ZStack(alignment: .top, content: {
|
||||||
.default_text_style_600(styleSize: 20)
|
HStack {
|
||||||
|
Spacer()
|
||||||
Text("Say \(callViewModel.upperCaseAuthTokenToRead) and click on the letters given by your correspondent:")
|
|
||||||
.default_text_style(styleSize: 15)
|
VStack {
|
||||||
.padding(.bottom, 20)
|
Image("security")
|
||||||
|
.resizable()
|
||||||
HStack(spacing: 25) {
|
.frame(width: 20, height: 20, alignment: .leading)
|
||||||
Spacer()
|
|
||||||
|
Text("call_dialog_zrtp_validate_trust_title")
|
||||||
HStack(alignment: .center) {
|
.default_text_style_white_700(styleSize: 16 / resizeView)
|
||||||
Text(callViewModel.letters1)
|
}
|
||||||
.default_text_style(styleSize: 30)
|
|
||||||
.frame(width: 60, height: 60)
|
|
||||||
}
|
|
||||||
.padding(10)
|
|
||||||
.background(Color.grayMain2c200)
|
|
||||||
.cornerRadius(40)
|
|
||||||
.onTapGesture {
|
|
||||||
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters1)
|
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
|
||||||
Text(callViewModel.letters2)
|
|
||||||
.default_text_style(styleSize: 30)
|
|
||||||
.frame(width: 60, height: 60)
|
|
||||||
}
|
|
||||||
.padding(10)
|
|
||||||
.background(Color.grayMain2c200)
|
|
||||||
.cornerRadius(40)
|
|
||||||
.onTapGesture {
|
|
||||||
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters2)
|
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(.bottom, 20)
|
|
||||||
|
|
||||||
HStack(spacing: 25) {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
|
||||||
Text(callViewModel.letters3)
|
|
||||||
.default_text_style(styleSize: 30)
|
|
||||||
.frame(width: 60, height: 60)
|
|
||||||
}
|
|
||||||
.padding(10)
|
|
||||||
.background(Color.grayMain2c200)
|
|
||||||
.cornerRadius(40)
|
|
||||||
.onTapGesture {
|
|
||||||
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters3)
|
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
|
||||||
Text(callViewModel.letters4)
|
|
||||||
.default_text_style(styleSize: 30)
|
|
||||||
.frame(width: 60, height: 60)
|
|
||||||
}
|
|
||||||
.padding(10)
|
|
||||||
.background(Color.grayMain2c200)
|
|
||||||
.cornerRadius(40)
|
|
||||||
.onTapGesture {
|
|
||||||
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters4)
|
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(.bottom, 20)
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Text("Skip")
|
|
||||||
.underline()
|
|
||||||
.tint(Color.grayMain2c600)
|
|
||||||
.default_text_style_600(styleSize: 15)
|
|
||||||
.foregroundStyle(Color.grayMain2c500)
|
|
||||||
}
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.padding(.bottom, 30)
|
|
||||||
.onTapGesture {
|
|
||||||
callViewModel.skipZrtpAuthentication()
|
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
callViewModel.updateZrtpSas(authTokenClicked: "")
|
|
||||||
callViewModel.zrtpPopupDisplayed = false
|
|
||||||
}, label: {
|
|
||||||
Text("Letters don't match!")
|
|
||||||
.default_text_style_orange_600(styleSize: 20)
|
|
||||||
.frame(height: 35)
|
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.top, 15)
|
||||||
|
.padding(.bottom, 2)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
HStack {
|
||||||
|
Text("call_zrtp_sas_validation_skip")
|
||||||
|
.underline()
|
||||||
|
.tint(.white)
|
||||||
|
.default_text_style_white_600(styleSize: 16 / resizeView)
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.skipZrtpAuthentication()
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.top, 10 / resizeView)
|
||||||
|
.padding(.trailing, 15 / resizeView)
|
||||||
})
|
})
|
||||||
.padding(.horizontal, 20)
|
|
||||||
.padding(.vertical, 10)
|
VStack(alignment: .center) {
|
||||||
.cornerRadius(60)
|
VStack {
|
||||||
.overlay(
|
if idiom != .pad && (orientation == .landscapeLeft
|
||||||
RoundedRectangle(cornerRadius: 60)
|
|| orientation == .landscapeRight
|
||||||
.inset(by: 0.5)
|
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) {
|
||||||
.stroke(Color.orangeMain500, lineWidth: 1)
|
HStack {
|
||||||
)
|
Text("call_dialog_zrtp_validate_trust_message")
|
||||||
.padding(.bottom)
|
.default_text_style(styleSize: 16 / resizeView)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.bottom, 10 / resizeView)
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
Text("call_dialog_zrtp_validate_trust_local_code_label")
|
||||||
|
.default_text_style(styleSize: 16 / resizeView)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
|
||||||
|
Text(!callViewModel.upperCaseAuthTokenToRead.isEmpty ? callViewModel.upperCaseAuthTokenToRead : "ZZ")
|
||||||
|
.default_text_style_700(styleSize: 22 / resizeView)
|
||||||
|
.padding(.bottom, 20 / resizeView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text(callViewModel.cacheMismatch ? "call_dialog_zrtp_validate_trust_warning_message" : "call_dialog_zrtp_validate_trust_message")
|
||||||
|
.default_text_style(styleSize: 16 / resizeView)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.bottom, 10 / resizeView)
|
||||||
|
|
||||||
|
Text("call_dialog_zrtp_validate_trust_local_code_label")
|
||||||
|
.default_text_style(styleSize: 16 / resizeView)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
|
||||||
|
Text(!callViewModel.upperCaseAuthTokenToRead.isEmpty ? callViewModel.upperCaseAuthTokenToRead : "ZZ")
|
||||||
|
.default_text_style_800(styleSize: 22 / resizeView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
Text("call_dialog_zrtp_validate_trust_remote_code_label")
|
||||||
|
.default_text_style(styleSize: 16 / resizeView)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.top, 15 / resizeView)
|
||||||
|
.padding(.bottom, 10 / resizeView)
|
||||||
|
|
||||||
|
if idiom != .pad && (orientation == .landscapeLeft
|
||||||
|
|| orientation == .landscapeRight
|
||||||
|
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) {
|
||||||
|
HStack(spacing: 30) {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters1)
|
||||||
|
.default_text_style(styleSize: 24 / resizeView)
|
||||||
|
.frame(width: 45 / resizeView, height: 45 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters1)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters2)
|
||||||
|
.default_text_style(styleSize: 24 / resizeView)
|
||||||
|
.frame(width: 45 / resizeView, height: 45 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters2)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters3)
|
||||||
|
.default_text_style(styleSize: 24 / resizeView)
|
||||||
|
.frame(width: 45 / resizeView, height: 45 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters3)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters4)
|
||||||
|
.default_text_style(styleSize: 24 / resizeView)
|
||||||
|
.frame(width: 45 / resizeView, height: 45 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters4)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 40 / resizeView)
|
||||||
|
.padding(.bottom, 20 / resizeView)
|
||||||
|
} else {
|
||||||
|
HStack(spacing: 30) {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters1)
|
||||||
|
.default_text_style(styleSize: 34 / resizeView)
|
||||||
|
.frame(width: 60 / resizeView, height: 60 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters1)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters2)
|
||||||
|
.default_text_style(styleSize: 34 / resizeView)
|
||||||
|
.frame(width: 60 / resizeView, height: 60 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters2)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 40 / resizeView)
|
||||||
|
.padding(.bottom, 20 / resizeView)
|
||||||
|
|
||||||
|
HStack(spacing: 30) {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters3)
|
||||||
|
.default_text_style(styleSize: 34 / resizeView)
|
||||||
|
.frame(width: 60 / resizeView, height: 60 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters3)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Text(callViewModel.letters4)
|
||||||
|
.default_text_style(styleSize: 34 / resizeView)
|
||||||
|
.frame(width: 60 / resizeView, height: 60 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(10 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: .gray.opacity(0.4), radius: 4)
|
||||||
|
.onTapGesture {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: callViewModel.letters4)
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 40 / resizeView)
|
||||||
|
.padding(.bottom, 20 / resizeView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 10 / resizeView)
|
||||||
|
.padding(.bottom, 10 / resizeView)
|
||||||
|
.cornerRadius(20)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.inset(by: 0.5)
|
||||||
|
.stroke(Color.grayMain2c200, lineWidth: 1)
|
||||||
|
)
|
||||||
|
.padding(.bottom, 10 / resizeView)
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
callViewModel.updateZrtpSas(authTokenClicked: "")
|
||||||
|
callViewModel.zrtpPopupDisplayed = false
|
||||||
|
}, label: {
|
||||||
|
Text("call_dialog_zrtp_validate_trust_letters_do_not_match")
|
||||||
|
.foregroundStyle(Color.redDanger500)
|
||||||
|
.default_text_style_orange_600(styleSize: 20 / resizeView)
|
||||||
|
.frame(height: 35 / resizeView)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
})
|
||||||
|
.padding(.horizontal, 20 / resizeView)
|
||||||
|
.padding(.vertical, 10 / resizeView)
|
||||||
|
.cornerRadius(60)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 60)
|
||||||
|
.inset(by: 0.5)
|
||||||
|
.stroke(Color.redDanger500, lineWidth: 1)
|
||||||
|
)
|
||||||
|
.padding(.bottom)
|
||||||
|
}
|
||||||
|
.padding(.top, 20 / resizeView)
|
||||||
|
.padding(.horizontal, 20 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.cornerRadius(20)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 20)
|
.background(callViewModel.cacheMismatch ? Color.orangeWarning600 : Color.blueInfo500)
|
||||||
.padding(.vertical, 20)
|
|
||||||
.background(.white)
|
|
||||||
.cornerRadius(20)
|
.cornerRadius(20)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal, 2)
|
||||||
.frame(maxHeight: .infinity)
|
.frame(maxHeight: .infinity)
|
||||||
.shadow(color: Color.orangeMain500, radius: 0, x: 0, y: 2)
|
.shadow(color: callViewModel.cacheMismatch ? Color.orangeWarning600 : Color.blueInfo500, radius: 0, x: 0, y: 2)
|
||||||
.frame(maxWidth: sharedMainViewModel.maxWidth)
|
.frame(maxWidth: sharedMainViewModel.maxWidth * 1.2)
|
||||||
|
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
|
||||||
|
.onAppear {
|
||||||
|
callViewModel.remoteAuthenticationTokens()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var alertZRTP: some View {
|
||||||
|
GeometryReader { geometry in
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
ZStack(alignment: .top, content: {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
Image("shield-warning")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
.frame(width: 25, height: 25, alignment: .leading)
|
||||||
|
|
||||||
|
Text("call_dialog_zrtp_security_alert_title")
|
||||||
|
.default_text_style_white_700(styleSize: 16 / resizeView)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.top, 15)
|
||||||
|
.padding(.bottom, 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
VStack(alignment: .center) {
|
||||||
|
VStack {
|
||||||
|
Text("call_dialog_zrtp_security_alert_message")
|
||||||
|
.default_text_style(styleSize: 16 / resizeView)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.bottom, 10 / resizeView)
|
||||||
|
}
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
|
||||||
|
if telecomManager.isNotVerifiedCounter <= 1 {
|
||||||
|
Button(action: {
|
||||||
|
callViewModel.isNotVerified = false
|
||||||
|
}, label: {
|
||||||
|
Text("call_dialog_zrtp_security_alert_try_again")
|
||||||
|
.foregroundStyle(Color.redDanger500)
|
||||||
|
.default_text_style_orange_600(styleSize: 20 / resizeView)
|
||||||
|
.frame(height: 35 / resizeView)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
})
|
||||||
|
.padding(.horizontal, 20 / resizeView)
|
||||||
|
.padding(.vertical, 10 / resizeView)
|
||||||
|
.cornerRadius(60)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 60)
|
||||||
|
.inset(by: 0.5)
|
||||||
|
.stroke(Color.redDanger500, lineWidth: 1)
|
||||||
|
)
|
||||||
|
.padding(.bottom)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
callViewModel.terminateCall()
|
||||||
|
}, label: {
|
||||||
|
HStack {
|
||||||
|
Image("phone-disconnect")
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
|
||||||
|
Text("call_action_hang_up")
|
||||||
|
.default_text_style_white_600(styleSize: 20)
|
||||||
|
.frame(height: 35)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
})
|
||||||
|
.padding(.horizontal, 20 / resizeView)
|
||||||
|
.padding(.vertical, 10 / resizeView)
|
||||||
|
.background(Color.redDanger500)
|
||||||
|
.cornerRadius(60)
|
||||||
|
.padding(.bottom)
|
||||||
|
}
|
||||||
|
.padding(.top, 20 / resizeView)
|
||||||
|
.padding(.horizontal, 20 / resizeView)
|
||||||
|
.background(.white)
|
||||||
|
.cornerRadius(20)
|
||||||
|
}
|
||||||
|
.background(Color.redDanger500)
|
||||||
|
.cornerRadius(20)
|
||||||
|
.padding(.horizontal, 2)
|
||||||
|
.frame(maxHeight: .infinity)
|
||||||
|
.shadow(color: Color.redDanger500, radius: 0, x: 0, y: 2)
|
||||||
|
.frame(maxWidth: sharedMainViewModel.maxWidth * 1.2)
|
||||||
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
|
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
callViewModel.remoteAuthenticationTokens()
|
callViewModel.remoteAuthenticationTokens()
|
||||||
|
|
@ -153,5 +397,5 @@ struct ZRTPPopup: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
ZRTPPopup(callViewModel: CallViewModel())
|
ZRTPPopup(callViewModel: CallViewModel(), resizeView: 1)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,11 @@ class CallViewModel: ObservableObject {
|
||||||
@Published var upperCaseAuthTokenToRead = ""
|
@Published var upperCaseAuthTokenToRead = ""
|
||||||
@Published var upperCaseAuthTokenToListen = ""
|
@Published var upperCaseAuthTokenToListen = ""
|
||||||
@Published var isMediaEncrypted: Bool = false
|
@Published var isMediaEncrypted: Bool = false
|
||||||
@Published var isZrtpPq: Bool = false
|
@Published var isNotEncrypted: Bool = false
|
||||||
|
@Published var isZrtp: Bool = false
|
||||||
@Published var isRemoteDeviceTrusted: Bool = false
|
@Published var isRemoteDeviceTrusted: Bool = false
|
||||||
|
@Published var cacheMismatch: Bool = false
|
||||||
|
@Published var isNotVerified: Bool = false
|
||||||
@Published var selectedCall: Call?
|
@Published var selectedCall: Call?
|
||||||
@Published var isTransferInsteadCall: Bool = false
|
@Published var isTransferInsteadCall: Bool = false
|
||||||
@Published var isOneOneCall: Bool = false
|
@Published var isOneOneCall: Bool = false
|
||||||
|
|
@ -125,14 +128,14 @@ class CallViewModel: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
var isMediaEncryptedTmp = false
|
var isMediaEncryptedTmp = false
|
||||||
var isZrtpPqTmp = false
|
var isZrtpTmp = false
|
||||||
if self.currentCall != nil && self.currentCall!.currentParams != nil {
|
if self.currentCall != nil && self.currentCall!.currentParams != nil {
|
||||||
if self.currentCall!.currentParams!.mediaEncryption == .ZRTP ||
|
if self.currentCall!.currentParams!.mediaEncryption == .ZRTP ||
|
||||||
self.currentCall!.currentParams!.mediaEncryption == .SRTP ||
|
self.currentCall!.currentParams!.mediaEncryption == .SRTP ||
|
||||||
self.currentCall!.currentParams!.mediaEncryption == .DTLS {
|
self.currentCall!.currentParams!.mediaEncryption == .DTLS {
|
||||||
|
|
||||||
isMediaEncryptedTmp = true
|
isMediaEncryptedTmp = true
|
||||||
isZrtpPqTmp = self.currentCall!.currentParams!.mediaEncryption == .ZRTP
|
isZrtpTmp = self.currentCall!.currentParams!.mediaEncryption == .ZRTP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,6 +203,9 @@ class CallViewModel: ObservableObject {
|
||||||
self.zrtpPopupDisplayed = false
|
self.zrtpPopupDisplayed = false
|
||||||
self.upperCaseAuthTokenToRead = ""
|
self.upperCaseAuthTokenToRead = ""
|
||||||
self.upperCaseAuthTokenToListen = ""
|
self.upperCaseAuthTokenToListen = ""
|
||||||
|
self.isNotVerified = false
|
||||||
|
|
||||||
|
self.updateEncryption()
|
||||||
self.isConference = false
|
self.isConference = false
|
||||||
self.participantList = []
|
self.participantList = []
|
||||||
self.activeSpeakerParticipant = nil
|
self.activeSpeakerParticipant = nil
|
||||||
|
|
@ -209,7 +215,9 @@ class CallViewModel: ObservableObject {
|
||||||
self.videoDisplayed = videoDisplayedTmp
|
self.videoDisplayed = videoDisplayedTmp
|
||||||
self.isOneOneCall = isOneOneCallTmp
|
self.isOneOneCall = isOneOneCallTmp
|
||||||
self.isMediaEncrypted = isMediaEncryptedTmp
|
self.isMediaEncrypted = isMediaEncryptedTmp
|
||||||
self.isZrtpPq = isZrtpPqTmp
|
self.isNotEncrypted = false
|
||||||
|
self.isZrtp = isZrtpTmp
|
||||||
|
self.cacheMismatch = cacheMismatchFlag
|
||||||
|
|
||||||
self.getCallsList()
|
self.getCallsList()
|
||||||
|
|
||||||
|
|
@ -228,21 +236,35 @@ class CallViewModel: ObservableObject {
|
||||||
})
|
})
|
||||||
|
|
||||||
self.callSuscriptions.insert(self.currentCall!.publisher?.onStatsUpdated?.postOnCoreQueue {(cbVal: (call: Call, stats: CallStats)) in
|
self.callSuscriptions.insert(self.currentCall!.publisher?.onStatsUpdated?.postOnCoreQueue {(cbVal: (call: Call, stats: CallStats)) in
|
||||||
if self.currentCall != nil {
|
DispatchQueue.main.async {
|
||||||
DispatchQueue.main.async {
|
if self.currentCall != nil {
|
||||||
self.callStatsModel.update(call: self.currentCall!, stats: cbVal.stats)
|
self.callStatsModel.update(call: self.currentCall!, stats: cbVal.stats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
self.callSuscriptions.insert(
|
self.callSuscriptions.insert(
|
||||||
self.currentCall!.publisher?.onAuthenticationTokenVerified?.postOnCoreQueue {(call: Call, verified: Bool) in
|
self.currentCall!.publisher?.onAuthenticationTokenVerified?.postOnCoreQueue {(call: Call, verified: Bool) in
|
||||||
Log.warn("[CallViewModel][ZRTPPopup] Notified that authentication token is \(verified ? "verified" : "not verified!")")
|
Log.warn("[CallViewModel][ZRTPPopup] Notified that authentication token is \(verified ? "verified" : "not verified!")")
|
||||||
|
if verified {
|
||||||
self.updateEncryption()
|
self.updateEncryption()
|
||||||
if self.currentCall != nil {
|
if self.currentCall != nil {
|
||||||
self.callMediaEncryptionModel.update(call: self.currentCall!)
|
self.callMediaEncryptionModel.update(call: self.currentCall!)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.telecomManager.isNotVerifiedCounter == 0 {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.isNotVerified = true
|
||||||
|
self.telecomManager.isNotVerifiedCounter += 1
|
||||||
|
}
|
||||||
|
self.showZrtpSasDialogIfPossible()
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.isNotVerified = true
|
||||||
|
self.telecomManager.isNotVerifiedCounter += 1
|
||||||
|
self.zrtpPopupDisplayed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -641,6 +663,7 @@ class CallViewModel: ObservableObject {
|
||||||
telecomManager.callInProgress = true
|
telecomManager.callInProgress = true
|
||||||
telecomManager.callDisplayed = true
|
telecomManager.callDisplayed = true
|
||||||
telecomManager.callStarted = true
|
telecomManager.callStarted = true
|
||||||
|
telecomManager.isNotVerifiedCounter = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
coreContext.doOnCoreQueue { core in
|
coreContext.doOnCoreQueue { core in
|
||||||
|
|
@ -881,18 +904,20 @@ class CallViewModel: ObservableObject {
|
||||||
coreContext.doOnCoreQueue { core in
|
coreContext.doOnCoreQueue { core in
|
||||||
if core.currentCall != nil {
|
if core.currentCall != nil {
|
||||||
let tokens = core.currentCall!.remoteAuthenticationTokens
|
let tokens = core.currentCall!.remoteAuthenticationTokens
|
||||||
DispatchQueue.main.async {
|
if !tokens.isEmpty {
|
||||||
self.letters1 = tokens[0]
|
DispatchQueue.main.async {
|
||||||
self.letters2 = tokens[1]
|
self.letters1 = tokens[0]
|
||||||
self.letters3 = tokens[2]
|
self.letters2 = tokens[1]
|
||||||
self.letters4 = tokens[3]
|
self.letters3 = tokens[2]
|
||||||
|
self.letters4 = tokens[3]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateEncryption() {
|
private func updateEncryption() {
|
||||||
coreContext.doOnCoreQueue { core in
|
coreContext.doOnCoreQueue { _ in
|
||||||
if self.currentCall != nil && self.currentCall!.currentParams != nil {
|
if self.currentCall != nil && self.currentCall!.currentParams != nil {
|
||||||
switch self.currentCall!.currentParams!.mediaEncryption {
|
switch self.currentCall!.currentParams!.mediaEncryption {
|
||||||
case MediaEncryption.ZRTP:
|
case MediaEncryption.ZRTP:
|
||||||
|
|
@ -918,12 +943,14 @@ class CallViewModel: ObservableObject {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// When Post Quantum is available, ZRTP is Post Quantum
|
// When Post Quantum is available, ZRTP is Post Quantum
|
||||||
let isZrtpPqTmp = Core.getPostQuantumAvailable
|
let isZrtpPQTmp = Core.getPostQuantumAvailable
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.isRemoteDeviceTrusted = isRemoteDeviceTrustedTmp
|
self.isRemoteDeviceTrusted = isRemoteDeviceTrustedTmp
|
||||||
self.isMediaEncrypted = true
|
self.isMediaEncrypted = true
|
||||||
self.isZrtpPq = isZrtpPqTmp
|
self.isZrtp = true
|
||||||
|
self.cacheMismatch = cacheMismatchFlag
|
||||||
|
self.isNotEncrypted = false
|
||||||
|
|
||||||
if isDeviceTrusted {
|
if isDeviceTrusted {
|
||||||
ToastViewModel.shared.toastMessage = "Info_call_securised"
|
ToastViewModel.shared.toastMessage = "Info_call_securised"
|
||||||
|
|
@ -938,12 +965,18 @@ class CallViewModel: ObservableObject {
|
||||||
case MediaEncryption.SRTP, MediaEncryption.DTLS:
|
case MediaEncryption.SRTP, MediaEncryption.DTLS:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.isMediaEncrypted = true
|
self.isMediaEncrypted = true
|
||||||
self.isZrtpPq = false
|
self.isZrtp = false
|
||||||
|
self.isNotEncrypted = false
|
||||||
}
|
}
|
||||||
default:
|
case MediaEncryption.None:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.isMediaEncrypted = false
|
self.isMediaEncrypted = false
|
||||||
self.isZrtpPq = false
|
self.isZrtp = false
|
||||||
|
if self.currentCall!.state == .StreamsRunning {
|
||||||
|
self.isNotEncrypted = true
|
||||||
|
} else {
|
||||||
|
self.isNotEncrypted = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -971,26 +1004,28 @@ class CallViewModel: ObservableObject {
|
||||||
|
|
||||||
let mySubstringSuffix = upperCaseAuthToken.suffix(2)
|
let mySubstringSuffix = upperCaseAuthToken.suffix(2)
|
||||||
|
|
||||||
switch self.currentCall!.dir {
|
DispatchQueue.main.async {
|
||||||
case Call.Dir.Incoming:
|
switch self.currentCall!.dir {
|
||||||
self.upperCaseAuthTokenToRead = String(mySubstringPrefix)
|
case Call.Dir.Incoming:
|
||||||
self.upperCaseAuthTokenToListen = String(mySubstringSuffix)
|
self.upperCaseAuthTokenToRead = String(mySubstringPrefix)
|
||||||
default:
|
self.upperCaseAuthTokenToListen = String(mySubstringSuffix)
|
||||||
self.upperCaseAuthTokenToRead = String(mySubstringSuffix)
|
default:
|
||||||
self.upperCaseAuthTokenToListen = String(mySubstringPrefix)
|
self.upperCaseAuthTokenToRead = String(mySubstringSuffix)
|
||||||
|
self.upperCaseAuthTokenToListen = String(mySubstringPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.zrtpPopupDisplayed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.zrtpPopupDisplayed = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func transferClicked() {
|
func transferClicked() {
|
||||||
coreContext.doOnCoreQueue { core in
|
coreContext.doOnCoreQueue { core in
|
||||||
var callToTransferTo = core.calls.last { call in
|
let callToTransferTo = core.calls.last { call in
|
||||||
call.state == Call.State.Paused && call.callLog?.callId != self.currentCall?.callLog?.callId
|
call.state == Call.State.Paused && call.callLog?.callId != self.currentCall?.callLog?.callId
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callToTransferTo == nil) {
|
if callToTransferTo == nil {
|
||||||
Log.error(
|
Log.error(
|
||||||
"[CallViewModel] Couldn't find a call in Paused state to transfer current call to"
|
"[CallViewModel] Couldn't find a call in Paused state to transfer current call to"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ extension Account {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func == (lhs: Account, rhs: Account) -> Bool {
|
static func == (lhs: Account, rhs: Account) -> Bool {
|
||||||
return lhs.params?.identityAddress?.asString() == rhs.params?.identityAddress?.asString()
|
if lhs.params != nil && lhs.params?.identityAddress != nil && rhs.params != nil && rhs.params?.identityAddress != nil {
|
||||||
|
return lhs.params?.identityAddress?.asString() == rhs.params?.identityAddress?.asString()
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue