From 55aeeb50a679694d87854121e2b61112bb000073 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 24 Oct 2022 08:03:30 +0000 Subject: [PATCH 01/61] Translated using Weblate --- linphone-app/assets/languages/de.ts | 6 +++--- linphone-app/assets/languages/fr_FR.ts | 18 +++++++++--------- linphone-app/assets/languages/hu.ts | 6 +++--- linphone-app/assets/languages/it.ts | 8 ++++---- linphone-app/assets/languages/pt_BR.ts | 6 +++--- linphone-app/assets/languages/ru.ts | 10 +++++----- linphone-app/assets/languages/tr.ts | 8 ++++---- linphone-app/assets/languages/zh_CN.ts | 4 ++-- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/linphone-app/assets/languages/de.ts b/linphone-app/assets/languages/de.ts index 5c52e5721..6c354fb22 100644 --- a/linphone-app/assets/languages/de.ts +++ b/linphone-app/assets/languages/de.ts @@ -2629,7 +2629,7 @@ Klicken Sie hier: <a href="%1">%1</a> useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - DNS-Auflösung wird von Linphone via SAL gemacht. Die IP wird an den LDAP-Server übertragen. Dadurch kann bei der TLS-Verhandlung der Hostname nicht geprüft werden. Sie können die Prüfung deaktivieren um die Verbindung zu erzwingen. + DNS-Auflösung wird von %1 via SAL gemacht. Die IP wird an den LDAP-Server übertragen. Dadurch kann bei der TLS-Verhandlung der Hostname nicht geprüft werden. Sie können die Prüfung deaktivieren um die Verbindung zu erzwingen. verifyTLSLabel @@ -2718,7 +2718,7 @@ Klicken Sie hier: <a href="%1">%1</a> domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - Füge die Domain der SIP-Adresse hinzu (sip:username@domain).<br>Der Standardwert ist sip.linphone.org + Füge die Domain der SIP-Adresse hinzu (sip:username@domain). miscLabel @@ -2730,7 +2730,7 @@ Klicken Sie hier: <a href="%1">%1</a> debugTooltip - Bei LDAP-Anfragen ausführliche Logeinträge in die Linphone-Logdatei schreiben (hilfreich um TLS-Verbindungen zu untersuchen). + Bei LDAP-Anfragen ausführliche Logeinträge Logdatei schreiben (hilfreich um TLS-Verbindungen zu untersuchen). diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts index 3dcdb259a..2beb47381 100644 --- a/linphone-app/assets/languages/fr_FR.ts +++ b/linphone-app/assets/languages/fr_FR.ts @@ -173,7 +173,7 @@ usernameStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). usernameStatusInvalid @@ -189,7 +189,7 @@ passwordStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). passwordStatusMissingCharacters @@ -1236,7 +1236,7 @@ URL du serveur non configurée. ephemeralNotInConference! 'Ephemeral message is only supported in conference based chat room!' - Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! + Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! Warning about not being in conference based chat room. @@ -2020,7 +2020,7 @@ Cliquez ici : <a href="%1">%1</a> newConferenceScheduleTitle 'Would you like to schedule your meeting?' : Ask about setting the meeting as scheduled. - Voulez-vous programmer cette réunion ? + Voulez-vous programmer cette réunion ? newConferenceDate @@ -2600,7 +2600,7 @@ Cliquez ici : <a href="%1">%1</a> serverTooltip - Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ + Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ bindDNLabel @@ -2718,7 +2718,7 @@ Cliquez ici : <a href="%1">%1</a> domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - Ajouter le domaine à l'adresse SIP (sip:nomdutilisateur@domaine). La valeur par défaut est sip.linphone.org + Ajouter le domaine à l'adresse SIP (sip:nomdutilisateur@domaine). miscLabel @@ -2730,7 +2730,7 @@ Cliquez ici : <a href="%1">%1</a> debugTooltip - Obtenir des traces dans le fichier traces de Linphone lors des opérations (utile pour déboguer les connexions TLS). + Obtenir des traces dans le fichier traces lors des opérations (utile pour déboguer les connexions TLS). @@ -3546,7 +3546,7 @@ Cliquez ici : <a href="%1">%1</a> deleteTimeline 'Are you sure you want to delete and leave this timeline?' - Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? + Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? deleteTimelineTooltip @@ -3651,7 +3651,7 @@ Cliquez ici : <a href="%1">%1</a> warningFeatures 'Some features require a %1 account, such as group messaging or ephemeral messaging.' : Warning text about features. %1 is the application name - Certaines fonctionnalités avancées comme les messages de groupe ou les messages éphémères nécessitent un compte Linphone. + Certaines fonctionnalités avancées comme les messages de groupe ou les messages éphémères nécessitent un compte %1. warningThirdParty diff --git a/linphone-app/assets/languages/hu.ts b/linphone-app/assets/languages/hu.ts index d3a709610..3c48bc478 100644 --- a/linphone-app/assets/languages/hu.ts +++ b/linphone-app/assets/languages/hu.ts @@ -2616,7 +2616,7 @@ Kattintson ide: <a href="%1">%1</a> useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - A DNS feloldását Linphone végzi SAL használatával. Egy IP-címet továbbít az LDAP kiszolgálónak. Ezzel a TLS tárgyalás nem tudta ellenőrizni az állomásnévét. Deaktiválhatja az ellenőrzéseket, ha kényszeríteni szeretné a kapcsolatot. + A DNS feloldását %1 végzi SAL használatával. Egy IP-címet továbbít az LDAP kiszolgálónak. Ezzel a TLS tárgyalás nem tudta ellenőrizni az állomásnévét. Deaktiválhatja az ellenőrzéseket, ha kényszeríteni szeretné a kapcsolatot. verifyTLSLabel @@ -2705,7 +2705,7 @@ Kattintson ide: <a href="%1">%1</a> domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - Tartomány hozzáadása a SIP-címhez (sip:felhasználónév@tartomány).<br>Az alapértelmezett érték a sip.linphone.org + Tartomány hozzáadása a SIP-címhez (sip:felhasználónév@tartomány). miscLabel @@ -2717,7 +2717,7 @@ Kattintson ide: <a href="%1">%1</a> debugTooltip - Részletes naplófájlok beszerzése a Linphone naplófájljába tranzakciók során (hasznos a TLS-kapcsolatok hibakereséséhez). + Részletes naplófájlok beszerzése naplófájljába tranzakciók során (hasznos a TLS-kapcsolatok hibakereséséhez). diff --git a/linphone-app/assets/languages/it.ts b/linphone-app/assets/languages/it.ts index 194d4e30c..f5fb0bad0 100644 --- a/linphone-app/assets/languages/it.ts +++ b/linphone-app/assets/languages/it.ts @@ -1456,7 +1456,7 @@ URL del server non configurato. incallSnapshotTooltip 'Take Snapshot' : Tooltip for takking snapshot. - Esegui uno snapshot' + Esegui uno snapshot incallWaitMessage @@ -2060,7 +2060,7 @@ Clicca: <a href="%1">%1</a> newConferenceSendLinphoneInviteLabel 'Send invite via %1' : Label for checkbox for sending invitations with the application. %1 is the application name. - Invita tramite Linphone + Invita tramite %1 newConferenceSendEmailInviteLabel @@ -2629,7 +2629,7 @@ Clicca: <a href="%1">%1</a> useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - Linphone usa SAL per la risoluzione DNS. Passerà l'indirizzo IP a LDAP. Facendo cosi la negoziazione TLS non può controllare il nome dell'host. Si possono disattivare le verifiche se si vuole forzare la connessione. + %1 usa SAL per la risoluzione DNS. Passerà l'indirizzo IP a LDAP. Facendo cosi la negoziazione TLS non può controllare il nome dell'host. Si possono disattivare le verifiche se si vuole forzare la connessione. verifyTLSLabel @@ -2718,7 +2718,7 @@ Clicca: <a href="%1">%1</a> domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - Aggiunge il dominio all'indirizzo SIP (sip:nomeutente@dominio).<br>Il valore di default è sip.linphone.org + Aggiunge il dominio all'indirizzo SIP (sip:nomeutente@dominio). miscLabel diff --git a/linphone-app/assets/languages/pt_BR.ts b/linphone-app/assets/languages/pt_BR.ts index 180c4c7a5..6480d0a71 100644 --- a/linphone-app/assets/languages/pt_BR.ts +++ b/linphone-app/assets/languages/pt_BR.ts @@ -2629,7 +2629,7 @@ Clique aqui: <a href="%1">%1 </a> useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - A resolução DNS é feita pelo Linphone usando SAL. Ele vai passar um IP para o LDAP. Com isso, a negociação TLS não conseguiu verificar o nome do host. Você pode desativar as verificações se quiser forçar a conexão. + A resolução DNS é feita pelo %1 usando SAL. Ele vai passar um IP para o LDAP. Com isso, a negociação TLS não conseguiu verificar o nome do host. Você pode desativar as verificações se quiser forçar a conexão. verifyTLSLabel @@ -2718,7 +2718,7 @@ Clique aqui: <a href="%1">%1 </a> domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - Adicione o domínio ao endereço SIP (sip:username@domain). <br>O valor padrão é sip.linphone.org + Adicione o domínio ao endereço SIP (sip:username@domain). miscLabel @@ -2730,7 +2730,7 @@ Clique aqui: <a href="%1">%1 </a> debugTooltip - Obtenha logs detalhados no arquivo de log do Linphone ao fazer transações (útil para depurar conexões TLS). + Obtenha logs detalhados no arquivo de log ao fazer transações (útil para depurar conexões TLS). diff --git a/linphone-app/assets/languages/ru.ts b/linphone-app/assets/languages/ru.ts index dee0ec5e7..37bc2b37a 100644 --- a/linphone-app/assets/languages/ru.ts +++ b/linphone-app/assets/languages/ru.ts @@ -2072,7 +2072,7 @@ newConferenceSendLinphoneInviteLabel 'Send invite via %1' : Label for checkbox for sending invitations with the application. %1 is the application name. - Отправить приглашение через Linphone + Отправить приглашение через %1 newConferenceSendEmailInviteLabel @@ -2642,7 +2642,7 @@ useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - Разрешение DNS выполняется Linphone с использованием SAL. Он передаст IP в LDAP. При этом согласование TLS не может проверить имя хоста. Вы можете деактивировать проверки, если хотите принудительно установить соединение. + Разрешение DNS выполняется %1 с использованием SAL. Он передаст IP в LDAP. При этом согласование TLS не может проверить имя хоста. Вы можете деактивировать проверки, если хотите принудительно установить соединение. verifyTLSLabel @@ -2731,7 +2731,7 @@ domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - Добавьте домен к SIP-адресу (sip:username@domain).<br>Значение по умолчанию: sip.linphone.org + Добавьте домен к SIP-адресу (sip:username@domain). miscLabel @@ -2743,7 +2743,7 @@ debugTooltip - Получайте подробные журналы в файле журнала Linphone при выполнении транзакций (полезно для отладки соединений TLS). + Получайте подробные журналы в файле журнала при выполнении транзакций (полезно для отладки соединений TLS). @@ -3664,7 +3664,7 @@ warningFeatures 'Some features require a %1 account, such as group messaging or ephemeral messaging.' : Warning text about features. %1 is the application name - Для некоторых функций требуется аккаунт Linphone, например для группового обмена сообщениями или обмена недолговечными сообщениями. + Для некоторых функций требуется аккаунт %1, например для группового обмена сообщениями или обмена недолговечными сообщениями. warningThirdParty diff --git a/linphone-app/assets/languages/tr.ts b/linphone-app/assets/languages/tr.ts index 5e17d0170..51f897499 100644 --- a/linphone-app/assets/languages/tr.ts +++ b/linphone-app/assets/languages/tr.ts @@ -2616,7 +2616,7 @@ Buraya tıklayın: <a href="%1">%1</a> useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - DNS çözümleme SAL kullanılarak Linphone tarafından yapılır. LDAP'a bir IP gönderir. Bunu yaparak, TLS uzlaşısı ana makine adını denetleyemez. Bağlantıyı dayatmak isteniyorsa doğrulamaları devre dışı bırakmanız gerekebilir. + DNS çözümleme SAL kullanılarak %1 tarafından yapılır. LDAP'a bir IP gönderir. Bunu yaparak, TLS uzlaşısı ana makine adını denetleyemez. Bağlantıyı dayatmak isteniyorsa doğrulamaları devre dışı bırakmanız gerekebilir. verifyTLSLabel @@ -2705,7 +2705,7 @@ Buraya tıklayın: <a href="%1">%1</a> domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - SIP adresine etki alanı ekle (sip:kullanici@etkialanı).<br>Öntanımlı değer: sip.linphone.org + SIP adresine etki alanı ekle (sip:kullanici@etkialanı). miscLabel @@ -2717,7 +2717,7 @@ Buraya tıklayın: <a href="%1">%1</a> debugTooltip - İşlem yaparken Linphone günlük dosyasına ayrıntılı günlükle (TLS bağlantısı hataları ayıklanırken kullanışlıdır). + İşlem yaparken günlük dosyasına ayrıntılı günlükle (TLS bağlantısı hataları ayıklanırken kullanışlıdır). @@ -3638,7 +3638,7 @@ Buraya tıklayın: <a href="%1">%1</a> warningFeatures 'Some features require a %1 account, such as group messaging or ephemeral messaging.' : Warning text about features. %1 is the application name - Küme iletileri veya kısa ömürlü iletiler gibi bazı özellikler Linphone hesabı gerektirir. + Küme iletileri veya kısa ömürlü iletiler gibi bazı özellikler %1 hesabı gerektirir. warningThirdParty diff --git a/linphone-app/assets/languages/zh_CN.ts b/linphone-app/assets/languages/zh_CN.ts index 09ea53613..88d9978f9 100644 --- a/linphone-app/assets/languages/zh_CN.ts +++ b/linphone-app/assets/languages/zh_CN.ts @@ -2616,7 +2616,7 @@ useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - DNS 解析已由 Linphone 使用 SAL 完成。 它会将 IP 传递给 LDAP。 通过这样做,TLS 协商无法检查主机名。 如果想强制连接,您可以停用验证。 + DNS 解析已由 %1 使用 SAL 完成。 它会将 IP 传递给 LDAP。 通过这样做,TLS 协商无法检查主机名。 如果想强制连接,您可以停用验证。 verifyTLSLabel @@ -2705,7 +2705,7 @@ domainTooltip 'Add the domain to the sip address(username@domain).' Tooltip to explain that this field is used to complete a result with this domain. - 添加域名到SIP地址(sip:username@domain)。<br>默认值是sip.linphone.org + 添加域名到SIP地址(sip:username@domain)。 miscLabel From f06f4ad6d68f8b71444310c600dbce90d6e92978 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 24 Oct 2022 10:52:39 +0200 Subject: [PATCH 02/61] Reordering constants. --- linphone-app/src/utils/Constants.hpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/linphone-app/src/utils/Constants.hpp b/linphone-app/src/utils/Constants.hpp index 4d490992b..b70972b5d 100644 --- a/linphone-app/src/utils/Constants.hpp +++ b/linphone-app/src/utils/Constants.hpp @@ -36,21 +36,16 @@ public: //---------------------------------------------------------------------------------- - static constexpr char WindowIconPath[] = ":/assets/images/linphone_logo.svg"; static constexpr char DefaultLocale[] = "en"; - - static constexpr char ApplicationMinimalQtVersion[] = "5.10.0"; static constexpr char DefaultFont[] = "Noto Sans"; static constexpr size_t MaxLogsCollectionSize = 10485760*5; // 50MB. - #ifdef ENABLE_UPDATE_CHECK static constexpr int VersionUpdateCheckInterval = 86400000; // 24 hours in milliseconds. #endif // ifdef ENABLE_UPDATE_CHECK static constexpr char DefaultXmlrpcUri[] = "https://subscribe.linphone.org:444/wizard.php"; - static constexpr char LinphoneDomain[] = "sip.linphone.org"; static constexpr char DefaultContactParameters[] = "message-expires=604800"; static constexpr char DefaultContactParametersOnRemove[] = "message-expires=0"; static constexpr int DefaultExpires = 3600; @@ -69,9 +64,6 @@ public: static constexpr char LinphoneBZip2_dll[] = "https://www.linphone.org/releases/windows/tools/bzip2/bzip2.dll"; static constexpr char DefaultRlsUri[] = "sips:rls@sip.linphone.org"; static constexpr char DefaultLogsEmail[] = "linphone-desktop@belledonne-communications.com"; - static constexpr char DefaultConferenceURI[] = "sip:conference-factory@sip.linphone.org"; - static constexpr char DefaultVideoConferenceURI[] = "sip:videoconference-factory@sip.linphone.org"; - static constexpr char DefaultLimeServerURL[] = "https://lime.linphone.org/lime-server/lime-server.php"; static constexpr char DefaultFlexiAPIURL[] = "http://fs-test-sandbox.linphone.org/flexiapi/api/";// Need "/" at the end static constexpr char RemoteProvisioningURL[] = "http://fs-test-sandbox.linphone.org/flexiapi/provisioning"; @@ -94,7 +86,18 @@ public: static constexpr qint64 FileSizeLimit = 524288000;// In Bytes. static constexpr int ThumbnailImageFileWidth = 100; static constexpr int ThumbnailImageFileHeight = 100; + +//-------------------------------------------------------------------------------- +// LINPHONE +//-------------------------------------------------------------------------------- + static constexpr char LinphoneDomain[] = "sip.linphone.org"; // Use for checking if config are a Linphone + static constexpr char WindowIconPath[] = ":/assets/images/linphone_logo.svg"; + static constexpr char ApplicationMinimalQtVersion[] = "5.10.0"; + static constexpr char DefaultConferenceURI[] = "sip:conference-factory@sip.linphone.org"; // Default for a Linphone account + static constexpr char DefaultVideoConferenceURI[] = "sip:videoconference-factory@sip.linphone.org"; // Default for a Linphone account + static constexpr char DefaultLimeServerURL[] = "https://lime.linphone.org/lime-server/lime-server.php"; // Default for a Linphone account + static constexpr char PathAssistantConfig[] = "/" EXECUTABLE_NAME "/assistant/"; static constexpr char PathAvatars[] = "/avatars/"; static constexpr char PathCaptures[] = "/" EXECUTABLE_NAME "/captures/"; @@ -146,8 +149,6 @@ public: // 3 = CPIM on basic chat rooms // 4 = RTP bundle mode // 5 = Video Conference URI - - //-------------------------------------------------------------------------------- // CISCO //-------------------------------------------------------------------------------- From 35d90ceb78e3b0924ae81de201a242fb4c754544 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 24 Oct 2022 11:10:57 +0200 Subject: [PATCH 03/61] Fix LDAP crash and stuck assistant. --- .../src/components/settings/AccountSettingsModel.cpp | 6 +++++- linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/linphone-app/src/components/settings/AccountSettingsModel.cpp b/linphone-app/src/components/settings/AccountSettingsModel.cpp index e0b73b2a0..44d1a447e 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.cpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.cpp @@ -507,7 +507,11 @@ QString AccountSettingsModel::getPrimarySipAddress () const { } QString AccountSettingsModel::getDefaultAccountDomain() const{ - return Utils::coreStringToAppString(CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getDomain()); + auto account = CoreManager::getInstance()->getCore()->getDefaultAccount(); + if(account) + return Utils::coreStringToAppString(account->getParams()->getDomain()); + else + return ""; } // ----------------------------------------------------------------------------- diff --git a/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml b/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml index 759e3be1c..1352c6693 100644 --- a/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml +++ b/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml @@ -138,12 +138,14 @@ ColumnLayout { append({ $text: qsTr('useOtherSipAccount'), $view: 'UseOtherSipAccount', - $viewType: 'UseOtherSipAccount' + $viewType: 'UseOtherSipAccount', + $props: {} }) append( { $text: qsTr('fetchRemoteConfiguration'), $view: 'FetchRemoteConfiguration', - $viewType: 'FetchRemoteConfiguration' + $viewType: 'FetchRemoteConfiguration', + $props: {} }) } } From 1def97ee08164f0ae520e7e7a907aeaa1ce34532 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 24 Oct 2022 17:32:08 +0200 Subject: [PATCH 04/61] Use png2icns to generate apple icns from png. --- linphone-app/assets/icons/genicons.sh | 1 + linphone-app/assets/icons/genicons_1.0.sh | 1 + linphone-app/assets/icons/genicons_1.1.sh | 1 + 3 files changed, 3 insertions(+) diff --git a/linphone-app/assets/icons/genicons.sh b/linphone-app/assets/icons/genicons.sh index 858411db9..360f52d04 100755 --- a/linphone-app/assets/icons/genicons.sh +++ b/linphone-app/assets/icons/genicons.sh @@ -25,3 +25,4 @@ do inkscape -z -e hicolor/${i}x${i}/apps/icon.png -w $i -h $i ../images/linphone_logo.svg done convert hicolor/16x16/apps/icon.png hicolor/22x22/apps/icon.png hicolor/24x24/apps/icon.png hicolor/32x32/apps/icon.png hicolor/64x64/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png -colors 256 ../icon.ico +png2icns ../../cmake_builder/linphone_package/macos/linphone.icns hicolor/16x16/apps/icon.png hicolor/32x32/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png diff --git a/linphone-app/assets/icons/genicons_1.0.sh b/linphone-app/assets/icons/genicons_1.0.sh index 2994f1b34..2ff6a9242 100755 --- a/linphone-app/assets/icons/genicons_1.0.sh +++ b/linphone-app/assets/icons/genicons_1.0.sh @@ -25,3 +25,4 @@ do inkscape -z --export-type=png --export-file=hicolor/${i}x${i}/apps/icon.png -w $i -h $i ../images/linphone_logo.svg done convert hicolor/16x16/apps/icon.png hicolor/22x22/apps/icon.png hicolor/24x24/apps/icon.png hicolor/32x32/apps/icon.png hicolor/64x64/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png -colors 256 ../icon.ico +png2icns ../../cmake_builder/linphone_package/macos/linphone.icns hicolor/16x16/apps/icon.png hicolor/32x32/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png diff --git a/linphone-app/assets/icons/genicons_1.1.sh b/linphone-app/assets/icons/genicons_1.1.sh index 19982c5e0..91d2b2fdc 100755 --- a/linphone-app/assets/icons/genicons_1.1.sh +++ b/linphone-app/assets/icons/genicons_1.1.sh @@ -25,3 +25,4 @@ do inkscape -z --export-type=png --export-filename=hicolor/${i}x${i}/apps/icon.png -w $i -h $i ../images/linphone_logo.svg done convert hicolor/16x16/apps/icon.png hicolor/22x22/apps/icon.png hicolor/24x24/apps/icon.png hicolor/32x32/apps/icon.png hicolor/64x64/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png -colors 256 ../icon.ico +png2icns ../../cmake_builder/linphone_package/macos/linphone.icns hicolor/16x16/apps/icon.png hicolor/32x32/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png From 5a44f1f3bb6d2b74e8adbf07cb6637b123d01aa9 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 25 Oct 2022 11:24:38 +0200 Subject: [PATCH 05/61] Update conference detection on call. Display group chat icone when calling/receiving a conference. --- .../src/components/call/CallModel.cpp | 17 +- .../src/components/call/CallModel.hpp | 3 + .../src/components/settings/SettingsModel.cpp | 3 - .../ui/modules/Linphone/Contact/Avatar.qml | 168 ++++++++++-------- .../ui/modules/Linphone/Contact/Contact.qml | 31 +--- 5 files changed, 109 insertions(+), 113 deletions(-) diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index f75823394..666502aab 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -240,7 +240,22 @@ QSharedPointer CallModel::getConferenceSharedModel(){ bool CallModel::isConference () const{ // Check status to avoid crash when requesting a conference on an ended call. - return mCall && (Utils::coreStringToAppString(mCall->getRemoteAddress()->asString()).toLower().contains("conf-id") || (getStatus() != CallStatusEnded && mCall->getConference() != nullptr)); + bool isConf = false; + if(mCall){ + isConf = getStatus() != CallStatusEnded && (mCall->getConference() != nullptr || mConferenceInfoModel != nullptr); + if(!isConf){// Check special cases for Linphone. Having conf-id for a conference URI is not standard. + auto remoteAddress = mCall->getRemoteAddress(); + if( remoteAddress->getDomain() == Constants::LinphoneDomain){ + isConf = remoteAddress->hasUriParam("conf-id"); + } + } + } + + return isConf; +} + +bool CallModel::isOneToOne() const{ + return !isConference(); } // ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/call/CallModel.hpp b/linphone-app/src/components/call/CallModel.hpp index 2659a33a0..1a3792e7b 100644 --- a/linphone-app/src/components/call/CallModel.hpp +++ b/linphone-app/src/components/call/CallModel.hpp @@ -56,6 +56,8 @@ class CallModel : public QObject { Q_PROPERTY(bool isInConference READ isInConference NOTIFY isInConferenceChanged) Q_PROPERTY(bool isConference READ isConference CONSTANT) + Q_PROPERTY(bool isOneToOne READ isOneToOne CONSTANT) + Q_PROPERTY(int duration READ getDuration CONSTANT) // Constants but called with a timer in qml. Q_PROPERTY(float quality READ getQuality CONSTANT) @@ -137,6 +139,7 @@ public: return mIsInConference; } bool isConference () const; + bool isOneToOne() const; void setRecordFile (const std::shared_ptr &callParams); static void setRecordFile (const std::shared_ptr &callParams, const QString &to); diff --git a/linphone-app/src/components/settings/SettingsModel.cpp b/linphone-app/src/components/settings/SettingsModel.cpp index ce815e893..d1b4c0018 100644 --- a/linphone-app/src/components/settings/SettingsModel.cpp +++ b/linphone-app/src/components/settings/SettingsModel.cpp @@ -548,12 +548,9 @@ static inline QVariantMap createMapFromVideoDefinition (const shared_ptrgetCore()->videoSupported()); - map["name"] = QStringLiteral("Bad EGG"); map["width"] = QStringLiteral("?????"); map["height"] = QStringLiteral("?????"); - return map; } diff --git a/linphone-app/ui/modules/Linphone/Contact/Avatar.qml b/linphone-app/ui/modules/Linphone/Contact/Avatar.qml index ab2f99fcf..efe711055 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Avatar.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Avatar.qml @@ -10,84 +10,94 @@ import UtilsCpp 1.0 // ============================================================================= Item { - id: avatar - - // --------------------------------------------------------------------------- - - property alias presenceLevel: presenceLevelIcon.level - property color backgroundColor: AvatarStyle.backgroundColor - property color foregroundColor: 'transparent' - property string username - property var image - - property var _initialsRegex: /^\s*([^\s\.]+)(?:[\s\.]+([^\s\.]+))?/ - - property bool isPhoneNumber: UtilsCpp.isPhoneNumber(username) - - // --------------------------------------------------------------------------- - - function isLoaded () { - return roundedImage.status === Image.Ready - } - - function _computeInitials () { - var result = username.match(_initialsRegex) - if (!result) { - return username.length > 0 ? username.charAt(0).toUpperCase() : '' - } - - return result[1].charAt(0).toUpperCase() + ( - result[2] != null - ? result[2].charAt(0).toUpperCase() - : '' - ) - } - - // --------------------------------------------------------------------------- - - RoundedImage { - id: roundedImage - - anchors.fill: parent - backgroundColor: avatar.backgroundColor - foregroundColor: avatar.foregroundColor - source: avatar.image || '' - Icon{ + id: avatar + + // --------------------------------------------------------------------------- + + property alias presenceLevel: presenceLevelIcon.level + property color backgroundColor: AvatarStyle.backgroundColor + property color foregroundColor: 'transparent' + property string username + property var image + property bool isOneToOne: true + + property var _initialsRegex: /^\s*([^\s\.]+)(?:[\s\.]+([^\s\.]+))?/ + + property bool isPhoneNumber: UtilsCpp.isPhoneNumber(username) + + // --------------------------------------------------------------------------- + + function isLoaded () { + return roundedImage.status === Image.Ready + } + + function _computeInitials () { + var result = username.match(_initialsRegex) + if (!result) { + return username.length > 0 ? username.charAt(0).toUpperCase() : '' + } + + return result[1].charAt(0).toUpperCase() + ( + result[2] != null + ? result[2].charAt(0).toUpperCase() + : '' + ) + } + + // --------------------------------------------------------------------------- + + RoundedImage { + id: roundedImage + anchors.fill: parent - icon: AvatarStyle.personImage - visible: parent.source == '' && avatar.isPhoneNumber - overwriteColor: AvatarStyle.initials.color - } - } - - Text { - id: initialsText - anchors.centerIn: parent - color: AvatarStyle.initials.color - font.pointSize: { - var width - - if (parent.width > 0) { - width = parent.width / AvatarStyle.initials.ratio - } - - return AvatarStyle.initials.pointSize * (width || 1) - } - - text: _computeInitials() - visible: roundedImage.status !== Image.Ready && !avatar.isPhoneNumber - } - - PresenceLevel { - id: presenceLevelIcon - visible: level >= 0 - - anchors { - bottom: parent.bottom - right: parent.right - } - - height: parent.height / 4 - width: parent.width / 4 - } + backgroundColor: avatar.backgroundColor + foregroundColor: avatar.foregroundColor + source: avatar.image || '' + Icon{ + anchors.fill: parent + icon: AvatarStyle.personImage + visible: parent.source == '' && avatar.isPhoneNumber + overwriteColor: AvatarStyle.initials.color + } + } + + Text { + id: initialsText + anchors.centerIn: parent + color: AvatarStyle.initials.color + font.pointSize: { + var width + + if (parent.width > 0) { + width = parent.width / AvatarStyle.initials.ratio + } + + return AvatarStyle.initials.pointSize * (width || 1) + } + + text: _computeInitials() + visible: roundedImage.status !== Image.Ready && !avatar.isPhoneNumber && avatar.isOneToOne + } + + Icon { + anchors.fill: parent + icon: ContactStyle.groupChat.icon + overwriteColor: ContactStyle.groupChat.avatarColor + iconSize: avatar.width + //visible: entry!=undefined && entry.isOneToOne!=undefined && !entry.isOneToOne + visible: !avatar.isOneToOne + } + + PresenceLevel { + id: presenceLevelIcon + visible: level >= 0 + + anchors { + bottom: parent.bottom + right: parent.right + } + + height: parent.height / 4 + width: parent.width / 4 + } } diff --git a/linphone-app/ui/modules/Linphone/Contact/Contact.qml b/linphone-app/ui/modules/Linphone/Contact/Contact.qml index 81a7a73f2..ae90b0a1a 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Contact.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Contact.qml @@ -75,16 +75,7 @@ Rectangle { ? '' : item.username : item.username - visible:!groupChat.visible - Icon { - - anchors.fill: parent - - icon: ContactStyle.groupChat.icon - overwriteColor: ContactStyle.groupChat.avatarColor - iconSize: ContactStyle.contentHeight - visible: entry!=undefined && entry.isOneToOne!=undefined && !entry.isOneToOne - } + isOneToOne: entry==undefined || entry.isOneToOne==undefined || entry.isOneToOne Icon{ anchors.top:parent.top @@ -98,26 +89,6 @@ Rectangle { onClicked: item.avatarClicked(mouse) } } - Icon { - id: groupChat - - Layout.preferredHeight: ContactStyle.contentHeight - Layout.preferredWidth: ContactStyle.contentHeight - - icon: ContactStyle.groupChat.icon - overwriteColor: ContactStyle.groupChat.color - iconSize: ContactStyle.contentHeight - visible: false //entry!=undefined && entry.isOneToOne!=undefined && !entry.isOneToOne - - Icon{ - anchors.right: parent.right - anchors.top:parent.top - anchors.topMargin: -5 - visible: entry!=undefined && entry.haveEncryption != undefined && entry.haveEncryption - icon: entry?(entry.securityLevel === 2?'secure_level_1': entry.securityLevel===3? 'secure_level_2' : 'secure_level_unsafe'):'secure_level_unsafe' - iconSize:15 - } - } ContactDescription { id: description From 1197cf0643b9b1327a2380002d086a91141f3528 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 25 Oct 2022 16:24:47 +0200 Subject: [PATCH 06/61] Draft feature rejected. Revert "Make a cache for text to each chat rooms." This reverts commit 610097c5a52cfcdcf5c562a826ae1a7d826d5425. --- linphone-app/assets/images/draft_custom.svg | 49 ------------------- linphone-app/resources.qrc | 1 - .../components/chat-room/ChatRoomModel.cpp | 30 +----------- .../components/chat-room/ChatRoomModel.hpp | 13 +---- .../chat-room/ChatRoomProxyModel.cpp | 9 +++- .../chat-room/ChatRoomProxyModel.hpp | 5 ++ .../ui/modules/Linphone/Chat/Chat.qml | 5 +- .../Styles/Timeline/TimelineStyle.qml | 7 --- .../Linphone/Timeline/TimelineItem.qml | 19 ++----- 9 files changed, 20 insertions(+), 118 deletions(-) delete mode 100644 linphone-app/assets/images/draft_custom.svg diff --git a/linphone-app/assets/images/draft_custom.svg b/linphone-app/assets/images/draft_custom.svg deleted file mode 100644 index 069924dae..000000000 --- a/linphone-app/assets/images/draft_custom.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc index 2c0eb933b..d3d6ddeee 100644 --- a/linphone-app/resources.qrc +++ b/linphone-app/resources.qrc @@ -77,7 +77,6 @@ assets/images/declined_outgoing_call_custom.svg assets/images/delete_custom.svg assets/images/download_custom.svg - assets/images/draft_custom.svg assets/images/drop_down_custom.svg assets/images/edit_custom.svg assets/images/ended_call_custom.svg diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 28a7ace0b..947c67fa5 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -523,14 +523,6 @@ int ChatRoomModel::getAllUnreadCount(){ return mUnreadMessagesCount + mMissedCallsCount; } -QString ChatRoomModel::getCachedText()const{ - return mCachedText; -} - -bool ChatRoomModel::hasDraft() const{ - return mHasDraft; -} - //------------------------------------------------------------------------------------------------ void ChatRoomModel::setSubject(QString& subject){ @@ -605,23 +597,6 @@ void ChatRoomModel::enableMarkAsRead(const bool& enable){ } } -bool ChatRoomModel::setCachedText(const QString& text){ - if(mCachedText != text){ - mCachedText = text; - emit cachedTextChanged(); - setHasDraft(!mCachedText.isEmpty()); - return true; - }else - return false; -} - -void ChatRoomModel::setHasDraft(const bool& cached){ - if(mHasDraft != cached){ - mHasDraft = cached; - emit hasDraftChanged(); - } -} - void ChatRoomModel::setReply(ChatMessageModel * model){ if(model != mReplyModel.get()){ if( model && model->getChatMessage() ) @@ -724,7 +699,6 @@ void ChatRoomModel::sendMessage (const QString &message) { if(recorder->haveVocalRecorder()) recorder->clearVocalRecorder(); CoreManager::getInstance()->getChatModel()->clear(); - setCachedText(""); } } @@ -744,8 +718,8 @@ void ChatRoomModel::forwardMessage(ChatMessageModel * model){ } // ----------------------------------------------------------------------------- -void ChatRoomModel::compose (const QString& text) { - if( setCachedText(text) && mChatRoom)// only send a compose if text has changed +void ChatRoomModel::compose () { + if( mChatRoom) mChatRoom->compose(); } diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index bcac30bd0..ec8e82e26 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -92,9 +92,6 @@ public: Q_PROPERTY(bool entriesLoading READ isEntriesLoading WRITE setEntriesLoading NOTIFY entriesLoadingChanged) - Q_PROPERTY(QString cachedText READ getCachedText WRITE setCachedText NOTIFY cachedTextChanged) - Q_PROPERTY(bool hasDraft READ hasDraft WRITE setHasDraft NOTIFY hasDraftChanged) - static QSharedPointer create(std::shared_ptr chatRoom, const std::list>& callLogs = std::list>()); ChatRoomModel (std::shared_ptr chatRoom, const std::list>& callLogs = std::list>(), QObject * parent = nullptr); @@ -144,8 +141,6 @@ public: QList getComposers(); QString getParticipantAddress(); // return peerAddress if not secure else return the first participant SIP address. int getAllUnreadCount(); // Return unread messages and missed call. - QString getCachedText() const; - bool hasDraft() const; //---- Setters void setSubject(QString& subject); @@ -159,8 +154,6 @@ public: void setEphemeralEnabled(bool enabled); void setEphemeralLifetime(long lifetime); void enableMarkAsRead(const bool& enable); - bool setCachedText(const QString& text); // return true if cache changed - void setHasDraft(const bool& draft); void setReply(ChatMessageModel * model); ChatMessageModel * getReply()const; @@ -175,7 +168,7 @@ public: Q_INVOKABLE void updateParticipants(const QVariantList& participants); void sendMessage (const QString &message); Q_INVOKABLE void forwardMessage(ChatMessageModel * model); - void compose (const QString& text); + void compose (); Q_INVOKABLE void resetMessageCount (); void initEntries(); Q_INVOKABLE int loadMoreEntries(); // return new entries count @@ -280,8 +273,6 @@ signals: void markAsReadEnabledChanged(); void chatRoomDeleted();// Must be connected with DirectConnection mode void replyChanged(); - void cachedTextChanged(); - void hasDraftChanged(); // Chat Room listener callbacks @@ -314,8 +305,6 @@ private: QSharedPointer mReplyModel; QSharedPointer mUnreadMessageNotice; int mBindingCalls = 0; - QString mCachedText; // TODO : replace it by content to manage files/audio etc. - bool mHasDraft = false; QWeakPointer mSelf; }; diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp index cc644c9bd..ec1b15942 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp @@ -36,6 +36,8 @@ using namespace std; +QString ChatRoomProxyModel::gCachedText; + // ============================================================================= ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { @@ -99,7 +101,8 @@ CREATE_PARENT_MODEL_FUNCTION(deleteChatRoom) void ChatRoomProxyModel::compose (const QString& text) { if (mChatRoomModel) - mChatRoomModel->compose(text); + mChatRoomModel->compose(); + gCachedText = text; } int ChatRoomProxyModel::getEntryTypeFilter () { @@ -239,6 +242,10 @@ QVariant ChatRoomProxyModel::getAt(int row){ return sourceModel()->data(sourceIndex); } +QString ChatRoomProxyModel::getCachedText() const{ + return gCachedText; +} + void ChatRoomProxyModel::setIsCall(const bool& isCall){ if(mIsCall != isCall) { if(mChatRoomModel){ diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp index 03758ec28..39a5dc675 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp @@ -40,6 +40,7 @@ class ChatRoomProxyModel : public QSortFilterProxyModel { Q_PROPERTY(QString fullLocalAddress READ getFullLocalAddress WRITE setFullLocalAddress NOTIFY fullLocalAddressChanged) Q_PROPERTY(ChatRoomModel *chatRoomModel READ getChatRoomModel WRITE setChatRoomModel NOTIFY chatRoomModelChanged) Q_PROPERTY(QList composers READ getComposers NOTIFY isRemoteComposingChanged) + Q_PROPERTY(QString cachedText READ getCachedText) Q_PROPERTY(QString filterText MEMBER mFilterText WRITE setFilterText NOTIFY filterTextChanged) Q_PROPERTY(bool markAsReadEnabled READ markAsReadEnabled WRITE enableMarkAsRead NOTIFY markAsReadEnabledChanged)// Focus is at end of the list. Used to reset message count if not at end @@ -119,6 +120,9 @@ private: void setChatRoomModel (ChatRoomModel *chatRoomModel); QList getComposers () const; + + QString getCachedText() const; + void reload (ChatRoomModel *chatRoomModel); void handleIsActiveChanged (QWindow *window); @@ -134,6 +138,7 @@ private: QString mLocalAddress; QString mFullPeerAddress; QString mFullLocalAddress; + static QString gCachedText; bool mMarkAsReadEnabled; bool mIsCall = false; diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.qml b/linphone-app/ui/modules/Linphone/Chat/Chat.qml index 47c3b769b..63adcaf1e 100644 --- a/linphone-app/ui/modules/Linphone/Chat/Chat.qml +++ b/linphone-app/ui/modules/Linphone/Chat/Chat.qml @@ -445,10 +445,7 @@ Rectangle { } } onAudioRecordRequest: RecorderManager.resetVocalRecorder() - Component.onCompleted: { - text = proxyModel.chatRoomModel.cachedText - cursorPosition=text.length - } + Component.onCompleted: {text = proxyModel.cachedText; cursorPosition=text.length} Rectangle{ anchors.fill:parent color:'white' diff --git a/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml index 1a25f90d3..e21555316 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml @@ -17,13 +17,6 @@ QtObject { property color selectedTimerColor: ColorsList.addImageColor(sectionName+'_ephemeralTimer_c', icon, 'q').color } - property QtObject draft: QtObject{ - property string icon: 'draft_custom' - property int iconSize : 30 - property color color: ColorsList.addImageColor(sectionName+'_draft', icon, 'ad').color - property color selectedColor: ColorsList.addImageColor(sectionName+'_draft_c', icon, 'q').color - } - property QtObject contact: QtObject { property int height: 60 diff --git a/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml b/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml index 2b9db1ebc..3e8f34e42 100644 --- a/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml +++ b/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml @@ -73,27 +73,14 @@ Item { text: mainItem.timelineModel && UtilsCpp.toDateTimeString(mainItem.timelineModel.chatRoomModel.lastUpdateTime) isClickable: true } - - Icon{ - id: draft - icon: TimelineStyle.draft.icon - iconSize: visible ? TimelineStyle.draft.iconSize : 0 - overwriteColor: mainItem.timelineModel && mainItem.timelineModel.selected ? TimelineStyle.draft.selectedColor : TimelineStyle.draft.color - anchors.right:parent.right - anchors.bottom:parent.bottom - anchors.bottomMargin: 3 - anchors.rightMargin: 7 - visible: mainItem.timelineModel && mainItem.timelineModel.chatRoomModel.hasDraft - } - Icon{ icon: TimelineStyle.ephemeralTimer.icon iconSize: TimelineStyle.ephemeralTimer.iconSize overwriteColor: mainItem.timelineModel && mainItem.timelineModel.selected ? TimelineStyle.ephemeralTimer.selectedTimerColor : TimelineStyle.ephemeralTimer.timerColor - anchors.right:draft.left + anchors.right:parent.right anchors.bottom:parent.bottom - anchors.bottomMargin: 3 - anchors.rightMargin: draft.visible ? 0 : 7 + anchors.bottomMargin: 7 + anchors.rightMargin: 7 visible: mainItem.timelineModel && mainItem.timelineModel.chatRoomModel.ephemeralEnabled } MouseArea { From cb2cc3cef9b663df48aea74d649c56b4e09d6969 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 25 Oct 2022 17:15:58 +0200 Subject: [PATCH 07/61] Update SDK --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index a286c00b6..af1b28595 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit a286c00b618e218fde8314498bb49101c8fd9214 +Subproject commit af1b28595eb3ca9406c24ed3683e6e524eeaddbe From 39f72680eae5c7ff8f437eca24bdfb38fb4c43c1 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 27 Oct 2022 13:55:07 +0200 Subject: [PATCH 08/61] Fix hidden timelines. Do timeline deletion on SDK callabacks to avoid using deleted objects. From secure chats rooms, forward messages on the secure chat rooms if selected from contacts. Update SDK. --- .../src/components/call/CallModel.cpp | 4 +++- .../src/components/call/CallModel.hpp | 4 ++-- .../src/components/calls/CallsListModel.cpp | 2 +- .../components/chat-room/ChatRoomModel.cpp | 18 +++++++++------ .../components/chat-room/ChatRoomModel.hpp | 4 ++-- .../chat-room/ChatRoomProxyModel.cpp | 2 +- .../src/components/settings/SettingsModel.cpp | 1 - .../sip-addresses/SipAddressesModel.cpp | 6 +++-- .../components/timeline/TimelineListModel.cpp | 22 +++++++++---------- .../ui/modules/Linphone/Chat/Chat.qml | 7 +++--- linphone-sdk | 2 +- 11 files changed, 39 insertions(+), 33 deletions(-) diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index 666502aab..093d3158d 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -242,7 +242,9 @@ bool CallModel::isConference () const{ // Check status to avoid crash when requesting a conference on an ended call. bool isConf = false; if(mCall){ - isConf = getStatus() != CallStatusEnded && (mCall->getConference() != nullptr || mConferenceInfoModel != nullptr); + // Do not call getConference on Ended status. + isConf = (getStatus() != CallStatusEnded && mCall->getConference() != nullptr) || mConferenceInfoModel != nullptr; + if(!isConf){// Check special cases for Linphone. Having conf-id for a conference URI is not standard. auto remoteAddress = mCall->getRemoteAddress(); if( remoteAddress->getDomain() == Constants::LinphoneDomain){ diff --git a/linphone-app/src/components/call/CallModel.hpp b/linphone-app/src/components/call/CallModel.hpp index 1a3792e7b..7138a000b 100644 --- a/linphone-app/src/components/call/CallModel.hpp +++ b/linphone-app/src/components/call/CallModel.hpp @@ -55,8 +55,8 @@ class CallModel : public QObject { Q_PROPERTY(bool isOutgoing READ isOutgoing CONSTANT) Q_PROPERTY(bool isInConference READ isInConference NOTIFY isInConferenceChanged) - Q_PROPERTY(bool isConference READ isConference CONSTANT) - Q_PROPERTY(bool isOneToOne READ isOneToOne CONSTANT) + Q_PROPERTY(bool isConference READ isConference NOTIFY conferenceInfoModelChanged) + Q_PROPERTY(bool isOneToOne READ isOneToOne NOTIFY conferenceInfoModelChanged) Q_PROPERTY(int duration READ getDuration CONSTANT) // Constants but called with a timer in qml. diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp index e2c50ca14..72c53acc5 100644 --- a/linphone-app/src/components/calls/CallsListModel.cpp +++ b/linphone-app/src/components/calls/CallsListModel.cpp @@ -343,7 +343,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se initializer->setAdminsData(admins); ChatRoomInitializer::start(initializer); } - timeline = timelineList->getTimeline(chatRoom, ChatRoomModel::isTerminated(chatRoom)); + timeline = timelineList->getTimeline(chatRoom, true); }else{ if(admins.size() > 0){ ChatRoomInitializer::create(chatRoom)->setAdmins(admins); diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 947c67fa5..56249f197 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -107,7 +107,7 @@ void ChatRoomModel::connectTo(ChatRoomListener * listener){ } // ----------------------------------------------------------------------------- -QSharedPointer ChatRoomModel::create(std::shared_ptr chatRoom, const std::list>& callLogs){ +QSharedPointer ChatRoomModel::create(const std::shared_ptr& chatRoom, const std::list>& callLogs){ QSharedPointer model = QSharedPointer::create(chatRoom, callLogs); if(model){ model->mSelf = model; @@ -117,7 +117,7 @@ QSharedPointer ChatRoomModel::create(std::shared_ptr chatRoom, const std::list>& callLogs, QObject * parent) : ProxyListModel(parent){ +ChatRoomModel::ChatRoomModel (const std::shared_ptr& chatRoom, const std::list>& callLogs, QObject * parent) : ProxyListModel(parent){ App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE CoreManager *coreManager = CoreManager::getInstance(); mCoreHandlers = coreManager->getHandlers(); @@ -311,11 +311,11 @@ QString ChatRoomModel::getLocalAddress () const { } QString ChatRoomModel::getFullPeerAddress () const { - return mChatRoom ? Utils::coreStringToAppString(mChatRoom->getPeerAddress()->asString()) : ""; + return mChatRoom && mChatRoom->getPeerAddress() ? Utils::coreStringToAppString(mChatRoom->getPeerAddress()->asString()) : ""; } QString ChatRoomModel::getFullLocalAddress () const { - return mChatRoom ? Utils::coreStringToAppString(mChatRoom->getLocalAddress()->asString()) : ""; + return mChatRoom && mChatRoom->getLocalAddress()? Utils::coreStringToAppString(mChatRoom->getLocalAddress()->asString()) : ""; } QString ChatRoomModel::getConferenceAddress () const { @@ -620,15 +620,14 @@ void ChatRoomModel::markAsToDelete(){ void ChatRoomModel::deleteChatRoom(){ qInfo() << "Deleting ChatRoom : " << getSubject() << ", address=" << getFullPeerAddress(); if(mChatRoom){ - mChatRoom->removeListener(mChatRoomListener); CoreManager::getInstance()->getCore()->deleteChatRoom(mChatRoom); } - emit chatRoomDeleted(); } void ChatRoomModel::leaveChatRoom (){ if(mChatRoom){ - mChatRoom->leave(); + if(!isReadOnly()) + mChatRoom->leave(); if( mChatRoom->getHistorySize() == 0 && mChatRoom->getHistoryEventsSize() == 0) deleteChatRoom(); } @@ -1311,6 +1310,11 @@ void ChatRoomModel::onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState){ updateLastUpdateTime(); emit stateChanged(getState()); + if(newState == linphone::ChatRoom::State::Deleted){ + mChatRoom->removeListener(mChatRoomListener); + mChatRoom = nullptr; + emit chatRoomDeleted(); + } } void ChatRoomModel::onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index ec8e82e26..9ec963137 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -93,8 +93,8 @@ public: Q_PROPERTY(bool entriesLoading READ isEntriesLoading WRITE setEntriesLoading NOTIFY entriesLoadingChanged) - static QSharedPointer create(std::shared_ptr chatRoom, const std::list>& callLogs = std::list>()); - ChatRoomModel (std::shared_ptr chatRoom, const std::list>& callLogs = std::list>(), QObject * parent = nullptr); + static QSharedPointer create(const std::shared_ptr& chatRoom, const std::list>& callLogs = std::list>()); + ChatRoomModel (const std::shared_ptr& chatRoom, const std::list>& callLogs = std::list>(), QObject * parent = nullptr); ~ChatRoomModel (); diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp index ec1b15942..50526b763 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp @@ -335,7 +335,7 @@ void ChatRoomProxyModel::setChatRoomModel (ChatRoomModel *chatRoomModel){ }else{ if(mIsCall && mChatRoomModel) mChatRoomModel->removeBindingCall(); - mChatRoomModel = nullptr; + mChatRoomModel = nullptr; } } // ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/settings/SettingsModel.cpp b/linphone-app/src/components/settings/SettingsModel.cpp index d1b4c0018..cbf7d438a 100644 --- a/linphone-app/src/components/settings/SettingsModel.cpp +++ b/linphone-app/src/components/settings/SettingsModel.cpp @@ -69,7 +69,6 @@ SettingsModel::SettingsModel (QObject *parent) : QObject(parent) { connect(coreManager->getAccountSettingsModel(), &AccountSettingsModel::accountSettingsUpdated, this, &SettingsModel::videoConferenceEnabledChanged); connect(coreManager->getAccountSettingsModel(), &AccountSettingsModel::accountSettingsUpdated, this, &SettingsModel::secureChatEnabledChanged); - configureRlsUri(); } diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp index a76cf3d1b..b4b17cc7e 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp @@ -455,8 +455,10 @@ void SipAddressesModel::handleMessageCountReset (ChatRoomModel *chatRoomModel) { } void SipAddressesModel::handleMessageSent (const shared_ptr &message) { - const QString peerAddress(Utils::coreStringToAppString(message->getChatRoom()->getPeerAddress()->asStringUriOnly())); - addOrUpdateSipAddress(peerAddress, message); + if(message->getChatRoom() && message->getChatRoom()->getPeerAddress()){ + const QString peerAddress(Utils::coreStringToAppString(message->getChatRoom()->getPeerAddress()->asStringUriOnly())); + addOrUpdateSipAddress(peerAddress, message); + } } void SipAddressesModel::handleIsComposingChanged (const shared_ptr &chatRoom) { diff --git a/linphone-app/src/components/timeline/TimelineListModel.cpp b/linphone-app/src/components/timeline/TimelineListModel.cpp index c9a4f521d..68a26b0b0 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.cpp +++ b/linphone-app/src/components/timeline/TimelineListModel.cpp @@ -71,7 +71,6 @@ TimelineListModel::TimelineListModel(const TimelineListModel* model){ auto newItem = qobject_cast(item)->clone(); connect(newItem.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); connect(newItem.get(), &TimelineModel::chatRoomDeleted, this, &TimelineListModel::onChatRoomDeleted); - connect(newItem->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); mList << newItem; } } @@ -141,7 +140,6 @@ QSharedPointer TimelineListModel::getTimeline(std::shared_ptr model = TimelineModel::create(this, chatRoom); if(model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); - connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); add(model); return model; } @@ -189,7 +187,6 @@ QSharedPointer TimelineListModel::getChatRoomModel(std::shared_pt QSharedPointer model = TimelineModel::create(this, chatRoom); if(model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); - connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); add(model); return model->mChatRoomModel; } @@ -249,7 +246,7 @@ void TimelineListModel::updateTimelines () { allChatRooms.remove_if([](std::shared_ptr chatRoom){ if( ChatRoomModel::isTerminated(chatRoom) && chatRoom->getUnreadMessagesCount() > 0) chatRoom->markAsRead(); - return !chatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic) && chatRoom->getConferenceAddress() && chatRoom->getHistoryEventsSize() == 0; + return chatRoom->getState() == linphone::ChatRoom::State::Deleted || (!chatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic) && chatRoom->getConferenceAddress() && chatRoom->getHistoryEventsSize() == 0); }); //Remove no more chat rooms @@ -294,7 +291,6 @@ void TimelineListModel::updateTimelines () { QSharedPointer model = TimelineModel::create(this, dbChatRoom, callLogs); if( model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); - connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); add(model); } } @@ -306,12 +302,10 @@ void TimelineListModel::add (QSharedPointer timeline){ auto chatRoomModel = timeline->getChatRoomModel(); auto chatRoom = chatRoomModel->getChatRoom(); connect(timeline.get(), &TimelineModel::chatRoomDeleted, this, &TimelineListModel::onChatRoomDeleted); - if( !chatRoomModel->haveConferenceAddress() || chatRoom->getHistoryEventsSize() != 0) { - connect(chatRoomModel, &ChatRoomModel::lastUpdateTimeChanged, this, &TimelineListModel::updated); - ProxyListModel::add(timeline); - emit layoutChanged(); - emit countChanged(); - } + connect(chatRoomModel, &ChatRoomModel::lastUpdateTimeChanged, this, &TimelineListModel::updated); + ProxyListModel::add(timeline); + emit layoutChanged(); + emit countChanged(); } void TimelineListModel::removeChatRoomModel(QSharedPointer model){ @@ -356,7 +350,6 @@ void TimelineListModel::onChatRoomStateChanged(const std::shared_ptr model = TimelineModel::create(this, chatRoom); if(model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); - connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); add(model); } }else if(state == linphone::ChatRoom::State::Deleted || state == linphone::ChatRoom::State::Terminated){ @@ -368,6 +361,11 @@ void TimelineListModel::onChatRoomStateChanged(const std::shared_ptr Date: Thu, 27 Oct 2022 14:27:55 +0200 Subject: [PATCH 09/61] Display snapshots button for 1-1, hide it while in conference. --- linphone-app/ui/views/App/Calls/Incall.qml | 2 +- linphone-app/ui/views/App/Calls/IncallFullscreen.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index 8b6d05c66..962fd6337 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -269,7 +269,7 @@ Rectangle { isCustom: true backgroundRadius: width/2 colorSet: IncallStyle.buttons.screenshot - visible: SettingsModel.incallScreenshotEnabled && mainItem.isReady && mainItem.callModel && mainItem.callModel.snapshotEnabled + visible: SettingsModel.incallScreenshotEnabled && mainItem.isReady && mainItem.callModel && (!mainItem.callModel.isConference || mainItem.callModel.snapshotEnabled) onClicked: mainItem.callModel.takeSnapshot() //: 'Take Snapshot' : Tooltip for takking snapshot. tooltipText: qsTr('incallSnapshotTooltip') diff --git a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml index be64e5069..20d9e4381 100644 --- a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml +++ b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml @@ -236,7 +236,7 @@ Window { isCustom: true backgroundRadius: width/2 colorSet: IncallStyle.buttons.screenshot - visible: SettingsModel.incallScreenshotEnabled && conference.callModel && conference.callModel.snapshotEnabled + visible: SettingsModel.incallScreenshotEnabled && conference.callModel && (!conference.callModel.isConference || mainItem.callModel.snapshotEnabled) onClicked: conference.callModel && conference.callModel.takeSnapshot() //: 'Take Snapshot' : Tooltip for takking snapshot. tooltipText: qsTr('incallSnapshotTooltip') From c420b897a8fd7be83115be8d513eb4e2a1fbe283 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 27 Oct 2022 14:02:47 +0000 Subject: [PATCH 10/61] Translated using Weblate Currently translated at 99.9% (1001 of 1002 strings) (French) Translation: Linphone Desktop/Master Translate-URL: https://weblate.linphone.org/projects/linphone-desktop/master/fr/ (cherry picked from commit 6e8614572daa1d3b1de6d231e4e1a7faf2f88e34) --- linphone-app/assets/languages/fr_FR.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts index 2beb47381..8268ea906 100644 --- a/linphone-app/assets/languages/fr_FR.ts +++ b/linphone-app/assets/languages/fr_FR.ts @@ -2060,7 +2060,7 @@ Cliquez ici : <a href="%1">%1</a> newConferenceSendLinphoneInviteLabel 'Send invite via %1' : Label for checkbox for sending invitations with the application. %1 is the application name. - Envoyer les invitations avec Linphone + Envoyer les invitations avec %1 newConferenceSendEmailInviteLabel @@ -2629,7 +2629,7 @@ Cliquez ici : <a href="%1">%1</a> useSalTooltip 'The dns resolution is done by %1 using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname. You may deactivate the verifications if wanted to force the connection.' - La résolution DNS est effectuée par Linphone en utilisant SAL. Il fournira une IP à LDAP. Ce faisant, la négociation TLS ne pourra pas vérifier le nom d'hôte. Vous devrez donc désactiver les vérifications si vous voulez forcer la connexion. + La résolution DNS est effectuée par %1 en utilisant SAL. Il fournira une IP à LDAP. Ce faisant, la négociation TLS ne pourra pas vérifier le nom d'hôte. Vous devrez donc désactiver les vérifications si vous voulez forcer la connexion. verifyTLSLabel From 92a666a487ad7d94b0ec6cbb8a36dfd0c85ec4f3 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 27 Oct 2022 16:43:31 +0200 Subject: [PATCH 11/61] Set log collection to default if no account. --- linphone-app/src/components/core/CoreManager.cpp | 2 ++ linphone-app/src/utils/Constants.cpp | 1 + linphone-app/src/utils/Constants.hpp | 1 + 3 files changed, 4 insertions(+) diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index 01aca27c0..07ba4f78f 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -285,6 +285,8 @@ void CoreManager::createLinphoneCore (const QString &configPath) { mCore->enableRecordAware(true); if(mCore->getAccountCreatorUrl() == "") mCore->setAccountCreatorUrl(Constants::DefaultFlexiAPIURL); + if( mCore->getAccountList().size() == 0) + mCore->setLogCollectionUploadServerUrl(Constants::DefaultUploadLogsServer); } void CoreManager::updateUserAgent(){ diff --git a/linphone-app/src/utils/Constants.cpp b/linphone-app/src/utils/Constants.cpp index 8e4483ab2..1d6191af5 100644 --- a/linphone-app/src/utils/Constants.cpp +++ b/linphone-app/src/utils/Constants.cpp @@ -65,6 +65,7 @@ constexpr int Constants::ThumbnailImageFileHeight; constexpr qint64 Constants::FileSizeLimit; constexpr char Constants::DefaultXmlrpcUri[]; +constexpr char Constants::DefaultUploadLogsServer[]; constexpr char Constants::DefaultConferenceURI[]; constexpr char Constants::DefaultVideoConferenceURI[]; constexpr char Constants::DefaultLimeServerURL[]; diff --git a/linphone-app/src/utils/Constants.hpp b/linphone-app/src/utils/Constants.hpp index b70972b5d..2140a8a52 100644 --- a/linphone-app/src/utils/Constants.hpp +++ b/linphone-app/src/utils/Constants.hpp @@ -46,6 +46,7 @@ public: #endif // ifdef ENABLE_UPDATE_CHECK static constexpr char DefaultXmlrpcUri[] = "https://subscribe.linphone.org:444/wizard.php"; + static constexpr char DefaultUploadLogsServer[] = "https://www.linphone.org:444/lft.php"; static constexpr char DefaultContactParameters[] = "message-expires=604800"; static constexpr char DefaultContactParametersOnRemove[] = "message-expires=0"; static constexpr int DefaultExpires = 3600; From 29122171cf867466963c0597235569380e67b68d Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 27 Oct 2022 17:04:28 +0200 Subject: [PATCH 12/61] Hide security choices in new Chat room if no choice can be done (like if security is mandatory) --- .../ui/views/App/Main/Dialogs/NewChatRoom.qml | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/linphone-app/ui/views/App/Main/Dialogs/NewChatRoom.qml b/linphone-app/ui/views/App/Main/Dialogs/NewChatRoom.qml index 9e339de9c..c3c0c44fe 100644 --- a/linphone-app/ui/views/App/Main/Dialogs/NewChatRoom.qml +++ b/linphone-app/ui/views/App/Main/Dialogs/NewChatRoom.qml @@ -90,7 +90,7 @@ DialogPlus { Layout.fillWidth: true Layout.topMargin:15 spacing:4 - visible: SettingsModel.secureChatEnabled + visible: SettingsModel.secureChatEnabled && SettingsModel.standardChatEnabled Text { Layout.fillWidth: true //: 'Would you like to encrypt your chat?' : Ask about setting the chat room as secured. @@ -157,13 +157,24 @@ DialogPlus { ColumnLayout { Layout.fillWidth: true spacing:10 - Text{ - textFormat: Text.RichText - //: 'Subject' : Label of a text field about the subject of the chat room - text :qsTr('subjectLabel') +'*' - color: NewChatRoomStyle.subjectTitleColor - font.pointSize: Units.dp * 11 - font.weight: Font.DemiBold + RowLayout{ + Icon{ + id:defaultSecure + Layout.alignment: Qt.AlignCenter + Layout.preferredHeight: visible? 20 : 0 + Layout.preferredWidth: visible? 20 : 0 + icon: 'secure_on' + iconSize:20 + visible: SettingsModel.secureChatEnabled && !SettingsModel.standardChatEnabled + } + Text{ + textFormat: Text.RichText + //: 'Subject' : Label of a text field about the subject of the chat room + text :qsTr('subjectLabel') +'*' + color: NewChatRoomStyle.subjectTitleColor + font.pointSize: Units.dp * 11 + font.weight: Font.DemiBold + } } TextField { id:subject From 04f3997fd9dd873a1e0232403614ea3c4a846694 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 2 Nov 2022 10:38:43 +0100 Subject: [PATCH 13/61] Update Active Speaker API (fix synchronizations) --- .../conference/ConferenceListener.cpp | 5 +++ .../conference/ConferenceListener.hpp | 3 ++ .../components/conference/ConferenceModel.cpp | 4 +++ .../components/conference/ConferenceModel.hpp | 3 +- .../conferenceInfo/ConferenceInfoModel.hpp | 1 - .../ParticipantDeviceListModel.cpp | 33 ++++++++--------- .../ParticipantDeviceListModel.hpp | 7 ++-- .../ParticipantDeviceProxyModel.cpp | 23 ++++++------ .../ParticipantDeviceProxyModel.hpp | 9 +++-- linphone-app/src/utils/LinphoneEnums.hpp | 3 +- .../ui/modules/Linphone/Contact/Contact.qml | 4 ++- .../views/App/Calls/IncallActiveSpeaker.qml | 35 +++++-------------- linphone-sdk | 2 +- 13 files changed, 66 insertions(+), 66 deletions(-) diff --git a/linphone-app/src/components/conference/ConferenceListener.cpp b/linphone-app/src/components/conference/ConferenceListener.cpp index 32a5a55f1..19f65c159 100644 --- a/linphone-app/src/components/conference/ConferenceListener.cpp +++ b/linphone-app/src/components/conference/ConferenceListener.cpp @@ -41,6 +41,11 @@ ConferenceListener::~ConferenceListener(){ //----------------------------------------------------------------------------------------------------------------------- // LINPHONE LISTENERS //----------------------------------------------------------------------------------------------------------------------- +void ConferenceListener::onActiveSpeakerParticipantDevice(const std::shared_ptr & conference, const std::shared_ptr & participantDevice) { + qDebug() << "onActiveSpeakerParticipantDevice: " << participantDevice->getAddress()->asString().c_str(); + emit activeSpeakerParticipantDevice(participantDevice); +} + void ConferenceListener::onParticipantAdded(const std::shared_ptr & conference, const std::shared_ptr & participant){ qDebug() << "onParticipantAdded: " << participant->getAddress()->asString().c_str(); emit participantAdded(participant); diff --git a/linphone-app/src/components/conference/ConferenceListener.hpp b/linphone-app/src/components/conference/ConferenceListener.hpp index 7ad651fb3..8b80dbd47 100644 --- a/linphone-app/src/components/conference/ConferenceListener.hpp +++ b/linphone-app/src/components/conference/ConferenceListener.hpp @@ -35,6 +35,7 @@ public: virtual ~ConferenceListener(); // LINPHONE LISTENERS + virtual void onActiveSpeakerParticipantDevice(const std::shared_ptr & conference, const std::shared_ptr & participantDevice) override; virtual void onParticipantAdded(const std::shared_ptr & conference, const std::shared_ptr & participant) override; virtual void onParticipantRemoved(const std::shared_ptr & conference, const std::shared_ptr & participant) override; virtual void onParticipantAdminStatusChanged(const std::shared_ptr & conference, const std::shared_ptr & participant) override; @@ -50,6 +51,7 @@ public: //--------------------------------------------------------------------------- signals: + void activeSpeakerParticipantDevice(const std::shared_ptr & participantDevice); void participantAdded(const std::shared_ptr & participant); void participantRemoved(const std::shared_ptr & participant); void participantAdminStatusChanged(const std::shared_ptr & participant); @@ -61,6 +63,7 @@ signals: void participantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking); void conferenceStateChanged(linphone::Conference::State newState); void subjectChanged(const std::string & subject); + }; diff --git a/linphone-app/src/components/conference/ConferenceModel.cpp b/linphone-app/src/components/conference/ConferenceModel.cpp index aad85a9ac..e09a7d510 100644 --- a/linphone-app/src/components/conference/ConferenceModel.cpp +++ b/linphone-app/src/components/conference/ConferenceModel.cpp @@ -37,6 +37,7 @@ #include "components/Components.hpp" void ConferenceModel::connectTo(ConferenceListener * listener){ + connect(listener, &ConferenceListener::activeSpeakerParticipantDevice, this, &ConferenceModel::onActiveSpeakerParticipantDevice); connect(listener, &ConferenceListener::participantAdded, this, &ConferenceModel::onParticipantAdded); connect(listener, &ConferenceListener::participantRemoved, this, &ConferenceModel::onParticipantRemoved); connect(listener, &ConferenceListener::participantAdminStatusChanged, this, &ConferenceModel::onParticipantAdminStatusChanged); @@ -140,6 +141,9 @@ void ConferenceModel::setIsReady(bool state){ //----------------------------------------------------------------------------------------------------------------------- // LINPHONE LISTENERS //----------------------------------------------------------------------------------------------------------------------- +void ConferenceModel::onActiveSpeakerParticipantDevice(const std::shared_ptr & participantDevice){ + emit activeSpeakerParticipantDevice(participantDevice); +} void ConferenceModel::onParticipantAdded(const std::shared_ptr & participant){ qDebug() << "Added call, participant count: " << getParticipantList().size() << ". Me devices : " << mConference->getMe()->getDevices().size(); updateLocalParticipant(); diff --git a/linphone-app/src/components/conference/ConferenceModel.hpp b/linphone-app/src/components/conference/ConferenceModel.hpp index f5936b8ef..214681e2a 100644 --- a/linphone-app/src/components/conference/ConferenceModel.hpp +++ b/linphone-app/src/components/conference/ConferenceModel.hpp @@ -62,7 +62,7 @@ public: void setIsReady(bool state); - + virtual void onActiveSpeakerParticipantDevice(const std::shared_ptr & participantDevice); virtual void onParticipantAdded(const std::shared_ptr & participant); virtual void onParticipantRemoved(const std::shared_ptr & participant); virtual void onParticipantAdminStatusChanged(const std::shared_ptr & participant); @@ -77,6 +77,7 @@ public: //--------------------------------------------------------------------------- signals: + void activeSpeakerParticipantDevice(const std::shared_ptr & participantDevice); void localParticipantChanged(); void participantAdded(const std::shared_ptr & participant); void participantRemoved(const std::shared_ptr & participant); diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp index 17087a240..fa92147fa 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp @@ -100,7 +100,6 @@ public: virtual void onStateChanged(linphone::ConferenceScheduler::State state); virtual void onInvitationsSent(const std::list> & failedInvitations); - signals: void timeZoneModelChanged(); void dateTimeChanged(); diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp index 05f132cd9..ebb5234b1 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp @@ -58,6 +58,7 @@ void ParticipantDeviceListModel::initConferenceModel(){ updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false); qDebug() << "Conference have " << mList.size() << " devices"; + connect(conferenceModel.get(), &ConferenceModel::activeSpeakerParticipantDevice, this, &ParticipantDeviceListModel::onActiveSpeakerParticipantDevice); connect(conferenceModel.get(), &ConferenceModel::participantAdded, this, &ParticipantDeviceListModel::onParticipantAdded); connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this, &ParticipantDeviceListModel::onParticipantRemoved); connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded); @@ -116,6 +117,9 @@ bool ParticipantDeviceListModel::add(std::shared_ptr()->getDevice()))){ + mActiveSpeaker = mList.back().objectCast(); + emit activeSpeakerChanged(); } return true; } @@ -126,7 +130,6 @@ bool ParticipantDeviceListModel::remove(std::shared_ptr(); if( device->getDevice() == deviceToRemove){ device->updateVideoEnabled(); - mActiveSpeakers.removeAll(device.get()); removeRow(row); return true; }else @@ -163,14 +166,8 @@ QSharedPointer ParticipantDeviceListModel::getMe(int * i return nullptr; } -ParticipantDeviceModel* ParticipantDeviceListModel::getLastActiveSpeaking() const{ - if( mActiveSpeakers.size() == 0){ - if( mList.size() == 0) - return getMe().get(); - else - return mList.back().objectCast().get(); - }else - return mActiveSpeakers.first(); +ParticipantDeviceModel* ParticipantDeviceListModel::getActiveSpeakerModel() const{ + return mActiveSpeaker.get(); } bool ParticipantDeviceListModel::isMe(std::shared_ptr deviceToCheck)const{ @@ -280,6 +277,13 @@ void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(con else onParticipantDeviceAdded(participantDevice); } +void ParticipantDeviceListModel::onActiveSpeakerParticipantDevice(const std::shared_ptr& participantDevice){ + auto device = get(participantDevice); + if( device){ + mActiveSpeaker = device; + emit activeSpeakerChanged(); + } +} void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking){ auto device = get(participantDevice); @@ -288,14 +292,5 @@ void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std: } void ParticipantDeviceListModel::onParticipantDeviceSpeaking(){ - auto deviceModel = qobject_cast(sender()); - bool changed = false; - // Me should not be in the list. - if( !deviceModel->isMe() && (mActiveSpeakers.size() == 0 || deviceModel->getIsSpeaking())) {// Ensure to have at least one last active speaker - changed = mActiveSpeakers.removeAll(deviceModel) > 0; - mActiveSpeakers.push_front(deviceModel); - changed = true; - } - if(changed) - emit participantSpeaking(deviceModel); + } diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp index 318e46730..ed5edc3c1 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp @@ -47,12 +47,13 @@ public: bool remove(std::shared_ptr deviceToAdd); QSharedPointer get(std::shared_ptr deviceToGet, int * index = nullptr); QSharedPointer getMe(int * index = nullptr)const; - ParticipantDeviceModel* getLastActiveSpeaking() const; + ParticipantDeviceModel* getActiveSpeakerModel() const; bool isMe(std::shared_ptr device)const; bool isMeAlone() const; public slots: + void onActiveSpeakerParticipantDevice(const std::shared_ptr& participantDevice); void onConferenceModelChanged (); void onSecurityLevelChanged(std::shared_ptr device); void onParticipantAdded(const std::shared_ptr & participant); @@ -66,6 +67,7 @@ public slots: void onParticipantDeviceSpeaking(); signals: + void activeSpeakerChanged(); void securityLevelChanged(std::shared_ptr device); void participantSpeaking(ParticipantDeviceModel *speakingDevice); void conferenceCreated(); @@ -73,7 +75,8 @@ signals: private: CallModel * mCallModel = nullptr; - QList mActiveSpeakers;// First item is last speaker + QSharedPointer mActiveSpeaker; + //QList mActiveSpeakers;// First item is last speaker bool mInitialized = false; }; diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp index b05c9129d..272c25480 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp @@ -57,9 +57,9 @@ ParticipantDeviceModel *ParticipantDeviceProxyModel::getAt(int row){ return sourceModel()->data(sourceIndex).value(); } -ParticipantDeviceModel* ParticipantDeviceProxyModel::getLastActiveSpeaking(){ +ParticipantDeviceModel* ParticipantDeviceProxyModel::getActiveSpeakerModel(){ auto listModel = qobject_cast(sourceModel()); - return listModel ? listModel->getLastActiveSpeaking() : nullptr; + return listModel ? listModel->getActiveSpeakerModel() : nullptr; } CallModel * ParticipantDeviceProxyModel::getCallModel() const{ @@ -74,15 +74,19 @@ ParticipantDeviceModel * ParticipantDeviceProxyModel::getMe() const{ bool ParticipantDeviceProxyModel::isShowMe() const{ return mShowMe; } - + +void ParticipantDeviceProxyModel::connectTo(ParticipantDeviceListModel* model){ + connect(model, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged); + connect(model, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking); + connect(model, &ParticipantDeviceListModel::conferenceCreated, this, &ParticipantDeviceProxyModel::conferenceCreated); + connect(model, &ParticipantDeviceListModel::meChanged, this, &ParticipantDeviceProxyModel::meChanged); + connect(model, &ParticipantDeviceListModel::activeSpeakerChanged, this, &ParticipantDeviceProxyModel::activeSpeakerChanged); +} void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){ setFilterType(1); mCallModel = callModel; auto sourceModel = new ParticipantDeviceListModel(mCallModel); - connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged); - connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking); - connect(sourceModel, &ParticipantDeviceListModel::conferenceCreated, this, &ParticipantDeviceProxyModel::conferenceCreated); - connect(sourceModel, &ParticipantDeviceListModel::meChanged, this, &ParticipantDeviceProxyModel::meChanged); + connectTo(sourceModel); setSourceModel(sourceModel); emit countChanged(); emit meChanged(); @@ -91,10 +95,7 @@ void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){ void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant){ setFilterType(0); auto sourceModel = participant->getParticipantDevices().get(); - connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged); - connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking); - connect(sourceModel, &ParticipantDeviceListModel::conferenceCreated, this, &ParticipantDeviceProxyModel::conferenceCreated); - connect(sourceModel, &ParticipantDeviceListModel::meChanged, this, &ParticipantDeviceProxyModel::meChanged); + connectTo(sourceModel); setSourceModel(sourceModel); emit countChanged(); emit meChanged(); diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp index ecdedfd02..9a939ac53 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp @@ -42,12 +42,14 @@ public: Q_PROPERTY(CallModel * callModel READ getCallModel WRITE setCallModel NOTIFY callModelChanged) Q_PROPERTY(bool showMe READ isShowMe WRITE setShowMe NOTIFY showMeChanged) Q_PROPERTY(ParticipantDeviceModel * me READ getMe NOTIFY meChanged) + Q_PROPERTY(ParticipantDeviceModel* activeSpeaker READ getActiveSpeakerModel NOTIFY activeSpeakerChanged) ParticipantDeviceProxyModel (QObject *parent = nullptr); Q_INVOKABLE ParticipantDeviceModel* getAt(int row); - Q_INVOKABLE ParticipantDeviceModel* getLastActiveSpeaking(); - ParticipantDeviceModel * getMe() const; + ParticipantDeviceModel* getActiveSpeakerModel(); + ParticipantDeviceModel* getMe() const; + CallModel * getCallModel() const; bool isShowMe() const; @@ -56,11 +58,14 @@ public: void setParticipant(ParticipantModel * participant); void setShowMe(const bool& show); + void connectTo(ParticipantDeviceListModel* model); + public slots: void onCountChanged(); void onParticipantSpeaking(ParticipantDeviceModel * speakingDevice); signals: + void activeSpeakerChanged(); void callModelChanged(); void showMeChanged(); void meChanged(); diff --git a/linphone-app/src/utils/LinphoneEnums.hpp b/linphone-app/src/utils/LinphoneEnums.hpp index 806bf3139..16af1fae9 100644 --- a/linphone-app/src/utils/LinphoneEnums.hpp +++ b/linphone-app/src/utils/LinphoneEnums.hpp @@ -189,6 +189,7 @@ void fromString(const QString& transportType, LinphoneEnums::TransportType *tran Q_DECLARE_METATYPE(LinphoneEnums::CallStatus) + Q_DECLARE_METATYPE(LinphoneEnums::ChatMessageState) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceLayout) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceInfoState) @@ -198,6 +199,6 @@ Q_DECLARE_METATYPE(LinphoneEnums::MediaEncryption) Q_DECLARE_METATYPE(LinphoneEnums::ParticipantDeviceState) Q_DECLARE_METATYPE(LinphoneEnums::RecorderState) Q_DECLARE_METATYPE(LinphoneEnums::TunnelMode) - +Q_DECLARE_METATYPE(LinphoneEnums::TransportType) #endif diff --git a/linphone-app/ui/modules/Linphone/Contact/Contact.qml b/linphone-app/ui/modules/Linphone/Contact/Contact.qml index ae90b0a1a..e71f3a53a 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Contact.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Contact.qml @@ -107,7 +107,9 @@ Rectangle { ? item.organizer ? item.organizer : entry.sipAddress || entry.fullPeerAddress || entry.peerAddress || '' - : entry.participants.addressesToString + : entry.participants + ? entry.participants.addressesToString + : '' : '' } diff --git a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml index 8d6626699..47d84a931 100644 --- a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml +++ b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml @@ -29,30 +29,12 @@ Item { property int participantCount: callModel.isConference ? allDevices.count + 1 : 2 // +me. allDevices==0 if !conference - onParticipantCountChanged: {Qt.callLater(allDevices.updateCurrentDevice)} - property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel { id: allDevices callModel: mainItem.callModel - showMe: false - - onParticipantSpeaking: updateCurrentDevice() - + showMe: false onConferenceCreated: cameraView.resetCamera() - function updateCurrentDevice(){ - if( callModel ){ - if( callModel.isConference) { - var device = getLastActiveSpeaking() - if(device) // Get - cameraView.currentDevice = device - } - } - } - onMeChanged: if(cameraView.isPreview) { - cameraView.currentDevice = me - cameraView.resetCamera() - } } function clearAll(layoutMode){ @@ -67,6 +49,11 @@ Item { anchors.leftMargin: isRightReducedLayout || isLeftReducedLayout? 30 : 140 anchors.rightMargin: isRightReducedLayout ? 10 : 140 callModel: mainItem.callModel + currentDevice: isPreview + ? allDevices.me + : callModel.isConference + ? allDevices.activeSpeaker + : null deactivateCamera: isPreview && callModel.pausedByUser ? true : callModel.isConference @@ -79,14 +66,7 @@ Item { isVideoEnabled: !deactivateCamera isPreview: !preview.visible && mainItem.participantCount == 1 - onIsPreviewChanged: { - if( isPreview){ - currentDevice = allDevices.me - cameraView.resetCamera() - }else - allDevices.updateCurrentDevice() - cameraView.resetCamera() - } + onIsPreviewChanged: {cameraView.resetCamera() } isCameraFromDevice: isPreview isPaused: isPreview && callModel.pausedByUser ? false @@ -193,3 +173,4 @@ Item { } } + diff --git a/linphone-sdk b/linphone-sdk index b5cc94b43..11f72d4e2 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit b5cc94b43b9ad5644f5d7ec8bd8f9f7a81127a54 +Subproject commit 11f72d4e254a2a8305a9400e38cb44f125c18873 From ced6a8b3966a096354029b3e20d6b4a38d8c0f27 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 2 Nov 2022 11:00:28 +0100 Subject: [PATCH 14/61] Change contacts list to take account of all contacts in database (multiple lists, bodyless, remote provision) --- CHANGELOG.md | 1 + linphone-app/CMakeLists.txt | 2 + .../src/components/contact/ContactModel.cpp | 4 + .../src/components/contact/ContactModel.hpp | 2 + .../components/contacts/ContactsListModel.cpp | 92 ++++++++++++------- .../components/contacts/ContactsListModel.hpp | 14 ++- .../src/components/core/CoreManager.cpp | 2 +- .../components/friend/FriendListListener.cpp | 51 ++++++++++ .../components/friend/FriendListListener.hpp | 50 ++++++++++ linphone-app/ui/views/App/Main/MainWindow.qml | 2 + 10 files changed, 187 insertions(+), 33 deletions(-) create mode 100644 linphone-app/src/components/friend/FriendListListener.cpp create mode 100644 linphone-app/src/components/friend/FriendListListener.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index a0925c545..30ff3da58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New call layouts. - Display a waiting room before going into a conference. - Log viewer. +- Read contacts from all friends lists. - Option to set the display name in "using an account" tab of assistant. - Long pressed buttons. - Phone dialpad on main window. diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index 656baf131..431756981 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -204,6 +204,7 @@ set(SOURCES src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp src/components/file/FileDownloader.cpp src/components/file/FileExtractor.cpp + src/components/friend/FriendListListener.cpp src/components/history/HistoryModel.cpp src/components/history/HistoryProxyModel.cpp src/components/ldap/LdapModel.cpp @@ -338,6 +339,7 @@ set(HEADERS src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp src/components/file/FileDownloader.hpp src/components/file/FileExtractor.hpp + src/components/friend/FriendListListener.hpp src/components/history/HistoryModel.hpp src/components/history/HistoryProxyModel.hpp src/components/ldap/LdapModel.hpp diff --git a/linphone-app/src/components/contact/ContactModel.cpp b/linphone-app/src/components/contact/ContactModel.cpp index ddfa6cc25..7d85c58d3 100644 --- a/linphone-app/src/components/contact/ContactModel.cpp +++ b/linphone-app/src/components/contact/ContactModel.cpp @@ -215,3 +215,7 @@ Presence::PresenceLevel ContactModel::getPresenceLevel () const { bool ContactModel::hasCapability(const LinphoneEnums::FriendCapability& capability){ return mLinphoneFriend->hasCapability(LinphoneEnums::toLinphone(capability)); } + +std::shared_ptr ContactModel::getFriend() const{ + return mLinphoneFriend; +} \ No newline at end of file diff --git a/linphone-app/src/components/contact/ContactModel.hpp b/linphone-app/src/components/contact/ContactModel.hpp index c59eb01dd..e482b8d88 100644 --- a/linphone-app/src/components/contact/ContactModel.hpp +++ b/linphone-app/src/components/contact/ContactModel.hpp @@ -57,6 +57,8 @@ public: Q_INVOKABLE VcardModel *cloneVcardModel () const; Presence::PresenceLevel getPresenceLevel () const; Q_INVOKABLE bool hasCapability(const LinphoneEnums::FriendCapability& capability); + + std::shared_ptr getFriend() const; signals: void contactUpdated (); diff --git a/linphone-app/src/components/contacts/ContactsListModel.cpp b/linphone-app/src/components/contacts/ContactsListModel.cpp index c2bf043b0..337ff8fad 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.cpp +++ b/linphone-app/src/components/contacts/ContactsListModel.cpp @@ -24,40 +24,26 @@ #include "components/contact/ContactModel.hpp" #include "components/contact/VcardModel.hpp" #include "components/core/CoreManager.hpp" +#include "components/friend/FriendListListener.hpp" #include "ContactsListModel.hpp" +// ============================================================================= +void ContactsListModel::connectTo(FriendListListener * listener){ + connect(listener, &FriendListListener::contactCreated, this, &ContactsListModel::onContactCreated); + connect(listener, &FriendListListener::contactDeleted, this, &ContactsListModel::onContactDeleted); + connect(listener, &FriendListListener::contactUpdated, this, &ContactsListModel::onContactUpdated); + connect(listener, &FriendListListener::syncStatusChanged, this, &ContactsListModel::onSyncStatusChanged); + connect(listener, &FriendListListener::presenceReceived, this, &ContactsListModel::onPresenceReceived); +} // ============================================================================= using namespace std; ContactsListModel::ContactsListModel (QObject *parent) : ProxyListModel(parent) { - mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists().front(); - // Clean friends. - { - list> toRemove; - for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) { - if (!linphoneFriend->getVcard()) - toRemove.push_back(linphoneFriend); - } - - for (const auto &linphoneFriend : toRemove) { - qWarning() << QStringLiteral("Remove one friend without vcard."); - mLinphoneFriends->removeFriend(linphoneFriend); - } - } - - // Init contacts with linphone friends list. - QQmlEngine *engine = App::getInstance()->getEngine(); - for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) { - auto contact = QSharedPointer::create(linphoneFriend); - - // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership - // The returned value must have a explicit parent or a QQmlEngine::CppOwnership. - engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership); - - addContact(contact); - } + mFriendListListener = std::make_shared(); + connectTo(mFriendListListener.get()); + update(); } ContactsListModel::~ContactsListModel(){ @@ -65,7 +51,7 @@ ContactsListModel::~ContactsListModel(){ beginResetModel(); mOptimizedSearch.clear(); mList.clear(); - mLinphoneFriends = nullptr; + mLinphoneFriends.clear(); endResetModel(); } } @@ -84,7 +70,8 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren mOptimizedSearch.remove(address.toString()); } - mLinphoneFriends->removeFriend(contact->mLinphoneFriend); + for(auto l : mLinphoneFriends) + l->removeFriend(contact->mLinphoneFriend); emit contactRemoved(contact); } @@ -123,7 +110,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) { contact = QSharedPointer::create(vcardModel); App::getInstance()->getEngine()->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership); - if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) { + if (mLinphoneFriends.front()->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) { qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel; return nullptr; } @@ -131,9 +118,8 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) { qInfo() << QStringLiteral("Add contact from vcard:") << contact.get() << vcardModel; // Make sure new subscribe is issued. - mLinphoneFriends->updateSubscriptions(); + mLinphoneFriends.front()->updateSubscriptions(); - addContact(contact); emit layoutChanged(); emit contactAdded(contact); @@ -177,3 +163,47 @@ void ContactsListModel::addContact (QSharedPointer contact) { mOptimizedSearch[address.toString()] = contact; } } + +void ContactsListModel::update(){ + beginResetModel(); + for(auto l : mLinphoneFriends) + l->removeListener(mFriendListListener); + mLinphoneFriends.clear(); + mOptimizedSearch.clear(); + mList.clear(); + endResetModel(); + + mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists(); + + for(auto l : mLinphoneFriends){ + l->addListener(mFriendListListener); + for (const auto &linphoneFriend : l->getFriends()) { + onContactCreated(linphoneFriend); + } + } +} + +//------------------------------------------------------------------------------------------------ + +void ContactsListModel::onContactCreated(const std::shared_ptr & linphoneFriend){ + QQmlEngine *engine = App::getInstance()->getEngine(); + auto haveContact = std::find_if(mList.begin(), mList.end(), [linphoneFriend] (const QSharedPointer& item){ + return item.objectCast()->getFriend() == linphoneFriend; + }); + if(haveContact == mList.end()) { + auto contact = QSharedPointer::create(linphoneFriend); + // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership + // The returned value must have a explicit parent or a QQmlEngine::CppOwnership. + engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership); + addContact(contact); + } +} +void ContactsListModel::onContactDeleted(const std::shared_ptr & linphoneFriend){ +} +void ContactsListModel::onContactUpdated(const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend){ +} +void ContactsListModel::onSyncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message){ +} +void ContactsListModel::onPresenceReceived(const std::list> & friends){ +} + diff --git a/linphone-app/src/components/contacts/ContactsListModel.hpp b/linphone-app/src/components/contacts/ContactsListModel.hpp index f6ea3b627..aa59869a3 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.hpp +++ b/linphone-app/src/components/contacts/ContactsListModel.hpp @@ -33,6 +33,7 @@ namespace linphone { class ContactModel; class VcardModel; +class FriendListListener; class ContactsListModel : public ProxyListModel { friend class SipAddressesModel; @@ -52,6 +53,16 @@ public: Q_INVOKABLE void removeContact (ContactModel *contact); Q_INVOKABLE void cleanAvatars (); + Q_INVOKABLE void update (); + + void connectTo(FriendListListener * listener); + +public slots: + void onContactCreated(const std::shared_ptr & linphoneFriend); + void onContactDeleted(const std::shared_ptr & linphoneFriend); + void onContactUpdated(const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend); + void onSyncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message); + void onPresenceReceived(const std::list> & friends); signals: void contactAdded (QSharedPointer); @@ -65,7 +76,8 @@ private: void addContact (QSharedPointer contact); QMap> mOptimizedSearch; - std::shared_ptr mLinphoneFriends; + std::list> mLinphoneFriends; + std::shared_ptr mFriendListListener; }; #endif // CONTACTS_LIST_MODEL_H_ diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index 07ba4f78f..c4c013123 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -260,6 +260,7 @@ void CoreManager::createLinphoneCore (const QString &configPath) { Paths::getFactoryConfigFilePath(), nullptr ); + setDatabasesPaths(); // Enable LIME on your core to use encryption. mCore->enableLimeX3Dh(mCore->limeX3DhAvailable()); // Now see the CoreService.CreateGroupChatRoom to see how to create a secure chat room @@ -279,7 +280,6 @@ void CoreManager::createLinphoneCore (const QString &configPath) { QString userAgent = Utils::computeUserAgent(config); mCore->setUserAgent(Utils::appStringToCoreString(userAgent), mCore->getVersion()); mCore->start(); - setDatabasesPaths(); setOtherPaths(); mCore->enableFriendListSubscription(true); mCore->enableRecordAware(true); diff --git a/linphone-app/src/components/friend/FriendListListener.cpp b/linphone-app/src/components/friend/FriendListListener.cpp new file mode 100644 index 000000000..12d976792 --- /dev/null +++ b/linphone-app/src/components/friend/FriendListListener.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#include "FriendListListener.hpp" +#include "../../utils/Utils.hpp" + +#include + +// ============================================================================= + +FriendListListener::FriendListListener(QObject *parent) : QObject(parent) { +} + +//-------------------------------------------------------------------- +void FriendListListener::onContactCreated(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) { + qDebug() << "onContactCreated: " << Utils::coreStringToAppString(linphoneFriend->getName()); + emit contactCreated(linphoneFriend); +} +void FriendListListener::onContactDeleted(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) { + qDebug() << "onContactDeleted: " << Utils::coreStringToAppString(linphoneFriend->getName()); + emit contactDeleted(linphoneFriend); +} +void FriendListListener::onContactUpdated(const std::shared_ptr & friendList, const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend) { + qDebug() << "onContactUpdated: " << Utils::coreStringToAppString(newFriend->getName()); + emit contactUpdated(newFriend, oldFriend); +} +void FriendListListener::onSyncStatusChanged(const std::shared_ptr & friendList, linphone::FriendList::SyncStatus status, const std::string & message) { + qDebug() << "onSyncStatusChanged: [" << (int)status<<"] " << Utils::coreStringToAppString(message); + emit syncStatusChanged(status, message); +} +void FriendListListener::onPresenceReceived(const std::shared_ptr & friendList, const std::list> & friends) { + qDebug() << "onPresenceReceived: " <. + */ + +#ifndef FRIEND_LIST_LISTENER_H_ +#define FRIEND_LIST_LISTENER_H_ + + +#include + +#include + +// ============================================================================= + +class FriendListListener : public QObject, public linphone::FriendListListener { + Q_OBJECT + +public: + FriendListListener (QObject *parent = nullptr); + virtual void onContactCreated(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) override; + virtual void onContactDeleted(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) override; + virtual void onContactUpdated(const std::shared_ptr & friendList, const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend) override; + virtual void onSyncStatusChanged(const std::shared_ptr & friendList, linphone::FriendList::SyncStatus status, const std::string & message) override; + virtual void onPresenceReceived(const std::shared_ptr & friendList, const std::list> & friends) override; + +signals: + void contactCreated(const std::shared_ptr & linphoneFriend); + void contactDeleted(const std::shared_ptr & linphoneFriend); + void contactUpdated(const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend); + void syncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message); + void presenceReceived(const std::list> & friends); +}; + +#endif diff --git a/linphone-app/ui/views/App/Main/MainWindow.qml b/linphone-app/ui/views/App/Main/MainWindow.qml index e84ded5f2..b60cc6661 100644 --- a/linphone-app/ui/views/App/Main/MainWindow.qml +++ b/linphone-app/ui/views/App/Main/MainWindow.qml @@ -307,10 +307,12 @@ ApplicationWindow { visible: SettingsModel.contactsEnabled onSelected: { + ContactsListModel.update() timeline.model.unselectAll() setView('Contacts') } onClicked:{ + ContactsListModel.update() setView('Contacts') } Icon{ From dd39203d47a4bc3aaac15adfe43fd1c155942126 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 2 Nov 2022 16:46:06 +0100 Subject: [PATCH 15/61] Change group chats and conference icons. Change color on selected call (call list). Change burger icon into dot menu in calls list. Change conversation icon to match timeline. Merge calls into conference. Fix twin participants on invitation. --- .../assets/images/chat_room_custom.svg | 75 ++++++---------- .../assets/images/conference_merge_custom.svg | 67 ++++++++++++++ linphone-app/resources.qrc | 1 + .../src/components/call/CallModel.cpp | 13 ++- .../src/components/call/CallModel.hpp | 2 + .../src/components/calls/CallsListModel.cpp | 90 ++++++++++++++++++- .../src/components/calls/CallsListModel.hpp | 6 ++ .../ParticipantDeviceListModel.cpp | 13 +++ .../modules/Linphone/Calls/CallControls.qml | 1 + .../ui/modules/Linphone/Calls/Calls.qml | 11 +-- .../ui/modules/Linphone/Contact/Avatar.qml | 7 +- .../ui/modules/Linphone/Contact/Contact.qml | 1 + .../Linphone/Styles/Calls/CallsStyle.qml | 5 +- .../Linphone/Styles/Contact/AvatarStyle.qml | 3 + .../Linphone/Styles/Contact/ContactStyle.qml | 1 + .../ui/views/App/Calls/CallsWindow.qml | 5 +- .../ui/views/App/Main/Conversation.qml | 15 +--- .../App/Styles/Calls/CallsWindowStyle.qml | 8 +- linphone-sdk | 2 +- 19 files changed, 243 insertions(+), 83 deletions(-) create mode 100644 linphone-app/assets/images/conference_merge_custom.svg diff --git a/linphone-app/assets/images/chat_room_custom.svg b/linphone-app/assets/images/chat_room_custom.svg index 408e19619..a9d140c6d 100644 --- a/linphone-app/assets/images/chat_room_custom.svg +++ b/linphone-app/assets/images/chat_room_custom.svg @@ -3,16 +3,19 @@ width="80" height="80" viewBox="0 0 80 80" + fill="none" version="1.1" - id="svg21" + id="svg8" sodipodi:docname="chat_room_custom.svg" - inkscape:version="1.1 (c68e22c387, 2021-05-23)" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + - - - - - + inkscape:current-layer="svg8" /> - - - - - - - - - - + id="g832" + transform="matrix(0.67345025,0,0,0.67345025,9.9999997,20)"> + + + diff --git a/linphone-app/assets/images/conference_merge_custom.svg b/linphone-app/assets/images/conference_merge_custom.svg new file mode 100644 index 000000000..8f195ab4b --- /dev/null +++ b/linphone-app/assets/images/conference_merge_custom.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc index d3d6ddeee..8cc39f5fa 100644 --- a/linphone-app/resources.qrc +++ b/linphone-app/resources.qrc @@ -62,6 +62,7 @@ assets/images/conference_audio_only_custom.svg assets/images/conference_layout_grid_custom.svg assets/images/conference_layout_active_speaker_custom.svg + assets/images/conference_merge_custom.svg assets/images/contact_add_custom.svg assets/images/contact_card_photo_custom.svg assets/images/contact_custom.svg diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index 093d3158d..63a8ed4a3 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -109,8 +109,10 @@ CallModel::CallModel (shared_ptr call){ if(mCall) { mRemoteAddress = mCall->getRemoteAddress()->clone(); - if(mCall->getConference()) + if(mCall->getConference()) { mConferenceModel = ConferenceModel::create(mCall->getConference()); + connect(mConferenceModel.get(), &ConferenceModel::participantAdminStatusChanged, this, &CallModel::onParticipantAdminStatusChanged); + } auto conferenceInfo = CoreManager::getInstance()->getCore()->findConferenceInformationFromUri(getConferenceAddress()); if( conferenceInfo ){ mConferenceInfoModel = ConferenceInfoModel::create(conferenceInfo); @@ -232,7 +234,8 @@ ConferenceInfoModel * CallModel::getConferenceInfoModel(){ QSharedPointer CallModel::getConferenceSharedModel(){ if(mCall->getConference() && !mConferenceModel){ - mConferenceModel = ConferenceModel::create(mCall->getConference()); + mConferenceModel = ConferenceModel::create(mCall->getConference()); + connect(mConferenceModel.get(), &ConferenceModel::participantAdminStatusChanged, this, &CallModel::onParticipantAdminStatusChanged); emit conferenceModelChanged(); } return mConferenceModel; @@ -977,6 +980,12 @@ void CallModel::onChatRoomInitialized(int state){ emit chatRoomModelChanged(); } +void CallModel::onParticipantAdminStatusChanged(const std::shared_ptr & participant){ + if(mConferenceModel && participant == mConferenceModel->getConference()->getMe()) { + emit meAdminChanged(); + } +} + void CallModel::setRemoteDisplayName(const std::string& name){ mRemoteAddress->setDisplayName(name); if(mCall) { diff --git a/linphone-app/src/components/call/CallModel.hpp b/linphone-app/src/components/call/CallModel.hpp index 7138a000b..5c8976f97 100644 --- a/linphone-app/src/components/call/CallModel.hpp +++ b/linphone-app/src/components/call/CallModel.hpp @@ -200,8 +200,10 @@ public slots: void endCall(); void onRemoteRecording(const std::shared_ptr & call, bool recording); void onChatRoomInitialized(int state); + void onParticipantAdminStatusChanged(const std::shared_ptr & participant); signals: + void meAdminChanged(); void callErrorChanged (const QString &callError); void callIdChanged(); void isInConferenceChanged (bool status); diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp index 72c53acc5..924960e97 100644 --- a/linphone-app/src/components/calls/CallsListModel.cpp +++ b/linphone-app/src/components/calls/CallsListModel.cpp @@ -69,6 +69,7 @@ CallsListModel::CallsListModel (QObject *parent) : ProxyListModel(parent) { mCoreHandlers.get(), &CoreHandlers::callStateChanged, this, &CallsListModel::handleCallStateChanged ); + connect(this, &CallsListModel::countChanged, this, &CallsListModel::canMergeCallsChanged); } CallModel *CallsListModel::findCallModelFromPeerAddress (const QString &peerAddress) const { @@ -372,15 +373,100 @@ void CallsListModel::prepareConferenceCall(ConferenceInfoModel * model){ app->smartShowWindow(app->getCallsWindow()); emit callConferenceAsked(model); } + int CallsListModel::addAllToConference(){ return CoreManager::getInstance()->getCore()->addAllToConference(); } + +void CallsListModel::mergeAll(){ + auto core = CoreManager::getInstance()->getCore(); + auto currentCalls = CoreManager::getInstance()->getCore()->getCalls(); + shared_ptr conference = core->getConference(); + + // Search a managable conference from calls + if(!conference){ + for(auto call : currentCalls){ + auto dbConference = call->getConference(); + if(dbConference && dbConference->getMe()->isAdmin()){ + conference = dbConference; + break; + } + } + } + + auto currentCall = CoreManager::getInstance()->getCore()->getCurrentCall(); + bool enablingVideo = false; + if( currentCall ) + enablingVideo = currentCall->getCurrentParams()->videoEnabled(); + if(!conference){ + auto parameters = core->createConferenceParams(conference); + + if(!CoreManager::getInstance()->getSettingsModel()->getVideoConferenceEnabled()) { + parameters->enableVideo(false); + parameters->setConferenceFactoryAddress(nullptr);// Do a local conference + parameters->setSubject("Local meeting"); + }else{ + parameters->enableVideo(enablingVideo); + parameters->setSubject("Meeting"); + } + conference = core->createConferenceWithParams(parameters); + } + + list> allLinphoneAddresses; + list> newCalls; + list> runningCallsToAdd; + + for(auto call : currentCalls){ + if(!call->getConference()){ + runningCallsToAdd.push_back(call); + } + } + +// 1) Add running calls + if( runningCallsToAdd.size() > 0){ + conference->addParticipants(runningCallsToAdd); + } + /* +// 2) Put in pause and remove all calls that are not in the conference list + for(const auto &call : CoreManager::getInstance()->getCore()->getCalls()){ + const std::string callAddress = call->getRemoteAddress()->asStringUriOnly(); + auto address = allLinphoneAddresses.begin(); + while(address != allLinphoneAddresses.end() && (*address)->asStringUriOnly() != callAddress) + ++address; + if(address == allLinphoneAddresses.end()){// Not in conference list : put in pause and remove it from conference if it's the case + if( call->getParams()->getLocalConferenceMode() ){// Remove conference if it is not yet requested + CoreManager::getInstance()->getCore()->removeFromConference(call); + }else + call->pause(); + } + }*/ +} // ----------------------------------------------------------------------------- int CallsListModel::getRunningCallsNumber () const { return CoreManager::getInstance()->getCore()->getCallsNb(); } +bool CallsListModel::canMergeCalls()const{ + auto calls = CoreManager::getInstance()->getCore()->getCalls(); + + bool mergableConference = false; + int mergableCalls = 0; + bool mergable = false; + for(auto itCall = calls.begin(); !mergable && itCall != calls.end() ; ++itCall ) { + auto conference = (*itCall)->getConference(); + if(conference){ + if( !mergableConference ) + mergableConference = (conference && conference->getMe()->isAdmin()); + }else{ + ++mergableCalls; + } + mergable = (mergableConference && mergableCalls>0) // A call can be merged into the conference + || mergableCalls>1;// 2 calls can be merged + } + return mergable; +} + void CallsListModel::terminateAllCalls () const { CoreManager::getInstance()->getCore()->terminateAllCalls(); } @@ -479,6 +565,8 @@ void CallsListModel::addCall (const shared_ptr &call) { qInfo() << QStringLiteral("Add call:") << callModel->getFullLocalAddress() << callModel->getFullPeerAddress(); App::getInstance()->getEngine()->setObjectOwnership(callModel.get(), QQmlEngine::CppOwnership); + connect(callModel.get(), &CallModel::meAdminChanged, this, &CallsListModel::canMergeCallsChanged); + add(callModel); emit layoutChanged(); @@ -511,7 +599,7 @@ void CallsListModel::addDummyCall () { int id = findCallIndex(mList, *callModel); emit dataChanged(index(id, 0), index(id, 0)); }); - + connect(callModel.get(), &CallModel::meAdminChanged, this, &CallsListModel::canMergeCallsChanged); add(callModel); emit layoutChanged(); diff --git a/linphone-app/src/components/calls/CallsListModel.hpp b/linphone-app/src/components/calls/CallsListModel.hpp index c7ed56ce1..1c774c039 100644 --- a/linphone-app/src/components/calls/CallsListModel.hpp +++ b/linphone-app/src/components/calls/CallsListModel.hpp @@ -37,6 +37,9 @@ class CallsListModel : public ProxyListModel { Q_OBJECT public: + Q_PROPERTY(bool canMergeCalls READ canMergeCalls NOTIFY canMergeCallsChanged) + + CallsListModel (QObject *parent = Q_NULLPTR); CallModel *findCallModelFromPeerAddress (const QString &peerAddress) const; @@ -57,9 +60,11 @@ public: Q_INVOKABLE void prepareConferenceCall(ConferenceInfoModel * model); Q_INVOKABLE int addAllToConference(); + Q_INVOKABLE void mergeAll(); Q_INVOKABLE int getRunningCallsNumber () const; + bool canMergeCalls()const; Q_INVOKABLE void terminateAllCalls () const; Q_INVOKABLE void terminateCall (const QString& sipAddress) const; @@ -73,6 +78,7 @@ signals: void callConferenceAsked(ConferenceInfoModel * conferenceInfoModel); void callMissed (CallModel *callModel); + void canMergeCallsChanged(); private: diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp index ebb5234b1..ea2e9b6c8 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp @@ -99,6 +99,8 @@ void ParticipantDeviceListModel::updateDevices(const std::list deviceToAdd){ + auto deviceToAddAddr = deviceToAdd->getAddress(); + int row = 0; qDebug() << "Adding device " << deviceToAdd->getAddress()->asString().c_str(); for(auto item : mList) { auto deviceModel = item.objectCast(); @@ -106,7 +108,12 @@ bool ParticipantDeviceListModel::add(std::shared_ptrupdateVideoEnabled(); return false; + }else if(deviceToAddAddr->equal(deviceModel->getDevice()->getAddress())){// Address is the same (same device) but the model is using another linphone object. Replace it. + deviceModel->updateVideoEnabled(); + removeRow(row); + break; } + ++row; } bool addMe = isMe(deviceToAdd); auto deviceModel = ParticipantDeviceModel::create(mCallModel, deviceToAdd, addMe); @@ -114,6 +121,12 @@ bool ParticipantDeviceListModel::add(std::shared_ptr(deviceModel); qDebug() << "Device added. Count=" << mList.count(); + QStringList debugDevices; + for(auto i : mList){ + auto item = i.objectCast(); + debugDevices.push_back( item->getAddress()); + } + qDebug() << debugDevices.join("\n"); if( addMe){ qDebug() << "Added a me device"; emit meChanged(); diff --git a/linphone-app/ui/modules/Linphone/Calls/CallControls.qml b/linphone-app/ui/modules/Linphone/Calls/CallControls.qml index 1797322f5..9687bdf4e 100644 --- a/linphone-app/ui/modules/Linphone/Calls/CallControls.qml +++ b/linphone-app/ui/modules/Linphone/Calls/CallControls.qml @@ -13,6 +13,7 @@ Rectangle { // --------------------------------------------------------------------------- default property alias _content: content.data + property alias isDarkMode: contact.isDarkMode property alias signIcon: signIcon.icon property alias subtitleColor: contact.subtitleColor diff --git a/linphone-app/ui/modules/Linphone/Calls/Calls.qml b/linphone-app/ui/modules/Linphone/Calls/Calls.qml index 4ce7f47f5..5004e78d5 100644 --- a/linphone-app/ui/modules/Linphone/Calls/Calls.qml +++ b/linphone-app/ui/modules/Linphone/Calls/Calls.qml @@ -144,20 +144,17 @@ ListView { id: _callControls // ------------------------------------------------------------------------- - - function useColorStatus () { - return calls.currentIndex === index && $modelData && $modelData.status !== CallModel.CallStatusEnded - } + isDarkMode: calls.currentIndex === index && $modelData!=undefined && $modelData.status!=undefined && $modelData.status !== CallModel.CallStatusEnded // ------------------------------------------------------------------------- - color: useColorStatus() + color: isDarkMode ? CallsStyle.entry.color.selected : CallsStyle.entry.color.normal - subtitleColor: useColorStatus() + subtitleColor: isDarkMode ? CallsStyle.entry.subtitleColor.selected : CallsStyle.entry.subtitleColor.normal - titleColor: useColorStatus() + titleColor: isDarkMode ? CallsStyle.entry.titleColor.selected : CallsStyle.entry.titleColor.normal diff --git a/linphone-app/ui/modules/Linphone/Contact/Avatar.qml b/linphone-app/ui/modules/Linphone/Contact/Avatar.qml index efe711055..a1a06c7a8 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Avatar.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Avatar.qml @@ -15,7 +15,8 @@ Item { // --------------------------------------------------------------------------- property alias presenceLevel: presenceLevelIcon.level - property color backgroundColor: AvatarStyle.backgroundColor + property bool isDarkMode: false + property color backgroundColor: isDarkMode ? AvatarStyle.backgroundDarkModeColor : AvatarStyle.backgroundColor property color foregroundColor: 'transparent' property string username property var image @@ -64,7 +65,7 @@ Item { Text { id: initialsText anchors.centerIn: parent - color: AvatarStyle.initials.color + color: isDarkMode ? AvatarStyle.initials.darkModeColor : AvatarStyle.initials.color font.pointSize: { var width @@ -82,7 +83,7 @@ Item { Icon { anchors.fill: parent icon: ContactStyle.groupChat.icon - overwriteColor: ContactStyle.groupChat.avatarColor + overwriteColor: isDarkMode ? ContactStyle.groupChat.avatarDarkModeColor : ContactStyle.groupChat.avatarColor iconSize: avatar.width //visible: entry!=undefined && entry.isOneToOne!=undefined && !entry.isOneToOne visible: !avatar.isOneToOne diff --git a/linphone-app/ui/modules/Linphone/Contact/Contact.qml b/linphone-app/ui/modules/Linphone/Contact/Contact.qml index e71f3a53a..630ee0ab0 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Contact.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Contact.qml @@ -21,6 +21,7 @@ Rectangle { property alias subtitleColor: description.subtitleColor property alias titleColor: description.titleColor property alias statusText : description.statusText + property alias isDarkMode: avatar.isDarkMode property bool displayUnreadMessageCount: false property bool showSubtitle : true diff --git a/linphone-app/ui/modules/Linphone/Styles/Calls/CallsStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Calls/CallsStyle.qml index 3722411a7..7056af056 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Calls/CallsStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Calls/CallsStyle.qml @@ -19,7 +19,7 @@ QtObject { } property QtObject burgerMenu: QtObject { property string name : 'burgerMenu' - property string icon : 'burger_menu_custom' + property string icon : 'menu_vdots_custom' property int iconSize: 35 property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color @@ -30,7 +30,7 @@ QtObject { } property QtObject selectedBurgerMenu: QtObject { property string name : 'selectedBurgerMenu' - property string icon : 'burger_menu_custom' + property string icon : 'menu_vdots_custom' property int iconSize: 35 property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_inv_bg').color property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_inv_bg').color @@ -39,6 +39,7 @@ QtObject { property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_inv_fg').color property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_inv_fg').color } + property QtObject hangup: QtObject { property int iconSize: 35 property string icon : 'hangup_custom' diff --git a/linphone-app/ui/modules/Linphone/Styles/Contact/AvatarStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Contact/AvatarStyle.qml index a7344b858..8f8f9c1d6 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Contact/AvatarStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Contact/AvatarStyle.qml @@ -9,11 +9,14 @@ import ColorsList 1.0 QtObject { property string sectionName: 'Avatar' property color backgroundColor: ColorsList.add(sectionName+'_bg', 'd').color + property color backgroundDarkModeColor: ColorsList.add(sectionName+'_dark_bg', 'q').color + property string personImage : 'contact_custom' property QtObject initials: QtObject { property color color: ColorsList.add(sectionName+'_initials', 'q').color + property color darkModeColor: ColorsList.add(sectionName+'_dark_initials', 'd').color property int pointSize: Units.dp * 10 property int ratio: 30 } diff --git a/linphone-app/ui/modules/Linphone/Styles/Contact/ContactStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Contact/ContactStyle.qml index 0e25378c6..29b751b5d 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Contact/ContactStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Contact/ContactStyle.qml @@ -16,5 +16,6 @@ QtObject { property string icon: 'chat_room_custom' property color color: ColorsList.addImageColor(sectionName+'_groupChat', icon, 'g').color property color avatarColor: ColorsList.addImageColor(sectionName+'_groupChat_onAvatar', icon, 'q').color + property color avatarDarkModeColor: ColorsList.addImageColor(sectionName+'_groupChat_dark_onAvatar', icon, 'd').color } } diff --git a/linphone-app/ui/views/App/Calls/CallsWindow.qml b/linphone-app/ui/views/App/Calls/CallsWindow.qml index 38a188c9f..5a2b81b69 100644 --- a/linphone-app/ui/views/App/Calls/CallsWindow.qml +++ b/linphone-app/ui/views/App/Calls/CallsWindow.qml @@ -140,11 +140,12 @@ Window { ActionButton { isCustom: true backgroundRadius: 4 - colorSet: CallsWindowStyle.callsList.newConference + colorSet: CallsWindowStyle.callsList.mergeConference visible: SettingsModel.conferenceEnabled + enabled: CallsListModel.canMergeCalls onClicked: { - Logic.openConferenceManager() + CallsListModel.mergeAll() } } } diff --git a/linphone-app/ui/views/App/Main/Conversation.qml b/linphone-app/ui/views/App/Main/Conversation.qml index b2cf8b343..40fa59185 100644 --- a/linphone-app/ui/views/App/Main/Conversation.qml +++ b/linphone-app/ui/views/App/Main/Conversation.qml @@ -103,20 +103,9 @@ ColumnLayout { //username: Logic.getUsername() username: chatRoomModel?chatRoomModel.username:( conversation._sipAddressObserver ? UtilsCpp.getDisplayName(conversation._sipAddressObserver.peerAddress) : '') - visible: !groupChat.visible + isOneToOne: chatRoomModel==undefined || chatRoomModel.isOneToOne==undefined || chatRoomModel.isOneToOne } - Icon { - id: groupChat - - Layout.preferredHeight: ConversationStyle.bar.groupChatSize - Layout.preferredWidth: ConversationStyle.bar.groupChatSize - - icon: ConversationStyle.bar.groupChatIcon - overwriteColor: ConversationStyle.bar.groupChatColor - iconSize: ConversationStyle.bar.groupChatSize - visible: chatRoomModel && !chatRoomModel.isOneToOne - } Item{ Layout.fillHeight: true Layout.fillWidth: true @@ -127,7 +116,7 @@ ColumnLayout { ColumnLayout{ property int maximumContentWidth: contactBar.width - -(avatar.visible?avatar.width:0)-(groupChat.visible?groupChat.width:0) + -(avatar.visible?avatar.width:0) -actionBar.width - (secureIcon.visible?secureIcon.width :0) -3*ConversationStyle.bar.spacing Layout.fillHeight: true diff --git a/linphone-app/ui/views/App/Styles/Calls/CallsWindowStyle.qml b/linphone-app/ui/views/App/Styles/Calls/CallsWindowStyle.qml index f0bd8069e..d02d535fa 100644 --- a/linphone-app/ui/views/App/Styles/Calls/CallsWindowStyle.qml +++ b/linphone-app/ui/views/App/Styles/Calls/CallsWindowStyle.qml @@ -37,16 +37,18 @@ QtObject { property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg').color property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg').color } - property QtObject newConference: QtObject { + property QtObject mergeConference: QtObject { property int iconSize: 40 - property string name : 'newConference' - property string icon : 'conference_custom' + property string name : 'mergeConference' + property string icon : 'conference_merge_custom' property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg').color property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg').color property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg').color + property color backgroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_d', icon, 'ma_d_b_bg').color property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg').color property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg').color property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg').color + property color foregroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_d', icon, 'ma_d_b_fg').color } property QtObject closeButton: QtObject{ diff --git a/linphone-sdk b/linphone-sdk index 11f72d4e2..e5c95eaed 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 11f72d4e254a2a8305a9400e38cb44f125c18873 +Subproject commit e5c95eaed5a2113cbba1ab62e8baa826abe7609c From 1c3f50704510327ffd3d21efbf44c7340ce35db6 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 3 Nov 2022 14:19:53 +0100 Subject: [PATCH 16/61] ZRTP authentication in popup. Fix PQ icons. --- linphone-app/assets/languages/da.ts | 18 +- linphone-app/assets/languages/de.ts | 18 +- linphone-app/assets/languages/en.ts | 20 ++- linphone-app/assets/languages/es.ts | 18 +- linphone-app/assets/languages/fr_FR.ts | 30 ++-- linphone-app/assets/languages/hu.ts | 18 +- linphone-app/assets/languages/it.ts | 18 +- linphone-app/assets/languages/ja.ts | 18 +- linphone-app/assets/languages/lt.ts | 18 +- linphone-app/assets/languages/pt.ts | 2 +- linphone-app/assets/languages/pt_BR.ts | 18 +- linphone-app/assets/languages/ru.ts | 18 +- linphone-app/assets/languages/sv.ts | 18 +- linphone-app/assets/languages/tr.ts | 18 +- linphone-app/assets/languages/uk.ts | 18 +- linphone-app/assets/languages/zh_CN.ts | 18 +- linphone-app/resources.qrc | 3 +- .../src/components/call/CallModel.cpp | 67 +++++-- .../src/components/call/CallModel.hpp | 17 +- .../ui/modules/Common/Form/ActionButton.qml | 2 +- .../Dialog/ZrtpTokenAuthenticationDialog.qml | 165 ++++++++++++++++++ .../ZrtpTokenAuthenticationDialogStyle.qml | 31 ++++ .../ui/modules/Linphone/Styles/qmldir | 2 + linphone-app/ui/modules/Linphone/qmldir | 1 + linphone-app/ui/views/App/Calls/Incall.js | 6 +- linphone-app/ui/views/App/Calls/Incall.qml | 31 ++-- .../ui/views/App/Calls/IncallFullscreen.qml | 34 ++-- .../App/Calls/ZrtpTokenAuthentication.qml | 139 --------------- 28 files changed, 498 insertions(+), 286 deletions(-) create mode 100644 linphone-app/ui/modules/Linphone/Dialog/ZrtpTokenAuthenticationDialog.qml create mode 100644 linphone-app/ui/modules/Linphone/Styles/Dialog/ZrtpTokenAuthenticationDialogStyle.qml delete mode 100644 linphone-app/ui/views/App/Calls/ZrtpTokenAuthentication.qml diff --git a/linphone-app/assets/languages/da.ts b/linphone-app/assets/languages/da.ts index 906a5320c..ae9f0bec4 100644 --- a/linphone-app/assets/languages/da.ts +++ b/linphone-app/assets/languages/da.ts @@ -3693,9 +3693,10 @@ Klik her: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Bekræft følgende SAS med peer. @@ -3707,12 +3708,19 @@ Klik her: <a href="%1">%1</a> Din kontakt burde sige: - deny - STOP + Later + 'Later' : Button label to do something in another time. + - accept - BEKRÆFT + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/de.ts b/linphone-app/assets/languages/de.ts index 6c354fb22..c96dc75eb 100644 --- a/linphone-app/assets/languages/de.ts +++ b/linphone-app/assets/languages/de.ts @@ -3693,9 +3693,10 @@ Klicken Sie hier: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Bestätige folgende SAS mit der Gegenstelle. @@ -3707,12 +3708,19 @@ Klicken Sie hier: <a href="%1">%1</a> Ihr Kontakt sollte sagen: - deny - ABLEHNEN + Later + 'Later' : Button label to do something in another time. + - accept - BESTÄTIGEN + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/en.ts b/linphone-app/assets/languages/en.ts index bfa73b268..80206faa0 100644 --- a/linphone-app/assets/languages/en.ts +++ b/linphone-app/assets/languages/en.ts @@ -3716,10 +3716,11 @@ Click here: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas - Confirm the following SAS with peer. + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. + To raise the security level, you can check the following codes with your correspondent. codeA @@ -3730,12 +3731,19 @@ Click here: <a href="%1">%1</a> Your contact should say: - deny - DENY + Later + 'Later' : Button label to do something in another time. + Later - accept - CONFIRM + Correct + 'Correct' : Button label to confirm a code. + Correct + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + Communication security diff --git a/linphone-app/assets/languages/es.ts b/linphone-app/assets/languages/es.ts index 50ecfe350..cb563a2c5 100644 --- a/linphone-app/assets/languages/es.ts +++ b/linphone-app/assets/languages/es.ts @@ -3693,9 +3693,10 @@ Haga clic aquí: <a href="%1">%1 </a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Confirma la siguiente SAS con el compañero @@ -3707,12 +3708,19 @@ Haga clic aquí: <a href="%1">%1 </a> Su contacto debería decir: - deny - DENEGAR + Later + 'Later' : Button label to do something in another time. + - accept - CONFIRMAR + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts index 8268ea906..1adabbc10 100644 --- a/linphone-app/assets/languages/fr_FR.ts +++ b/linphone-app/assets/languages/fr_FR.ts @@ -173,7 +173,7 @@ usernameStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). usernameStatusInvalid @@ -189,7 +189,7 @@ passwordStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). passwordStatusMissingCharacters @@ -1236,7 +1236,7 @@ URL du serveur non configurée. ephemeralNotInConference! 'Ephemeral message is only supported in conference based chat room!' - Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! + Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! Warning about not being in conference based chat room. @@ -2020,7 +2020,7 @@ Cliquez ici : <a href="%1">%1</a> newConferenceScheduleTitle 'Would you like to schedule your meeting?' : Ask about setting the meeting as scheduled. - Voulez-vous programmer cette réunion ? + Voulez-vous programmer cette réunion ? newConferenceDate @@ -2600,7 +2600,7 @@ Cliquez ici : <a href="%1">%1</a> serverTooltip - Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ + Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ bindDNLabel @@ -3546,7 +3546,7 @@ Cliquez ici : <a href="%1">%1</a> deleteTimeline 'Are you sure you want to delete and leave this timeline?' - Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? + Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? deleteTimelineTooltip @@ -3693,9 +3693,10 @@ Cliquez ici : <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Confirmez le SAS suivant avec votre interlocuteur. @@ -3707,12 +3708,19 @@ Cliquez ici : <a href="%1">%1</a> Votre interlocuteur devrait dire : - deny - REFUSER + Later + 'Later' : Button label to do something in another time. + - accept - CONFIRMER + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/hu.ts b/linphone-app/assets/languages/hu.ts index 3c48bc478..20c791ad1 100644 --- a/linphone-app/assets/languages/hu.ts +++ b/linphone-app/assets/languages/hu.ts @@ -3680,9 +3680,10 @@ Kattintson ide: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Erősítse meg a következő SAS-t a társsal. @@ -3694,12 +3695,19 @@ Kattintson ide: <a href="%1">%1</a> A kapcsolattartónak el kell mondania: - deny - Letiltás + Later + 'Later' : Button label to do something in another time. + - accept - Megerősít + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/it.ts b/linphone-app/assets/languages/it.ts index f5fb0bad0..4bed6ddc9 100644 --- a/linphone-app/assets/languages/it.ts +++ b/linphone-app/assets/languages/it.ts @@ -3693,9 +3693,10 @@ Clicca: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Confermare il seguente SAS con la controparte. @@ -3707,12 +3708,19 @@ Clicca: <a href="%1">%1</a> Il tuo contatto dovrebbe dire: - deny - RIFIUTA + Later + 'Later' : Button label to do something in another time. + - accept - CONFERMA + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/ja.ts b/linphone-app/assets/languages/ja.ts index 2c4470b7d..8403b9013 100644 --- a/linphone-app/assets/languages/ja.ts +++ b/linphone-app/assets/languages/ja.ts @@ -3680,9 +3680,10 @@ - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. ピアと次のSASを確認します。 @@ -3694,12 +3695,19 @@ 連絡先の内容は次のとおりです。 - deny - 拒否 + Later + 'Later' : Button label to do something in another time. + - accept - 確認 + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/lt.ts b/linphone-app/assets/languages/lt.ts index 0efdb74ff..b6141819c 100644 --- a/linphone-app/assets/languages/lt.ts +++ b/linphone-app/assets/languages/lt.ts @@ -3706,9 +3706,10 @@ Spustelėkite čia: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Patvirtinkite šią SAS su kolega. @@ -3720,12 +3721,19 @@ Spustelėkite čia: <a href="%1">%1</a> Jūsų kontaktas turėtų sakyti: - deny - ATMESTI + Later + 'Later' : Button label to do something in another time. + - accept - PATVIRTINTI + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/pt.ts b/linphone-app/assets/languages/pt.ts index 1f7b2d246..f7f3e89ca 100644 --- a/linphone-app/assets/languages/pt.ts +++ b/linphone-app/assets/languages/pt.ts @@ -2881,7 +2881,7 @@ - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas diff --git a/linphone-app/assets/languages/pt_BR.ts b/linphone-app/assets/languages/pt_BR.ts index 6480d0a71..d64a69244 100644 --- a/linphone-app/assets/languages/pt_BR.ts +++ b/linphone-app/assets/languages/pt_BR.ts @@ -3693,9 +3693,10 @@ Clique aqui: <a href="%1">%1 </a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Confirme o seguinte SAS com peer. @@ -3707,12 +3708,19 @@ Clique aqui: <a href="%1">%1 </a> Seu contato deve dizer: - deny - NEGAR + Later + 'Later' : Button label to do something in another time. + - accept - CONFIRMAR + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/ru.ts b/linphone-app/assets/languages/ru.ts index 37bc2b37a..e7a848531 100644 --- a/linphone-app/assets/languages/ru.ts +++ b/linphone-app/assets/languages/ru.ts @@ -3706,9 +3706,10 @@ - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Подтвердите следующую строку аутентификации с контактом. @@ -3720,12 +3721,19 @@ Ваш контакт должен сказать: - deny - ОТКЛОНИТЬ + Later + 'Later' : Button label to do something in another time. + - accept - ПОДТВЕРДИТЬ + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/sv.ts b/linphone-app/assets/languages/sv.ts index f0e325110..9961684a6 100644 --- a/linphone-app/assets/languages/sv.ts +++ b/linphone-app/assets/languages/sv.ts @@ -3693,9 +3693,10 @@ Klicka här: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Bekräfta följande SAS med partner @@ -3707,12 +3708,19 @@ Klicka här: <a href="%1">%1</a> Din kontaktperson bör säga: - deny - FÖRNEKA + Later + 'Later' : Button label to do something in another time. + - accept - BEKRÄFTA + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/tr.ts b/linphone-app/assets/languages/tr.ts index 51f897499..06654ba07 100644 --- a/linphone-app/assets/languages/tr.ts +++ b/linphone-app/assets/languages/tr.ts @@ -3680,9 +3680,10 @@ Buraya tıklayın: <a href="%1">%1</a> - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Aşağıdaki kısa yetkilendirme dizgesini eşinizle onaylayın. @@ -3694,12 +3695,19 @@ Buraya tıklayın: <a href="%1">%1</a> Kişiniz şunu söylemeli: - deny - REDDET + Later + 'Later' : Button label to do something in another time. + - accept - ONAYLA + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/uk.ts b/linphone-app/assets/languages/uk.ts index aab92854e..5d6aa1fe3 100644 --- a/linphone-app/assets/languages/uk.ts +++ b/linphone-app/assets/languages/uk.ts @@ -3706,9 +3706,10 @@ - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. Підтвердіть такий рядок автентифікації з контактом. @@ -3720,12 +3721,19 @@ Ваш контакт повинен сказати: - deny - ВІДХИЛИТИ + Later + 'Later' : Button label to do something in another time. + - accept - СХВАЛИТИ + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/assets/languages/zh_CN.ts b/linphone-app/assets/languages/zh_CN.ts index 88d9978f9..9ba77d1a6 100644 --- a/linphone-app/assets/languages/zh_CN.ts +++ b/linphone-app/assets/languages/zh_CN.ts @@ -3680,9 +3680,10 @@ - ZrtpTokenAuthentication + ZrtpTokenAuthenticationDialog confirmSas + 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. 与同行确认以下 SAS。 @@ -3694,12 +3695,19 @@ 您的联系人应该说: - deny - 否认 + Later + 'Later' : Button label to do something in another time. + - accept - 确认 + Correct + 'Correct' : Button label to confirm a code. + + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc index 8cc39f5fa..a5ff5052e 100644 --- a/linphone-app/resources.qrc +++ b/linphone-app/resources.qrc @@ -349,6 +349,7 @@ ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml ui/modules/Linphone/Dialog/SipAddressDialog.qml ui/modules/Linphone/Dialog/MultimediaParametersDialog.qml + ui/modules/Linphone/Dialog/ZrtpTokenAuthenticationDialog.qml ui/modules/Linphone/File/FileView.qml ui/modules/Linphone/History/History.qml ui/modules/Linphone/History/History.js @@ -394,6 +395,7 @@ ui/modules/Linphone/Styles/Dialog/MultimediaParametersDialogStyle.qml ui/modules/Linphone/Styles/Dialog/OnlineInstallerDialogStyle.qml ui/modules/Linphone/Styles/Dialog/SipAddressDialogStyle.qml + ui/modules/Linphone/Styles/Dialog/ZrtpTokenAuthenticationDialogStyle.qml ui/modules/Linphone/Styles/History/HistoryStyle.qml ui/modules/Linphone/Styles/Menus/SipAddressesMenuStyle.qml ui/modules/Linphone/Styles/Menus/IncallMenuStyle.qml @@ -441,7 +443,6 @@ ui/views/App/Calls/IncallGrid.qml ui/views/App/Calls/IncomingCall.qml ui/views/App/Calls/WaitingRoom.qml - ui/views/App/Calls/ZrtpTokenAuthentication.qml ui/views/App/Dialog/NewConference.qml ui/views/App/Main/Assistant/ActivateAppSipAccountWithEmail.qml ui/views/App/Main/Assistant/ActivateAppSipAccountWithPhoneNumber.qml diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index 63a8ed4a3..63225c720 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -61,6 +61,9 @@ CallModel::CallModel (shared_ptr call){ SettingsModel *settings = coreManager->getSettingsModel(); connect(this, &CallModel::callIdChanged, this, &CallModel::chatRoomModelChanged);// When the call Id change, the chat room change. + connect(this, &CallModel::encryptionChanged, this, &CallModel::securityUpdated); + connect(this, &CallModel::isPQZrtpChanged, this, &CallModel::securityUpdated); + mCall = call; if(mCall) mCall->setData("call-model", *this); @@ -70,6 +73,9 @@ CallModel::CallModel (shared_ptr call){ connectTo(mCallListener.get()); mCall->addListener(mCallListener); auto callParams = mCall->getParams(); + auto currentParams = mCall->getCurrentParams(); + if(currentParams) + mEncryption = static_cast(currentParams->getMediaEncryption()); mConferenceVideoLayout = LinphoneEnums::fromLinphone(callParams->getConferenceVideoLayout()); if(mConferenceVideoLayout == LinphoneEnums::ConferenceLayoutGrid && !callParams->videoEnabled()) mConferenceVideoLayout = LinphoneEnums::ConferenceLayoutAudioOnly; @@ -80,6 +86,7 @@ CallModel::CallModel (shared_ptr call){ settings->setCameraMode(settings->getActiveSpeakerCameraMode()); }else settings->setCameraMode(settings->getCallCameraMode()); + } // Deal with auto-answer. @@ -295,6 +302,8 @@ void CallModel::updateStats (const shared_ptr &callSt break; case linphone::StreamType::Audio: + if( callStats) + isPQZrtp(callStats->isZrtpKeyAgreementAlgoPostQuantum() ? CallPQStateOn : CallPQStateOff); updateStats(callStats, mAudioStats); updateEncrypionStats(callStats, mEncryptionStats); break; @@ -470,8 +479,10 @@ void CallModel::stopRecording () { // ----------------------------------------------------------------------------- void CallModel::handleCallEncryptionChanged (const shared_ptr &call) { - if (call == mCall) - emit securityUpdated(); + if (call == mCall){ + if(!setEncryption(static_cast(mCall->getCurrentParams()->getMediaEncryption()))) + emit securityUpdated(); + } } void CallModel::handleCallStateChanged (const shared_ptr &call, linphone::Call::State state) { @@ -504,6 +515,7 @@ void CallModel::handleCallStateChanged (const shared_ptr &call, mPausedByRemote = false; updateConferenceVideoLayout(); setCallId(QString::fromStdString(mCall->getCallLog()->getCallId())); + updateEncryption(); break; } case linphone::Call::State::Connected: getConferenceSharedModel(); @@ -1063,19 +1075,33 @@ void CallModel::updateConferenceVideoLayout(){ // ----------------------------------------------------------------------------- CallModel::CallEncryption CallModel::getEncryption () const { - if(mCall) - return static_cast(mCall->getCurrentParams()->getMediaEncryption()); - else - return CallEncryptionNone; + return mEncryption; +} + +bool CallModel::setEncryption(const CallModel::CallEncryption& encryption){ + if( encryption != mEncryption){ + mEncryption = encryption; + emit encryptionChanged(); + return true; + }else + return false; +} + +void CallModel::updateEncryption(){ + if(mCall){ + auto currentParams = mCall->getCurrentParams(); + if( currentParams){ + setEncryption(static_cast(currentParams->getMediaEncryption())); + } + } } bool CallModel::isSecured () const { if(mCall){ - shared_ptr params = mCall->getCurrentParams(); - linphone::MediaEncryption encryption = params->getMediaEncryption(); - return ( - encryption == linphone::MediaEncryption::ZRTP && mCall->getAuthenticationTokenVerified() - ) || encryption == linphone::MediaEncryption::SRTP || encryption == linphone::MediaEncryption::DTLS; + auto encryption = getEncryption(); + return (encryption == CallEncryptionZrtp && mCall->getAuthenticationTokenVerified()) + || encryption == CallEncryptionSrtp + || encryption == CallEncryptionDtls; }else return false; } @@ -1109,16 +1135,16 @@ QString CallModel::getRemoteSas () const { QString CallModel::getSecuredString (const shared_ptr &callStats) const { if(mCall){ - switch (mCall->getCurrentParams()->getMediaEncryption()) { - case linphone::MediaEncryption::SRTP: + switch (getEncryption()) { + case CallEncryptionSrtp: return QStringLiteral("SRTP"); - case linphone::MediaEncryption::ZRTP: - return (callStats && callStats->isZrtpKeyAgreementAlgoPostQuantum() || (!callStats && CoreManager::getInstance()->getCore()->getPostQuantumAvailable()) ) + case CallEncryptionZrtp: + return (callStats && callStats->isZrtpKeyAgreementAlgoPostQuantum() || (!callStats && mIsPQZrtp == CallPQStateOn) ) ? QStringLiteral("Post Quantum ZRTP") : QStringLiteral("ZRTP"); - case linphone::MediaEncryption::DTLS: + case CallEncryptionDtls: return QStringLiteral("DTLS"); - case linphone::MediaEncryption::None: + case CallEncryptionNone: break; } } @@ -1245,6 +1271,13 @@ void CallModel::updateEncrypionStats (const shared_ptr call); ~CallModel (); @@ -220,6 +228,8 @@ signals: void statusChanged (CallStatus status); void videoRequested (); void securityUpdated (); + void encryptionChanged(); + void isPQZrtpChanged(); void speakerVolumeGainChanged (float volume); void microVolumeGainChanged (float volume); @@ -283,6 +293,8 @@ public: bool getSnapshotEnabled() const; CallEncryption getEncryption () const; + bool setEncryption(const CallModel::CallEncryption& encryption);// true if changed + void updateEncryption(); bool isSecured () const; QString getLocalSas () const; @@ -295,6 +307,7 @@ public: QVariantList getEncryptionStats () const; void updateStats (const std::shared_ptr &callStats, QVariantList &statsList); void updateEncrypionStats (const std::shared_ptr &callStats, QVariantList &statsList); + void isPQZrtp(const CallPQState& isPQ); QString iceStateToString (linphone::IceState state) const; @@ -312,6 +325,8 @@ private: void connectTo(CallListener * listener); bool mIsInConference = false; + CallPQState mIsPQZrtp = CallPQStateNone; + CallEncryption mEncryption = CallEncryptionNone; bool mEndByUser = false; bool mPausedByRemote = false; diff --git a/linphone-app/ui/modules/Common/Form/ActionButton.qml b/linphone-app/ui/modules/Common/Form/ActionButton.qml index 4b2b20ae9..ba9856154 100644 --- a/linphone-app/ui/modules/Common/Form/ActionButton.qml +++ b/linphone-app/ui/modules/Common/Form/ActionButton.qml @@ -330,7 +330,7 @@ Item { hoverEnabled: true acceptedButtons: Qt.NoButton cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor - visible: !iconIsCustom + visible: !iconIsCustom && !tooltip.visible } } diff --git a/linphone-app/ui/modules/Linphone/Dialog/ZrtpTokenAuthenticationDialog.qml b/linphone-app/ui/modules/Linphone/Dialog/ZrtpTokenAuthenticationDialog.qml new file mode 100644 index 000000000..a0055accc --- /dev/null +++ b/linphone-app/ui/modules/Linphone/Dialog/ZrtpTokenAuthenticationDialog.qml @@ -0,0 +1,165 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 + +import Common 1.0 +import Linphone 1.0 + +import Linphone.Styles 1.0 + +// ============================================================================= +DialogPlus { + id: mainItem + + property var addressSelectedCallback + property var chatRoomSelectedCallback + + property var call + property alias localSas: localSasText.text + property alias remoteSas : remoteSasText.text + + buttons: [ + TextButtonA { + //: 'Later' : Button label to do something in another time. + text: qsTr('Later') + onClicked: { + if(mainItem.call) mainItem.call.verifyAuthenticationToken(false) + mainItem.exit(0) + } + }, + + TextButtonC { + //: 'Correct' : Button label to confirm a code. + text: qsTr('Correct') + onClicked: { + if(mainItem.call) mainItem.call.verifyAuthenticationToken(true) + mainItem.exit(1) + } + } + ] + + + + buttonsAlignment: Qt.AlignCenter + height: 400 + width: 350 + + radius: 10 + onCallChanged: if(!call) exit(0) + Component.onCompleted: if( !localSas || !remoteSas) mainItem.exit(0) + + ColumnLayout { + id:columnLayout + // --------------------------------------------------------------------------- + anchors.fill: parent + Layout.fillWidth: true + + Icon{ + Layout.alignment: Qt.AlignHCenter + Layout.bottomMargin: 5 + icon: mainItem.call.isPQZrtp === CallModel.CallPQStateOn + ? ZrtpTokenAuthenticationDialogStyle.pqIcon + : mainItem.call.isPQZrtp === CallModel.CallPQStateOff + ? ZrtpTokenAuthenticationDialogStyle.icon + : ZrtpTokenAuthenticationDialogStyle.secureIcon + iconSize: ZrtpTokenAuthenticationDialogStyle.iconSize + } + + // --------------------------------------------------------------------------- + // Main text. + // --------------------------------------------------------------------------- + Text { + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + //: 'Communication security' : Title of popup for ZRTP confirmation. + text: qsTr('title') + + color: ZrtpTokenAuthenticationDialogStyle.text.colorA + wrapMode: Text.WordWrap + + font { + bold: true + pointSize: ZrtpTokenAuthenticationDialogStyle.text.titlePointSize + } + } + Text { + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + //: 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. + text: qsTr('confirmSas') + + color: ZrtpTokenAuthenticationDialogStyle.text.colorA + wrapMode: Text.WordWrap + + font.pointSize: ZrtpTokenAuthenticationDialogStyle.text.pointSize + } + + // --------------------------------------------------------------------------- + // Rules. + // --------------------------------------------------------------------------- + + ColumnLayout { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + + spacing: ZrtpTokenAuthenticationDialogStyle.text.wordsSpacing + + Text { + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: ZrtpTokenAuthenticationDialogStyle.text.colorA + font.pointSize: ZrtpTokenAuthenticationDialogStyle.text.pointSize + text: qsTr('codeA') + } + + Text { + id: localSasText + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: ZrtpTokenAuthenticationDialogStyle.text.colorB + + font { + bold: true + pointSize: ZrtpTokenAuthenticationDialogStyle.text.sasPointSize + } + + text: mainItem.call?mainItem.call.localSas:'' + } + + Text { + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: ZrtpTokenAuthenticationDialogStyle.text.colorA + font.pointSize: ZrtpTokenAuthenticationDialogStyle.text.pointSize + text: qsTr('codeB') + } + + Text { + id: remoteSasText + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: ZrtpTokenAuthenticationDialogStyle.text.colorB + + font { + bold: true + pointSize: ZrtpTokenAuthenticationDialogStyle.text.sasPointSize + } + + text: mainItem.call?mainItem.call.remoteSas:'' + } + } + + } +} diff --git a/linphone-app/ui/modules/Linphone/Styles/Dialog/ZrtpTokenAuthenticationDialogStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Dialog/ZrtpTokenAuthenticationDialogStyle.qml new file mode 100644 index 000000000..bf9943a63 --- /dev/null +++ b/linphone-app/ui/modules/Linphone/Styles/Dialog/ZrtpTokenAuthenticationDialogStyle.qml @@ -0,0 +1,31 @@ +pragma Singleton +import QtQml 2.2 + +import Units 1.0 +import ColorsList 1.0 + +// ============================================================================= + +QtObject { + property string sectionName : 'ZrtpTokenAuthenticationDialog' + + property int height: 50 + property string pqIcon: 'secure_pq_zrtp' + property string secureIcon: 'secure_on' + property string icon: 'secure_level_2' + + property int iconSize: 60 + + property QtObject buttons: QtObject { + property int spacing: 10 + } + + property QtObject text: QtObject { + property color colorA: ColorsList.add(sectionName+'_zrtp_text_a', 'j').color + property color colorB: ColorsList.add(sectionName+'_zrtp_text_b', 's').color + property int pointSize: Units.dp * 10 + property int titlePointSize: Units.dp * 12 + property int sasPointSize: Units.dp * 13 + property int wordsSpacing: 5 + } +} diff --git a/linphone-app/ui/modules/Linphone/Styles/qmldir b/linphone-app/ui/modules/Linphone/Styles/qmldir index e4e244429..1194c8319 100644 --- a/linphone-app/ui/modules/Linphone/Styles/qmldir +++ b/linphone-app/ui/modules/Linphone/Styles/qmldir @@ -34,6 +34,8 @@ singleton ContactStyle 1.0 Contact/ContactStyle.qml singleton MultimediaParametersDialogStyle 1.0 Dialog/MultimediaParametersDialogStyle.qml singleton OnlineInstallerDialogStyle 1.0 Dialog/OnlineInstallerDialogStyle.qml singleton SipAddressDialogStyle 1.0 Dialog/SipAddressDialogStyle.qml +singleton ZrtpTokenAuthenticationDialogStyle 1.0 Dialog/ZrtpTokenAuthenticationDialogStyle.qml + singleton HistoryStyle 1.0 History/HistoryStyle.qml diff --git a/linphone-app/ui/modules/Linphone/qmldir b/linphone-app/ui/modules/Linphone/qmldir index 768e7a5cd..6355ee26b 100644 --- a/linphone-app/ui/modules/Linphone/qmldir +++ b/linphone-app/ui/modules/Linphone/qmldir @@ -36,6 +36,7 @@ ContactDescription 1.0 Contact/ContactDescription.qml SipAddressDialog 1.0 Dialog/SipAddressDialog.qml MultimediaParametersDialog 1.0 Dialog/MultimediaParametersDialog.qml +ZrtpTokenAuthenticationDialog 1.0 Dialog/ZrtpTokenAuthenticationDialog.qml FileView 1.0 File/FileView.qml diff --git a/linphone-app/ui/views/App/Calls/Incall.js b/linphone-app/ui/views/App/Calls/Incall.js index 9f0f33eaa..66412755a 100644 --- a/linphone-app/ui/views/App/Calls/Incall.js +++ b/linphone-app/ui/views/App/Calls/Incall.js @@ -100,12 +100,12 @@ function handleVideoRequested (call) { }) } -function makeReadableSecuredString (securedString) { - if (!securedString || !securedString.length) { +function makeReadableSecuredString (isSecured, secureString) { + if (!isSecured) { return qsTr('callNotSecured') } - return qsTr('securedStringFormat').replace('%1', securedString) + return qsTr('securedStringFormat').replace('%1', secureString) } function openCallStatistics () { diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index 962fd6337..cd616f849 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -57,6 +57,7 @@ Rectangle { } onParticipantCountChanged: Qt.callLater(function (){delayMessageBanner.restart()}) onIsReadyChanged: Qt.callLater(function (){delayMessageBanner.restart()}) + // --------------------------------------------------------------------------- color: IncallStyle.backgroundColor @@ -69,6 +70,9 @@ Rectangle { delayMessageBanner.restart() } onVideoRequested: Logic.handleVideoRequested(callModel) + onEncryptionChanged: if(!callModel.isSecured && callModel.encryption === CallModel.CallEncryptionZrtp){ + window.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel}) + } } // --------------------------------------------------------------------------- Rectangle{ @@ -293,7 +297,7 @@ Rectangle { anchors.top: featuresRow.bottom anchors.left: parent.left anchors.right: parent.right - anchors.bottom: zrtp.top + anchors.bottom: actionsButtons.top anchors.topMargin: 15 anchors.bottomMargin: 20 @@ -372,23 +376,6 @@ Rectangle { } } } - Loader{ - id: zrtp - active: call && !call.isSecured && call.encryption === CallModel.CallEncryptionZrtp - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: actionsButtons.top - anchors.leftMargin: CallStyle.container.margins - anchors.rightMargin: CallStyle.container.margins - anchors.bottomMargin: CallStyle.container.margins - height: active ? implicitHeight : 0 - sourceComponent:Component{ - ZrtpTokenAuthentication { - call: callModel - z: Constants.zPopup - onClose: {zrtp.active = false} - } - } - } // ------------------------------------------------------------------------- // Action Buttons. // ------------------------------------------------------------------------- @@ -406,14 +393,16 @@ Rectangle { backgroundRadius: width/2 colorSet: callModel.isSecured - ? SettingsModel.isPostQuantumAvailable && callModel.encryption === CallModel.CallEncryptionZrtp + ? SettingsModel.isPostQuantumAvailable && callModel.encryption === CallModel.CallEncryptionZrtp && callModel.isPQZrtp == CallModel.CallPQStateOn ? IncallStyle.buttons.postQuantumSecure : IncallStyle.buttons.secure : IncallStyle.buttons.unsecure - onClicked: zrtp.active =(callModel.encryption === CallModel.CallEncryptionZrtp) + onClicked: if(callModel.encryption === CallModel.CallEncryptionZrtp){ + window.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel}) + } - tooltipText: Logic.makeReadableSecuredString(callModel.securedString) + tooltipText: Logic.makeReadableSecuredString(callModel.isSecured, callModel.securedString) } RowLayout{ visible: callModel.remoteRecording diff --git a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml index 20d9e4381..61c223364 100644 --- a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml +++ b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml @@ -83,6 +83,9 @@ Window { onCameraFirstFrameReceived: Logic.handleCameraFirstFrameReceived(width, height) onStatusChanged: Logic.handleStatusChanged (status, conference._fullscreen) onVideoRequested: Logic.handleVideoRequested(callModel) + onEncryptionChanged: if(!callModel.isSecured && callModel.encryption === CallModel.CallEncryptionZrtp){ + window.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel}) + } } // --------------------------------------------------------------------------- @@ -259,7 +262,7 @@ Window { anchors.top: featuresRow.bottom anchors.left: parent.left anchors.right: parent.right - anchors.bottom: zrtp.top + anchors.bottom: actionsButtons.top anchors.topMargin: window.hideButtons ? 0 : 15 anchors.bottomMargin: window.hideButtons ? 0 : 20 @@ -336,22 +339,6 @@ Window { // ------------------------------------------------------------------------- // Action Buttons. // ------------------------------------------------------------------------- - - Loader{ - id: zrtp - active: call && !call.isSecured && call.encryption === CallModel.CallEncryptionZrtp - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: actionsButtons.top - anchors.margins: CallStyle.container.margins - height: active ? implicitHeight : 0 - sourceComponent:Component{ - ZrtpTokenAuthentication { - call: callModel - z: Constants.zPopup - onClose: {zrtp.active = false} - } - } - } // Security ActionButton{ id: securityButton @@ -362,13 +349,20 @@ Window { height: IncallStyle.buttons.secure.buttonSize width: height isCustom: true + iconIsCustom: ! (callModel.isSecured && SettingsModel.isPostQuantumAvailable && callModel.encryption === CallModel.CallEncryptionZrtp) backgroundRadius: width/2 - colorSet: callModel.isSecured ? IncallStyle.buttons.secure : IncallStyle.buttons.unsecure + colorSet: callModel.isSecured + ? SettingsModel.isPostQuantumAvailable && callModel.encryption === CallModel.CallEncryptionZrtp && callModel.isPQZrtp == CallModel.CallPQStateOn + ? IncallStyle.buttons.postQuantumSecure + : IncallStyle.buttons.secure + : IncallStyle.buttons.unsecure - onClicked: zrtp.active = (callModel.encryption === CallModel.CallEncryptionZrtp) + onClicked: if(callModel.encryption === CallModel.CallEncryptionZrtp){ + window.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel}) + } - tooltipText: Logic.makeReadableSecuredString(callModel.securedString) + tooltipText: Logic.makeReadableSecuredString(callModel.isSecured, callModel.securedString) } RowLayout{ visible: callModel && callModel.remoteRecording diff --git a/linphone-app/ui/views/App/Calls/ZrtpTokenAuthentication.qml b/linphone-app/ui/views/App/Calls/ZrtpTokenAuthentication.qml deleted file mode 100644 index 75f7cff09..000000000 --- a/linphone-app/ui/views/App/Calls/ZrtpTokenAuthentication.qml +++ /dev/null @@ -1,139 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Layouts 1.3 - -import Common 1.0 -import Linphone 1.0 - -import App.Styles 1.0 - -// ============================================================================= -Rectangle{ - id: zrtp - property var call - property alias localSas: localSasText.text - property alias remoteSas : remoteSasText.text - - signal close() - color:"transparent" - - implicitWidth: columnLayout.implicitWidth - implicitHeight: columnLayout.implicitHeight+CallStyle.container.margins - - radius: 10 - Component.onCompleted: if( !localSas || !remoteSas) zrtp.close() - - ColumnLayout { - id:columnLayout - // --------------------------------------------------------------------------- - - Layout.fillWidth: true - anchors.bottom: parent.bottom - - Icon{ - Layout.alignment: Qt.AlignHCenter - Layout.bottomMargin: 5 - visible: SettingsModel.isPostQuantumAvailable - icon: CallStyle.zrtpArea.pqIcon - iconSize: CallStyle.zrtpArea.iconSize - } - - // --------------------------------------------------------------------------- - // Main text. - // --------------------------------------------------------------------------- - - Text { - Layout.fillWidth: true - - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - text: qsTr('confirmSas') - - color: CallStyle.zrtpArea.text.colorA - elide: Text.ElideRight - - font { - bold: true - pointSize: CallStyle.zrtpArea.text.pointSize - } - } - - // --------------------------------------------------------------------------- - // Rules. - // --------------------------------------------------------------------------- - - Row { - Layout.alignment: Qt.AlignHCenter - - spacing: CallStyle.zrtpArea.text.wordsSpacing - - Text { - color: CallStyle.zrtpArea.text.colorA - font.pointSize: CallStyle.zrtpArea.text.pointSize - text: qsTr('codeA') - } - - Text { - id: localSasText - color: CallStyle.zrtpArea.text.colorB - - font { - bold: true - pointSize: CallStyle.zrtpArea.text.pointSize - } - - text: zrtp.call?zrtp.call.localSas:'' - } - - Text { - color: CallStyle.zrtpArea.text.colorA - font.pointSize: CallStyle.zrtpArea.text.pointSize - text: '-' - } - - Text { - color: CallStyle.zrtpArea.text.colorA - font.pointSize: CallStyle.zrtpArea.text.pointSize - text: qsTr('codeB') - } - - Text { - id: remoteSasText - color: CallStyle.zrtpArea.text.colorB - - font { - bold: true - pointSize: CallStyle.zrtpArea.text.pointSize - } - - text: zrtp.call?zrtp.call.remoteSas:'' - } - } - - // --------------------------------------------------------------------------- - // Buttons. - // --------------------------------------------------------------------------- - - Row { - Layout.alignment: Qt.AlignHCenter - - spacing: CallStyle.zrtpArea.buttons.spacing - - TextButtonA { - text: qsTr('deny') - onClicked: { - zrtp.call.verifyAuthenticationToken(false) - zrtp.close() - } - } - - TextButtonB { - text: qsTr('accept') - onClicked: { - zrtp.call.verifyAuthenticationToken(true) - zrtp.close() - } - } - } - } -} From c7f98896d04b915d7c2cec214258bdf1c588ad87 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 3 Nov 2022 15:33:25 +0000 Subject: [PATCH 17/61] Translated using Weblate (cherry picked from commit d2d605cb8252d8829e213141e06395ad5118c1e6) --- linphone-app/assets/languages/da.ts | 6 +++--- linphone-app/assets/languages/de.ts | 6 +++--- linphone-app/assets/languages/es.ts | 6 +++--- linphone-app/assets/languages/fr_FR.ts | 20 ++++++++++---------- linphone-app/assets/languages/hu.ts | 6 +++--- linphone-app/assets/languages/it.ts | 6 +++--- linphone-app/assets/languages/ja.ts | 6 +++--- linphone-app/assets/languages/lt.ts | 6 +++--- linphone-app/assets/languages/pt.ts | 18 ++++++++++++++++++ linphone-app/assets/languages/pt_BR.ts | 6 +++--- linphone-app/assets/languages/ru.ts | 6 +++--- linphone-app/assets/languages/sv.ts | 6 +++--- linphone-app/assets/languages/tr.ts | 6 +++--- linphone-app/assets/languages/uk.ts | 6 +++--- linphone-app/assets/languages/zh_CN.ts | 6 +++--- 15 files changed, 67 insertions(+), 49 deletions(-) diff --git a/linphone-app/assets/languages/da.ts b/linphone-app/assets/languages/da.ts index ae9f0bec4..9aa50fa99 100644 --- a/linphone-app/assets/languages/da.ts +++ b/linphone-app/assets/languages/da.ts @@ -3710,17 +3710,17 @@ Klik her: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Senere Correct 'Correct' : Button label to confirm a code. - + Korrigere title 'Communication security' : Title of popup for ZRTP confirmation. - + Kommunikationssikkerhed diff --git a/linphone-app/assets/languages/de.ts b/linphone-app/assets/languages/de.ts index c96dc75eb..695bad434 100644 --- a/linphone-app/assets/languages/de.ts +++ b/linphone-app/assets/languages/de.ts @@ -3710,17 +3710,17 @@ Klicken Sie hier: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Später Correct 'Correct' : Button label to confirm a code. - + Richtig title 'Communication security' : Title of popup for ZRTP confirmation. - + Kommunikationssicherheit diff --git a/linphone-app/assets/languages/es.ts b/linphone-app/assets/languages/es.ts index cb563a2c5..659fa342d 100644 --- a/linphone-app/assets/languages/es.ts +++ b/linphone-app/assets/languages/es.ts @@ -3710,17 +3710,17 @@ Haga clic aquí: <a href="%1">%1 </a> Later 'Later' : Button label to do something in another time. - + Tarde Correct 'Correct' : Button label to confirm a code. - + Correcto title 'Communication security' : Title of popup for ZRTP confirmation. - + Seguridad de la comunicación diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts index 1adabbc10..64d39b8da 100644 --- a/linphone-app/assets/languages/fr_FR.ts +++ b/linphone-app/assets/languages/fr_FR.ts @@ -173,7 +173,7 @@ usernameStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). usernameStatusInvalid @@ -189,7 +189,7 @@ passwordStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). passwordStatusMissingCharacters @@ -1236,7 +1236,7 @@ URL du serveur non configurée. ephemeralNotInConference! 'Ephemeral message is only supported in conference based chat room!' - Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! + Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! Warning about not being in conference based chat room. @@ -2020,7 +2020,7 @@ Cliquez ici : <a href="%1">%1</a> newConferenceScheduleTitle 'Would you like to schedule your meeting?' : Ask about setting the meeting as scheduled. - Voulez-vous programmer cette réunion ? + Voulez-vous programmer cette réunion ? newConferenceDate @@ -2600,7 +2600,7 @@ Cliquez ici : <a href="%1">%1</a> serverTooltip - Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ + Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ bindDNLabel @@ -3546,7 +3546,7 @@ Cliquez ici : <a href="%1">%1</a> deleteTimeline 'Are you sure you want to delete and leave this timeline?' - Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? + Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? deleteTimelineTooltip @@ -3697,7 +3697,7 @@ Cliquez ici : <a href="%1">%1</a> confirmSas 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check. - Confirmez le SAS suivant avec votre interlocuteur. + Pour accroitre le niveau de sécurité, vous pouvez confirmer les codes suivants avec votre interlocuteur. codeA @@ -3710,17 +3710,17 @@ Cliquez ici : <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Plus tard Correct 'Correct' : Button label to confirm a code. - + Correct title 'Communication security' : Title of popup for ZRTP confirmation. - + Sécurité des communications diff --git a/linphone-app/assets/languages/hu.ts b/linphone-app/assets/languages/hu.ts index 20c791ad1..9a20f7ba0 100644 --- a/linphone-app/assets/languages/hu.ts +++ b/linphone-app/assets/languages/hu.ts @@ -3697,17 +3697,17 @@ Kattintson ide: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Később Correct 'Correct' : Button label to confirm a code. - + Helyes title 'Communication security' : Title of popup for ZRTP confirmation. - + Kommunikációs biztonság diff --git a/linphone-app/assets/languages/it.ts b/linphone-app/assets/languages/it.ts index 4bed6ddc9..36fe51dec 100644 --- a/linphone-app/assets/languages/it.ts +++ b/linphone-app/assets/languages/it.ts @@ -3710,17 +3710,17 @@ Clicca: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Poi Correct 'Correct' : Button label to confirm a code. - + Corretto title 'Communication security' : Title of popup for ZRTP confirmation. - + Sicurezza delle comunicazioni diff --git a/linphone-app/assets/languages/ja.ts b/linphone-app/assets/languages/ja.ts index 8403b9013..d8bce574f 100644 --- a/linphone-app/assets/languages/ja.ts +++ b/linphone-app/assets/languages/ja.ts @@ -3697,17 +3697,17 @@ Later 'Later' : Button label to do something in another time. - + 後で Correct 'Correct' : Button label to confirm a code. - + title 'Communication security' : Title of popup for ZRTP confirmation. - + 通信セキュリティ diff --git a/linphone-app/assets/languages/lt.ts b/linphone-app/assets/languages/lt.ts index b6141819c..360c55639 100644 --- a/linphone-app/assets/languages/lt.ts +++ b/linphone-app/assets/languages/lt.ts @@ -3723,17 +3723,17 @@ Spustelėkite čia: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Vėliau Correct 'Correct' : Button label to confirm a code. - + Teisingas title 'Communication security' : Title of popup for ZRTP confirmation. - + Ryšių saugumas diff --git a/linphone-app/assets/languages/pt.ts b/linphone-app/assets/languages/pt.ts index f7f3e89ca..9294027e0 100644 --- a/linphone-app/assets/languages/pt.ts +++ b/linphone-app/assets/languages/pt.ts @@ -3805,4 +3805,22 @@ + + + + Later + 'Later' : Button label to do something in another time. + Mais tarde + + + Correct + 'Correct' : Button label to confirm a code. + Correcto + + + title + 'Communication security' : Title of popup for ZRTP confirmation. + Segurança de comunicação + + diff --git a/linphone-app/assets/languages/pt_BR.ts b/linphone-app/assets/languages/pt_BR.ts index d64a69244..96a09ec62 100644 --- a/linphone-app/assets/languages/pt_BR.ts +++ b/linphone-app/assets/languages/pt_BR.ts @@ -3710,17 +3710,17 @@ Clique aqui: <a href="%1">%1 </a> Later 'Later' : Button label to do something in another time. - + Tarde Correct 'Correct' : Button label to confirm a code. - + Correcto title 'Communication security' : Title of popup for ZRTP confirmation. - + Segurança das comunicações diff --git a/linphone-app/assets/languages/ru.ts b/linphone-app/assets/languages/ru.ts index e7a848531..2509e66ac 100644 --- a/linphone-app/assets/languages/ru.ts +++ b/linphone-app/assets/languages/ru.ts @@ -3723,17 +3723,17 @@ Later 'Later' : Button label to do something in another time. - + Позже Correct 'Correct' : Button label to confirm a code. - + Правильный title 'Communication security' : Title of popup for ZRTP confirmation. - + Безопасность связи diff --git a/linphone-app/assets/languages/sv.ts b/linphone-app/assets/languages/sv.ts index 9961684a6..0f5b48209 100644 --- a/linphone-app/assets/languages/sv.ts +++ b/linphone-app/assets/languages/sv.ts @@ -3710,17 +3710,17 @@ Klicka här: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Senare Correct 'Correct' : Button label to confirm a code. - + Korrigera title 'Communication security' : Title of popup for ZRTP confirmation. - + Kommunikationssäkerhet diff --git a/linphone-app/assets/languages/tr.ts b/linphone-app/assets/languages/tr.ts index 06654ba07..d4ab8547c 100644 --- a/linphone-app/assets/languages/tr.ts +++ b/linphone-app/assets/languages/tr.ts @@ -3697,17 +3697,17 @@ Buraya tıklayın: <a href="%1">%1</a> Later 'Later' : Button label to do something in another time. - + Sonra Correct 'Correct' : Button label to confirm a code. - + Haklı title 'Communication security' : Title of popup for ZRTP confirmation. - + İletişim güvenliği diff --git a/linphone-app/assets/languages/uk.ts b/linphone-app/assets/languages/uk.ts index 5d6aa1fe3..603506eca 100644 --- a/linphone-app/assets/languages/uk.ts +++ b/linphone-app/assets/languages/uk.ts @@ -3723,17 +3723,17 @@ Later 'Later' : Button label to do something in another time. - + Пізніше Correct 'Correct' : Button label to confirm a code. - + Правильний title 'Communication security' : Title of popup for ZRTP confirmation. - + Безпека зв'язку diff --git a/linphone-app/assets/languages/zh_CN.ts b/linphone-app/assets/languages/zh_CN.ts index 9ba77d1a6..faa1aa2d5 100644 --- a/linphone-app/assets/languages/zh_CN.ts +++ b/linphone-app/assets/languages/zh_CN.ts @@ -3697,17 +3697,17 @@ Later 'Later' : Button label to do something in another time. - + 稍后 Correct 'Correct' : Button label to confirm a code. - + 正确 title 'Communication security' : Title of popup for ZRTP confirmation. - + 通讯保安 From d68b0d32a25b94868b483f71e3e4183fe368e3b1 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Fri, 4 Nov 2022 09:05:53 +0100 Subject: [PATCH 18/61] Hide chat area when leaving. --- linphone-app/ui/modules/Linphone/Chat/Chat.qml | 4 ++-- linphone-sdk | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.qml b/linphone-app/ui/modules/Linphone/Chat/Chat.qml index 78ed6008f..6637251d6 100644 --- a/linphone-app/ui/modules/Linphone/Chat/Chat.qml +++ b/linphone-app/ui/modules/Linphone/Chat/Chat.qml @@ -380,6 +380,7 @@ Rectangle { Layout.fillWidth: true Layout.preferredHeight: textAreaBorders.height + chatMessagePreview.height+messageBlock.height color: ChatStyle.sendArea.backgroundBorder.color + visible: proxyModel.chatRoomModel && !proxyModel.chatRoomModel.isReadOnly && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled) ColumnLayout{ anchors.fill: parent spacing: 0 @@ -412,7 +413,6 @@ Rectangle { Layout.leftMargin: ChatStyle.sendArea.backgroundBorder.width borderColor: ChatStyle.sendArea.border.color topWidth: ChatStyle.sendArea.border.width - visible: proxyModel.chatRoomModel && !proxyModel.chatRoomModel.isReadOnly && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled) DroppableTextArea { id: textArea @@ -424,7 +424,7 @@ Rectangle { anchors.right: parent.right anchors.bottom: parent.bottom - height:ChatStyle.sendArea.height + ChatStyle.sendArea.border.width + height: visible ? ChatStyle.sendArea.height + ChatStyle.sendArea.border.width : 0 minimumHeight:ChatStyle.sendArea.height + ChatStyle.sendArea.border.width maximumHeight:container.height/2 diff --git a/linphone-sdk b/linphone-sdk index e5c95eaed..2cf715cb4 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit e5c95eaed5a2113cbba1ab62e8baa826abe7609c +Subproject commit 2cf715cb4615c8115aa0102738bc3f28c6302765 From 19de0a5d6c355c7c88c1c722003b8e6bf08c73aa Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Fri, 4 Nov 2022 17:31:29 +0100 Subject: [PATCH 19/61] Decorrelate Lime state option from media encryption. --- linphone-app/src/components/settings/SettingsModel.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/linphone-app/src/components/settings/SettingsModel.cpp b/linphone-app/src/components/settings/SettingsModel.cpp index cbf7d438a..c599ebad6 100644 --- a/linphone-app/src/components/settings/SettingsModel.cpp +++ b/linphone-app/src/components/settings/SettingsModel.cpp @@ -983,9 +983,6 @@ void SettingsModel::setMediaEncryption (MediaEncryption encryption) { if (encryption == getMediaEncryption()) return; - if (encryption != SettingsModel::MediaEncryptionZrtp) - setLimeState(false); - CoreManager::getInstance()->getCore()->setMediaEncryption( static_cast(encryption) ); @@ -1028,10 +1025,7 @@ void SettingsModel::setLimeState (const bool& state) { if (state == getLimeState()) return; - if (state) - setMediaEncryption(SettingsModel::MediaEncryptionZrtp); - - CoreManager::getInstance()->getCore()->enableLimeX3Dh(!state); + CoreManager::getInstance()->getCore()->enableLimeX3Dh(state); emit limeStateChanged(state); } From dcf77ffe7962182a6f34bb5ef31f1aa312671b05 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 7 Nov 2022 10:03:45 +0100 Subject: [PATCH 20/61] Fix translations on CLI commands. Use Phone number assistant : Fix phone number that was considered as not valid. --- linphone-app/src/app/App.cpp | 22 +++++++++++-------- .../App/Main/Assistant/UseAppSipAccount.qml | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp index 4dd083b69..2d6fd820a 100644 --- a/linphone-app/src/app/App.cpp +++ b/linphone-app/src/app/App.cpp @@ -153,7 +153,7 @@ static inline bool installLocale (App &app, QTranslator &translator, const QLoca } static inline string getConfigPathIfExists (const QCommandLineParser &parser) { - QString filePath = parser.value("config"); + QString filePath = parser.isSet("config") ? parser.value("config") : ""; string configPath; if(!QUrl(filePath).isRelative()){ configPath = Utils::appStringToCoreString(FileDownloader::synchronousDownload(filePath, Utils::coreStringToAppString(Paths::getConfigDirPath(false)), true)); @@ -217,12 +217,21 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U } bctbx_set_default_encoding(Constants::LinphoneLocaleEncoding);// Use UTF-8 for internals. Linphone uses UTF-8 so there will be no loss on data with less precise encodings. Qt will do the rest. + createParser(); + mParser->parse(this->arguments()); +// Get configuration for translators + shared_ptr config = Utils::getConfigIfExists (QString::fromStdString(getConfigPathIfExists(*mParser))); + + // Init locale. + mTranslator = new DefaultTranslator(this); + mDefaultTranslator = new DefaultTranslator(this); + initLocale(config); + Logger::init(config); + + createParser();// Recreate parser in order to use translations from config. mParser->process(*this); - // Initialize logger. - shared_ptr config = Utils::getConfigIfExists (QString::fromStdString(getConfigPathIfExists(*mParser))); - Logger::init(config); if (mParser->isSet("verbose")) Logger::getInstance()->setVerbose(true); @@ -230,11 +239,6 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U for (const auto &locale : QDir(Constants::LanguagePath).entryList()) mAvailableLocales << QLocale(locale); - // Init locale. - mTranslator = new DefaultTranslator(this); - mDefaultTranslator = new DefaultTranslator(this); - initLocale(config); - if (mParser->isSet("help")) { mParser->showHelp(); } diff --git a/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml b/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml index e7bbd5c14..4870c8155 100644 --- a/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml +++ b/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml @@ -89,7 +89,7 @@ AssistantAbstractView { function setCountryCode (index) { var model = telephoneNumbersModel - assistantModel.countryCode = index !== -1 ? model.data(model.index(index, 0)).countryCode || '' : '' + assistantModel.countryCode = index !== -1 ? model.data(model.index(index, 0),"countryCode") || '' : '' } configFilename: 'use-app-sip-account.rc' From f18ff79a9cea799e4986295ca3e96d2a4cbf96e5 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 8 Nov 2022 12:35:08 +0100 Subject: [PATCH 21/61] Display only meetings that have been scheduled in meetings list. --- .../components/conferenceInfo/ConferenceInfoProxyModel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp index 885b8c058..c3eb602ec 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp @@ -54,6 +54,8 @@ bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelInde QModelIndex index = listModel->index(sourceRow, 0, QModelIndex()); const ConferenceInfoModel* ics = sourceModel()->data(index).value(); if(ics){ + if(ics->getDuration() == 0) + return false; QDateTime currentDateTime = QDateTime::currentDateTime(); if( mFilterType == 0){ return ics->getEndDateTime() < currentDateTime; @@ -65,7 +67,7 @@ bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelInde return mFilterType == -1; } } - return true; + return false; } bool ConferenceInfoProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { From ed3bd406d0f83dd575629ed8d3018e94f95ff77a Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 10 Nov 2022 16:51:29 +0100 Subject: [PATCH 22/61] Remove mosaic animations and try to fix layouts. Use default friends list to add a contact. Use core friends list to remove a contact. Update SDK 5.2 --- .../components/contacts/ContactsListModel.cpp | 19 ++++- .../ui/modules/Common/Form/Mosaic.qml | 79 +------------------ .../ui/views/App/Main/ContactEdit.qml | 4 +- linphone-sdk | 2 +- 4 files changed, 21 insertions(+), 83 deletions(-) diff --git a/linphone-app/src/components/contacts/ContactsListModel.cpp b/linphone-app/src/components/contacts/ContactsListModel.cpp index 337ff8fad..139a7a900 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.cpp +++ b/linphone-app/src/components/contacts/ContactsListModel.cpp @@ -61,7 +61,9 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren if (row < 0 || count < 0 || limit >= mList.count()) return false; - + + auto friendsList = CoreManager::getInstance()->getCore()->getFriendsLists(); + beginRemoveRows(parent, row, limit); for (int i = 0; i < count; ++i) { @@ -70,7 +72,7 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren mOptimizedSearch.remove(address.toString()); } - for(auto l : mLinphoneFriends) + for(auto l : friendsList) l->removeFriend(contact->mLinphoneFriend); emit contactRemoved(contact); @@ -110,7 +112,16 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) { contact = QSharedPointer::create(vcardModel); App::getInstance()->getEngine()->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership); - if (mLinphoneFriends.front()->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) { + if( mLinphoneFriends.size() == 0){ + update();// Friends were not loaded correctly. Update them. + } + auto friendsList = CoreManager::getInstance()->getCore()->getDefaultFriendList(); + if( !friendsList){ + qWarning() << "There is no friends list available, cannot add a contact" ; + return nullptr; + } + + if (friendsList->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) { qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel; return nullptr; } @@ -118,7 +129,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) { qInfo() << QStringLiteral("Add contact from vcard:") << contact.get() << vcardModel; // Make sure new subscribe is issued. - mLinphoneFriends.front()->updateSubscriptions(); + friendsList->updateSubscriptions(); emit layoutChanged(); diff --git a/linphone-app/ui/modules/Common/Form/Mosaic.qml b/linphone-app/ui/modules/Common/Form/Mosaic.qml index 32151bbc5..48ea6f1bb 100644 --- a/linphone-app/ui/modules/Common/Form/Mosaic.qml +++ b/linphone-app/ui/modules/Common/Form/Mosaic.qml @@ -18,7 +18,7 @@ ColumnLayout{ } function add(item){ - if( !grid.isLayoutWillChanged() || !transitionningTimer.running) + if( !grid.isLayoutWillChanged()) appendItem(item) else bufferModels.append(item) @@ -34,7 +34,7 @@ ColumnLayout{ } function tryToAdd(item){ - if( !grid.isLayoutWillChanged() || !transitionningTimer.running) { + if( !grid.isLayoutWillChanged()) { appendItem(item) return true }else @@ -51,21 +51,7 @@ ColumnLayout{ property int transitionCount : 0 property var bufferModels : ListModel{} - property int maxTransitionTime: 250 - Timer{ - id: transitionningTimer - running: false - interval: maxTransitionTime + 5 - onTriggered: updateBuffers() - } - function startTransition(){ - transitionningTimer.restart() - } - function updateBuffers(){ - while(bufferModels.count > 0 && tryToAdd(bufferModels.get(0))){ - bufferModels.remove(0,1) - } - } + onWidthChanged: grid.updateLayout() onHeightChanged: grid.updateLayout() GridView{ @@ -120,63 +106,6 @@ ColumnLayout{ interactive: false model: DelegateModel{} - //------------------- ANIMATIONS - property Transition defaultTransition: Transition { - SequentialAnimation { - ScriptAction { - script: { - mainLayout.startTransition() - } - } - ParallelAnimation { - NumberAnimation { properties: "x,y"; duration: mainLayout.maxTransitionTime } - } - } - } - - add: Transition { - SequentialAnimation { - ScriptAction { - script: { - mainLayout.startTransition() - } - } - ParallelAnimation { - NumberAnimation { property: "opacity"; from: 0; duration: mainLayout.maxTransitionTime } - NumberAnimation { properties: "x,y"; from: 0; duration: mainLayout.maxTransitionTime; easing.type: Easing.OutBounce } - } - } - } - - addDisplaced: defaultTransition - displaced: defaultTransition - move: defaultTransition - moveDisplaced: defaultTransition - remove: Transition { - SequentialAnimation { - PropertyAction { target: grid; property: "GridView.delayRemove"; value: true } - ScriptAction { - script: { - mainLayout.startTransition() - } - } - ParallelAnimation { - NumberAnimation { property: "opacity"; to: 0; duration: mainLayout.maxTransitionTime } - NumberAnimation { properties: "x,y"; to: 0; duration: mainLayout.maxTransitionTime } - } - PropertyAction { target: grid; property: "GridView.delayRemove"; value: false } - } - } - removeDisplaced: defaultTransition - populate:defaultTransition - - Timer{ // if cell sizes change while adding/removing an item the animation will not end at the right position. - id: updateLayoutDelay - interval: mainLayout.maxTransitionTime - onTriggered: grid.updateLayout() - } - onItemCountChanged: { - updateLayoutDelay.restart() - } + onCountChanged: grid.updateLayout() } } \ No newline at end of file diff --git a/linphone-app/ui/views/App/Main/ContactEdit.qml b/linphone-app/ui/views/App/Main/ContactEdit.qml index b849d7016..96cb52522 100644 --- a/linphone-app/ui/views/App/Main/ContactEdit.qml +++ b/linphone-app/ui/views/App/Main/ContactEdit.qml @@ -35,9 +35,7 @@ ColumnLayout { Component.onDestruction: {_vcard=null}// Need to set it to null because of not calling destructor if not. Component.onCompleted:{ var sipAddress = contactEdit.sipAddress - var contact = contactEdit._contact = SipAddressesModel.mapSipAddressToContact( - sipAddress - ) + var contact = contactEdit._contact = SipAddressesModel.mapSipAddressToContact(sipAddress) if (!contact) { // Add a new contact. diff --git a/linphone-sdk b/linphone-sdk index 2cf715cb4..24d4e2b33 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 2cf715cb4615c8115aa0102738bc3f28c6302765 +Subproject commit 24d4e2b33d036dc7942108cd2391793e58c29de5 From 003daa8df8b03e67679afe2a6ee67c291364509f Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 15 Nov 2022 16:10:53 +0100 Subject: [PATCH 23/61] Margins in Waiting room. --- linphone-app/ui/views/App/Calls/WaitingRoom.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linphone-app/ui/views/App/Calls/WaitingRoom.qml b/linphone-app/ui/views/App/Calls/WaitingRoom.qml index f63a9142c..eafe22ec0 100644 --- a/linphone-app/ui/views/App/Calls/WaitingRoom.qml +++ b/linphone-app/ui/views/App/Calls/WaitingRoom.qml @@ -131,10 +131,13 @@ Rectangle { RowLayout{ Layout.fillWidth: true Layout.fillHeight: true + spacing: 0 Item{ id: stickerView Layout.fillHeight: true Layout.fillWidth: true + Layout.leftMargin: 10 + Layout.rightMargin: 10 Sticker{ id: contentsStack @@ -175,7 +178,7 @@ Rectangle { Loader{ id: multimediaLoader Layout.fillHeight: true - Layout.leftMargin: 10 + Layout.leftMargin: 0 Layout.rightMargin: 10 Layout.minimumHeight: item? item.fitHeight : 0 Layout.minimumWidth: item? item.fitWidth : 0 From 026124d7ba8aff450fe90db86353b7fa760cb93b Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 15 Nov 2022 16:38:11 +0100 Subject: [PATCH 24/61] Call history view : hide actions for conference. --- .../ui/views/App/Main/HistoryView.qml | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/linphone-app/ui/views/App/Main/HistoryView.qml b/linphone-app/ui/views/App/Main/HistoryView.qml index 83eb23794..5361edba4 100644 --- a/linphone-app/ui/views/App/Main/HistoryView.qml +++ b/linphone-app/ui/views/App/Main/HistoryView.qml @@ -14,12 +14,14 @@ import 'HistoryView.js' as Logic ColumnLayout { id: historyView - property string peerAddress - property string fullPeerAddress + property var entry + property string peerAddress : entry ? entry.sipAddress : '' + property string fullPeerAddress : entry ? entry.sipAddress : '' + property var _sipAddressObserver: peerAddress?SipAddressesModel.getSipAddressObserver((fullPeerAddress?fullPeerAddress:peerAddress), ''):null - + onEntryChanged: historyProxyModel.resetMessageCount() // --------------------------------------------------------------------------- spacing: 0 @@ -56,15 +58,21 @@ ColumnLayout { historyView._sipAddressObserver.presenceStatus ):null - username: peerAddress && historyView._sipAddressObserver? UtilsCpp.getDisplayName(historyView._sipAddressObserver.peerAddress):null - visible:peerAddress + username: historyView.entry && historyView.entry.wasConference + ? historyView.entry.title + : peerAddress && historyView._sipAddressObserver + ? UtilsCpp.getDisplayName(historyView._sipAddressObserver.peerAddress) + : null + visible: peerAddress } ContactDescription { Layout.fillHeight: true Layout.fillWidth: true - subtitleText: SipAddressesModel.cleanSipAddress(sipAddress)(historyView.peerAddress) + subtitleText: historyView.entry && historyView.entry.wasConference + ? '' + : SipAddressesModel.cleanSipAddress(historyView.peerAddress) subtitleColor: HistoryViewStyle.bar.description.subtitleColor titleText: avatar.username titleColor: HistoryViewStyle.bar.description.titleColor @@ -75,10 +83,10 @@ ColumnLayout { Layout.fillHeight: true spacing: HistoryViewStyle.bar.actions.spacing - ActionBar { anchors.verticalCenter: parent.verticalCenter iconSize: HistoryViewStyle.bar.actions.call.iconSize + visible: historyView.entry ? !historyView.entry.wasConference : false ActionButton { isCustom: true @@ -129,7 +137,7 @@ ColumnLayout { backgroundRadius: 4 colorSet: historyView._sipAddressObserver && historyView._sipAddressObserver.contact ? ConversationStyle.bar.actions.edit.viewContact : ConversationStyle.bar.actions.edit.addContact iconSize: HistoryViewStyle.bar.actions.edit.iconSize - visible: peerAddress && SettingsModel.contactsEnabled + visible: SettingsModel.contactsEnabled && historyView.entry ? !historyView.entry.wasConference : false onClicked: window.setView('ContactEdit', { sipAddress: historyView.peerAddress }) tooltipText: peerAddress?Logic.getEditTooltipText():'' @@ -158,9 +166,7 @@ ColumnLayout { Layout.fillWidth: true onEntryClicked:{ - historyView.fullPeerAddress=entry.sipAddress - historyView.peerAddress=entry.sipAddress - historyProxyModel.resetMessageCount() + historyView.entry = entry } proxyModel: HistoryProxyModel { From 5d5d4d39413f1a2fdfe01b886be0fe581638ed72 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 15 Nov 2022 17:22:35 +0100 Subject: [PATCH 25/61] Allow to activate camera on audio-only from the call window. --- linphone-app/ui/views/App/Calls/Incall.qml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index cd616f849..4354dc512 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -489,14 +489,26 @@ Rectangle { backgroundRadius: 90 colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff updating: callModel.videoEnabled && callModel.updating - enabled: !mainItem.isAudioOnly + property bool _activateCamera: false onClicked: if(callModel){ if( callModel.isConference){// Only deactivate camera in conference. - callModel.cameraEnabled = !callModel.cameraEnabled + if(mainItem.isAudioOnly && SettingsModel.videoConferenceLayout != 2) { + camera._activateCamera = true + conferenceLayout.item.clearAll(SettingsModel.videoConferenceLayout) + callModel.conferenceVideoLayout = SettingsModel.videoConferenceLayout + }else + callModel.cameraEnabled = !callModel.cameraEnabled }else{// In one-one, we deactivate all videos. callModel.videoEnabled = !callModel.videoEnabled } } + Connections{// Enable camera only when status is ok + target: callModel + onStatusChanged: if( camera._activateCamera && (status == LinphoneEnums.CallStatusConnected || status == LinphoneEnums.CallStatusIdle)){ + camera._activateCamera = false + callModel.cameraEnabled = true + } + } } } From 3677770de2b7380c29415efdc606a812ddd31bc7 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 16 Nov 2022 14:48:32 +0100 Subject: [PATCH 26/61] Fix system times zone on ICS and meetings times. --- .../src/components/conferenceInfo/ConferenceInfoModel.cpp | 2 +- .../ui/modules/Linphone/Chat/ChatCalendarMessage.qml | 3 ++- .../Linphone/Chat/ChatConferenceInvitationMessage.qml | 5 +++-- linphone-app/ui/scripts/Utils/utils.js | 8 ++++++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index 583e8a855..c99a2bc24 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -139,7 +139,7 @@ std::shared_ptr ConferenceInfoModel::findConferenceInf //------------------------------------------------------------------------------------------------ - +//Note conferenceInfo->getDateTime uses system timezone. QDateTime ConferenceInfoModel::getDateTimeUtc() const{ return QDateTime::fromMSecsSinceEpoch(mConferenceInfo->getDateTime() * 1000).toUTC(); } diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml index 4f8be65ec..febc5c715 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml @@ -111,7 +111,8 @@ Loader{ color: ChatCalendarMessageStyle.schedule.color elide: Text.ElideRight font.pointSize: ChatCalendarMessageStyle.schedule.pointSize - text: Qt.formatDateTime(mainItem.conferenceInfoModel.dateTime, 'hh:mm') +// Reminder: QML use locale time (not system). Use UTC from C++ => convert it into QML => pass QML => convert it into UTC and apply our timezone. + text: UtilsCpp.toTimeString(Utils.fromUTC(mainItem.conferenceInfoModel.dateTimeUtc), 'hh:mm') + (mainItem.conferenceInfoModel.duration > 0 ? ' (' +Utils.formatDuration(mainItem.conferenceInfoModel.duration * 60) + ')' : '') } diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml index e9820c144..d0b487a3d 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml @@ -158,7 +158,7 @@ Loader{ color: ChatCalendarMessageStyle.schedule.color elide: Text.ElideRight font.pointSize: Units.dp * 8 - text: Qt.formatDate(mainItem.conferenceInfoModel.dateTimeUtc, 'yyyy/MM/dd') + text: UtilsCpp.toDateString(Utils.fromUTC(mainItem.conferenceInfoModel.dateTimeUtc), 'yyyy/MM/dd') } } RowLayout { @@ -182,7 +182,8 @@ Loader{ color: ChatCalendarMessageStyle.schedule.color elide: Text.ElideRight font.pointSize: Units.dp * 8 - text: Qt.formatDateTime(mainItem.conferenceInfoModel.dateTimeUtc, 'hh:mm') +// Reminder: QML use locale time (not system). Use UTC from C++ => convert it into QML => pass QML => convert it into UTC and apply our timezone. + text: UtilsCpp.toTimeString( Utils.fromUTC(mainItem.conferenceInfoModel.dateTimeUtc), 'hh:mm') + (mainItem.conferenceInfoModel.duration > 0 ? ' ('+Utils.formatDuration(mainItem.conferenceInfoModel.duration * 60) + ')' : '') } diff --git a/linphone-app/ui/scripts/Utils/utils.js b/linphone-app/ui/scripts/Utils/utils.js index dc4e2f202..d82ed2452 100644 --- a/linphone-app/ui/scripts/Utils/utils.js +++ b/linphone-app/ui/scripts/Utils/utils.js @@ -562,6 +562,14 @@ function buildDate(date, time){ dateTime.setSeconds(time.getSeconds()) return dateTime } + + +function fromUTC(date){ + return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), + date.getUTCDate(), date.getUTCHours(), + date.getUTCMinutes(), date.getUTCSeconds())); +} + // ----------------------------------------------------------------------------- function formatSize (size) { From f924a17055604685321ef46e5e67aa499c7041bf Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 17 Nov 2022 12:17:56 +0100 Subject: [PATCH 27/61] Synchronize ICS from actions like deletion/cancellation. --- .../conferenceInfo/ConferenceInfoModel.cpp | 16 ++++++++++---- .../conferenceInfo/ConferenceInfoModel.hpp | 6 ++++- linphone-app/src/utils/LinphoneEnums.cpp | 22 ++++++++++++++----- linphone-app/src/utils/LinphoneEnums.hpp | 14 +++++++++++- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index c99a2bc24..b04ae22ba 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -104,6 +104,7 @@ ConferenceInfoModel::ConferenceInfoModel (QObject * parent) : QObject(parent){ connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::isScheduledChanged); connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::inviteModeChanged); connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::conferenceInfoStateChanged); + connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::conferenceSchedulerStateChanged); } // Callable from C++ @@ -124,6 +125,7 @@ ConferenceInfoModel::ConferenceInfoModel (std::shared_ptrgetState()); } +LinphoneEnums::ConferenceSchedulerState ConferenceInfoModel::getConferenceSchedulerState() const{ + return LinphoneEnums::fromLinphone(mLastConferenceSchedulerState); +} + //------------------------------------------------------------------------------------------------ // Convert into UTC with TimeZone and pass system timezone to conference info void ConferenceInfoModel::setDateTime(const QDateTime& dateTime){ @@ -323,14 +329,14 @@ void ConferenceInfoModel::createConference(const int& securityLevel) { mConferenceScheduler = ConferenceScheduler::create(); mConferenceScheduler->mSendInvite = mInviteMode; connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent); - connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onStateChanged); + connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onConferenceSchedulerStateChanged); mConferenceScheduler->getConferenceScheduler()->setInfo(mConferenceInfo); } void ConferenceInfoModel::cancelConference(){ mConferenceScheduler = ConferenceScheduler::create(); connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent); - connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onStateChanged); + connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onConferenceSchedulerStateChanged); mConferenceScheduler->getConferenceScheduler()->cancelConference(mConferenceInfo); } @@ -343,12 +349,14 @@ void ConferenceInfoModel::deleteConferenceInfo(){ //------------------------------------------------------------------------------------------------- -void ConferenceInfoModel::onStateChanged(linphone::ConferenceScheduler::State state){ - qDebug() << "ConferenceInfoModel::onStateChanged: " << (int) state; +void ConferenceInfoModel::onConferenceSchedulerStateChanged(linphone::ConferenceScheduler::State state){ + qDebug() << "ConferenceInfoModel::onConferenceSchedulerStateChanged: " << (int) state; + mLastConferenceSchedulerState = state; if( state == linphone::ConferenceScheduler::State::Ready) emit conferenceCreated(); else if( state == linphone::ConferenceScheduler::State::Error) emit conferenceCreationFailed(); + emit conferenceInfoChanged(); } void ConferenceInfoModel::onInvitationsSent(const std::list> & failedInvitations) { qDebug() << "ConferenceInfoModel::onInvitationsSent"; diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp index fa92147fa..2db672dbf 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp @@ -50,6 +50,7 @@ public: Q_PROPERTY(bool isScheduled READ isScheduled WRITE setIsScheduled NOTIFY isScheduledChanged) Q_PROPERTY(int inviteMode READ getInviteMode WRITE setInviteMode NOTIFY inviteModeChanged) Q_PROPERTY(LinphoneEnums::ConferenceInfoState state READ getConferenceInfoState NOTIFY conferenceInfoStateChanged) + Q_PROPERTY(LinphoneEnums::ConferenceSchedulerState conferenceSchedulerState READ getConferenceSchedulerState NOTIFY conferenceSchedulerStateChanged) static QSharedPointer create(std::shared_ptr conferenceInfo); ConferenceInfoModel (QObject * parent = nullptr); @@ -76,6 +77,7 @@ public: Q_INVOKABLE TimeZoneModel* getTimeZoneModel() const; Q_INVOKABLE QString getIcalendarString() const; LinphoneEnums::ConferenceInfoState getConferenceInfoState() const; + LinphoneEnums::ConferenceSchedulerState getConferenceSchedulerState() const; void setDateTime(const QDateTime& dateTime); void setDuration(const int& duration); @@ -97,7 +99,7 @@ public: // SCHEDULER - virtual void onStateChanged(linphone::ConferenceScheduler::State state); + virtual void onConferenceSchedulerStateChanged(linphone::ConferenceScheduler::State state); virtual void onInvitationsSent(const std::list> & failedInvitations); signals: @@ -112,6 +114,7 @@ signals: void isScheduledChanged(); void inviteModeChanged(); void conferenceInfoStateChanged(); + void conferenceSchedulerStateChanged(); void conferenceCreated(); void conferenceCreationFailed(); @@ -127,6 +130,7 @@ private: bool mIsScheduled = true; int mInviteMode = 0; bool mRemoveRequested = false;// true if user has request its deletion from DB + linphone::ConferenceScheduler::State mLastConferenceSchedulerState = linphone::ConferenceScheduler::State::Idle;// Workaround for missing getter in scheduler. }; Q_DECLARE_METATYPE(QSharedPointer) diff --git a/linphone-app/src/utils/LinphoneEnums.cpp b/linphone-app/src/utils/LinphoneEnums.cpp index 90026d573..e15cc1395 100644 --- a/linphone-app/src/utils/LinphoneEnums.cpp +++ b/linphone-app/src/utils/LinphoneEnums.cpp @@ -25,14 +25,18 @@ // ============================================================================= void LinphoneEnums::registerMetaTypes(){ - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); - qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); } linphone::MediaEncryption LinphoneEnums::toLinphone(const LinphoneEnums::MediaEncryption& data){ @@ -89,6 +93,14 @@ LinphoneEnums::ConferenceInfoState LinphoneEnums::fromLinphone(const linphone::C return static_cast(state); } +linphone::ConferenceScheduler::State LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceSchedulerState& state){ + return static_cast(state); +} + +LinphoneEnums::ConferenceSchedulerState LinphoneEnums::fromLinphone(const linphone::ConferenceScheduler::State& state){ + return static_cast(state); +} + linphone::ParticipantDeviceState LinphoneEnums::toLinphone(const LinphoneEnums::ParticipantDeviceState& state){ return static_cast(state); } diff --git a/linphone-app/src/utils/LinphoneEnums.hpp b/linphone-app/src/utils/LinphoneEnums.hpp index 16af1fae9..f3bffccf0 100644 --- a/linphone-app/src/utils/LinphoneEnums.hpp +++ b/linphone-app/src/utils/LinphoneEnums.hpp @@ -133,6 +133,18 @@ Q_ENUM_NS(ConferenceInfoState) linphone::ConferenceInfo::State toLinphone(const LinphoneEnums::ConferenceInfoState& state); LinphoneEnums::ConferenceInfoState fromLinphone(const linphone::ConferenceInfo::State& state); +enum ConferenceSchedulerState { + ConferenceSchedulerStateAllocationPending = int(linphone::ConferenceScheduler::State::AllocationPending), + ConferenceSchedulerStateError = int(linphone::ConferenceScheduler::State::Error), + ConferenceSchedulerStateIdle = int(linphone::ConferenceScheduler::State::Idle), + ConferenceSchedulerStateReady = int(linphone::ConferenceScheduler::State::Ready), + ConferenceSchedulerStateUpdating = int(linphone::ConferenceScheduler::State::Updating) +}; +Q_ENUM_NS(ConferenceSchedulerState) + +linphone::ConferenceScheduler::State toLinphone(const LinphoneEnums::ConferenceSchedulerState& state); +LinphoneEnums::ConferenceSchedulerState fromLinphone(const linphone::ConferenceScheduler::State& state); + enum ParticipantDeviceState { ParticipantDeviceStateJoining = int(linphone::ParticipantDeviceState::Joining), @@ -189,10 +201,10 @@ void fromString(const QString& transportType, LinphoneEnums::TransportType *tran Q_DECLARE_METATYPE(LinphoneEnums::CallStatus) - Q_DECLARE_METATYPE(LinphoneEnums::ChatMessageState) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceLayout) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceInfoState) +Q_DECLARE_METATYPE(LinphoneEnums::ConferenceSchedulerState) Q_DECLARE_METATYPE(LinphoneEnums::EventLogType) Q_DECLARE_METATYPE(LinphoneEnums::FriendCapability) Q_DECLARE_METATYPE(LinphoneEnums::MediaEncryption) From ba2d41365e16e3575d97a555c5dcd2cdf1509202 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 17 Nov 2022 12:18:06 +0100 Subject: [PATCH 28/61] Hide participant view in ICS when there is none. --- .../src/components/conferenceInfo/ConferenceInfoModel.hpp | 1 + .../ui/modules/Linphone/Chat/ChatCalendarMessage.qml | 2 ++ .../Linphone/Chat/ChatConferenceInvitationMessage.qml | 7 ++++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp index 2db672dbf..da7f01fc4 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp @@ -49,6 +49,7 @@ public: Q_PROPERTY(QString uri READ getUri NOTIFY uriChanged) Q_PROPERTY(bool isScheduled READ isScheduled WRITE setIsScheduled NOTIFY isScheduledChanged) Q_PROPERTY(int inviteMode READ getInviteMode WRITE setInviteMode NOTIFY inviteModeChanged) + Q_PROPERTY(int participantCount READ getParticipantCount NOTIFY participantsChanged) Q_PROPERTY(LinphoneEnums::ConferenceInfoState state READ getConferenceInfoState NOTIFY conferenceInfoStateChanged) Q_PROPERTY(LinphoneEnums::ConferenceSchedulerState conferenceSchedulerState READ getConferenceSchedulerState NOTIFY conferenceSchedulerStateChanged) diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml index febc5c715..e7022c1f3 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml @@ -179,6 +179,8 @@ Loader{ Layout.preferredHeight: parent.participantLineHeight Layout.preferredWidth: ChatCalendarMessageStyle.participants.iconSize Layout.alignment: Qt.AlignTop + + visible: mainItem.conferenceInfoModel.participantCount > 0 clip: false Icon{ anchors.top: parent.top diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml index d0b487a3d..b17b651d1 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml @@ -109,12 +109,14 @@ Loader{ } RowLayout { id: participantsRow + property int participantCount: mainItem.conferenceInfoModel.participantCount Layout.fillWidth: true Layout.preferredHeight: ChatCalendarMessageStyle.participants.iconSize Layout.leftMargin: 5 Layout.rightMargin: 15 - spacing: ChatCalendarMessageStyle.participants.spacing + spacing: ChatCalendarMessageStyle.participants.spacing + visible: participantsRow.participantCount > 0 Icon{ icon: ChatCalendarMessageStyle.participants.icon @@ -124,13 +126,12 @@ Loader{ Text { id: participantsList - property int participantCount: mainItem.conferenceInfoModel.getParticipantCount() Layout.fillWidth: true color: ChatCalendarMessageStyle.participants.color elide: Text.ElideRight font.pointSize: ChatCalendarMessageStyle.participants.pointSize //: '%1 participant' : number(=%1) of participant. - text: qsTr('icsParticipants', '', participantCount).arg(participantCount) + text: qsTr('icsParticipants', '', participantsRow.participantCount).arg(participantsRow.participantCount) } } ColumnLayout{ From 0156f9203a1d52e6bac6e51a0d54d36d96291bb4 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 17 Nov 2022 13:15:39 +0100 Subject: [PATCH 29/61] Remove selection in DatePicker if it is outside the current displayed month. --- linphone-app/ui/modules/Common/Picker/DatePicker.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-app/ui/modules/Common/Picker/DatePicker.qml b/linphone-app/ui/modules/Common/Picker/DatePicker.qml index fb9eb1b0d..f740d478b 100644 --- a/linphone-app/ui/modules/Common/Picker/DatePicker.qml +++ b/linphone-app/ui/modules/Common/Picker/DatePicker.qml @@ -107,7 +107,7 @@ Item{ id: cellItem property int day: index - 7 // 0 = top left below Sunday (-7 to 41) property int date: day - firstDay + 1 // 1-31 - property bool selected : new Date(year, month, date).toDateString() == monthList.selectedDate.toDateString() && text.text && day >= 0 + property bool selected : text.text != '-' && new Date(year, month, date).toDateString() == monthList.selectedDate.toDateString() && text.text && day >= 0 width: grid.cellMinSize height: width From fee7046f2166a235c5587925997b302067177bc0 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 17 Nov 2022 14:08:27 +0100 Subject: [PATCH 30/61] Update SDK for crash fix on Chat Rooms --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 24d4e2b33..94664893e 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 24d4e2b33d036dc7942108cd2391793e58c29de5 +Subproject commit 94664893e89fa2586d63735b2e42ebccb37f453d From 531f1cbae9f8adb24d41398a214373c29c217a6e Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 21 Nov 2022 10:20:20 +0100 Subject: [PATCH 31/61] Update SDK (fix ZRTP) --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 94664893e..3a00e2678 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 94664893e89fa2586d63735b2e42ebccb37f453d +Subproject commit 3a00e2678c97db3efdfe44683e5fa602ea4f0c65 From 6d23c90ba8d3977fdd11956badf0628e7e10af69 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 21 Nov 2022 14:47:57 +0100 Subject: [PATCH 32/61] Fix Times offset on ICS and on conference creation (mainly because of Windows unmanaged Timezones) --- linphone-app/ui/views/App/Dialog/NewConference.qml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/linphone-app/ui/views/App/Dialog/NewConference.qml b/linphone-app/ui/views/App/Dialog/NewConference.qml index d58f8ea5b..c84cced70 100644 --- a/linphone-app/ui/views/App/Dialog/NewConference.qml +++ b/linphone-app/ui/views/App/Dialog/NewConference.qml @@ -20,8 +20,8 @@ DialogPlus { property bool isNew: !conferenceInfoModel || conferenceInfoModel.uri === '' property ConferenceInfoModel conferenceInfoModel: ConferenceInfoModel{} onConferenceInfoModelChanged: { - dateField.setDate(conferenceManager.conferenceInfoModel.dateTime); - timeField.setTime(conferenceManager.conferenceInfoModel.dateTime); + dateField.setDate(conferenceManager.conferenceInfoModel.dateTimeUtc); + timeField.setTime(conferenceManager.conferenceInfoModel.dateTimeUtc); selectedParticipants.setAddresses(conferenceInfoModel) } property bool forceSchedule : false @@ -319,12 +319,15 @@ DialogPlus { TextField{id: timeField; Layout.preferredWidth: parent.cellWidth color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize function getTime(){ - return Date.fromLocaleTimeString(scheduleForm.locale, timeField.text, 'hh:mm') + return Date.fromLocaleTimeString(scheduleForm.locale, timeField._text, 'hh:mm') } function setTime(date){ - text = date.toLocaleTimeString(scheduleForm.locale, 'hh:mm') + _text = date.toLocaleTimeString(scheduleForm.locale, 'hh:mm') + text = UtilsCpp.toTimeString(date, 'hh:mm')// Display the unchanged time } - text: conferenceManager.conferenceInfoModel? conferenceManager.conferenceInfoModel.dateTime.toLocaleTimeString(scheduleForm.locale, 'hh:mm') : '' + // hidden time to be used from JS : JS Local time can be wrong on Windows because of daylights that are not takken account. + property string _text: conferenceManager.conferenceInfoModel? conferenceManager.conferenceInfoModel.dateTime.toLocaleTimeString(scheduleForm.locale, 'hh:mm') : '' + text: conferenceManager.conferenceInfoModel? UtilsCpp.toTimeString(conferenceManager.conferenceInfoModel.dateTimeUtc, 'hh:mm') : '' icon: 'drop_down_custom' onEditingFinished: if(rightStackView.currentItemType === 2) { From 2839b39c9f1b223ad43591596dee2a430f5257ab Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 21 Nov 2022 14:48:49 +0100 Subject: [PATCH 33/61] Update SDK (Fix camera previews on Windows) --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 3a00e2678..635a5b9c2 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 3a00e2678c97db3efdfe44683e5fa602ea4f0c65 +Subproject commit 635a5b9c2ef7951ce94c422352274c2b7685c215 From 8fdf862a27aba4fb097d3c8f14a54d4f33962d31 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 21 Nov 2022 15:51:39 +0100 Subject: [PATCH 34/61] On contact website info, if the scheme has been defined then add the default scheme : https. --- linphone-app/src/components/contact/VcardModel.cpp | 7 +++++-- linphone-app/src/components/contact/VcardModel.hpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/linphone-app/src/components/contact/VcardModel.cpp b/linphone-app/src/components/contact/VcardModel.cpp index 9f44ba24e..f807d756e 100644 --- a/linphone-app/src/components/contact/VcardModel.cpp +++ b/linphone-app/src/components/contact/VcardModel.cpp @@ -460,9 +460,12 @@ QVariantList VcardModel::getUrls () const { return list; } -bool VcardModel::addUrl (const QString &url) { +bool VcardModel::addUrl (QString url) { CHECK_VCARD_IS_WRITABLE(this); - + QUrl urlParser(url); + if( urlParser.scheme() == ""){ + url = "https://"+url; + } shared_ptr belcard = mVcard->getVcard(); if (findBelCardValue(belcard->getURLs(), url)) return false; diff --git a/linphone-app/src/components/contact/VcardModel.hpp b/linphone-app/src/components/contact/VcardModel.hpp index bbf6f0ce4..b4828ee38 100644 --- a/linphone-app/src/components/contact/VcardModel.hpp +++ b/linphone-app/src/components/contact/VcardModel.hpp @@ -88,7 +88,7 @@ public: Q_INVOKABLE void removeEmail (const QString &email); Q_INVOKABLE bool updateEmail (const QString &oldEmail, const QString &email); - Q_INVOKABLE bool addUrl (const QString &url); + Q_INVOKABLE bool addUrl (QString url); Q_INVOKABLE void removeUrl (const QString &url); Q_INVOKABLE bool updateUrl (const QString &oldUrl, const QString &url); From 91833adbae4acbc8e3ddfd80a1c684ba8d07d5f5 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 21 Nov 2022 16:57:47 +0100 Subject: [PATCH 35/61] Contacts fix on deletion --- linphone-app/src/components/contacts/ContactsListModel.cpp | 4 ++++ linphone-app/src/components/contacts/ContactsListModel.hpp | 1 + linphone-app/ui/views/App/Main/ContactEdit.js | 2 +- linphone-app/ui/views/App/Main/ContactEdit.qml | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/linphone-app/src/components/contacts/ContactsListModel.cpp b/linphone-app/src/components/contacts/ContactsListModel.cpp index 139a7a900..efb6522e2 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.cpp +++ b/linphone-app/src/components/contacts/ContactsListModel.cpp @@ -100,6 +100,10 @@ QSharedPointer ContactsListModel::findContactModelFromUsername (co } // ----------------------------------------------------------------------------- +ContactModel *ContactsListModel::getContactModelFromAddress (const QString& address) const{ + auto contact = findContactModelFromSipAddress(address); + return contact.get(); +} ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) { // Try to merge vcardModel to an existing contact. diff --git a/linphone-app/src/components/contacts/ContactsListModel.hpp b/linphone-app/src/components/contacts/ContactsListModel.hpp index aa59869a3..93768a758 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.hpp +++ b/linphone-app/src/components/contacts/ContactsListModel.hpp @@ -49,6 +49,7 @@ public: QSharedPointer findContactModelFromSipAddress (const QString &sipAddress) const; QSharedPointer findContactModelFromUsername (const QString &username) const; + Q_INVOKABLE ContactModel *getContactModelFromAddress (const QString& address) const; Q_INVOKABLE ContactModel *addContact (VcardModel *vcardModel); Q_INVOKABLE void removeContact (ContactModel *contact); diff --git a/linphone-app/ui/views/App/Main/ContactEdit.js b/linphone-app/ui/views/App/Main/ContactEdit.js index 11da59f9c..0c3b8898a 100644 --- a/linphone-app/ui/views/App/Main/ContactEdit.js +++ b/linphone-app/ui/views/App/Main/ContactEdit.js @@ -79,7 +79,7 @@ function removeContact () { if (status) { window.unlockView() window.setView('Contacts') - Linphone.ContactsListModel.remove(_contact) + Linphone.ContactsListModel.removeContact(_contact) } }) } diff --git a/linphone-app/ui/views/App/Main/ContactEdit.qml b/linphone-app/ui/views/App/Main/ContactEdit.qml index 96cb52522..1ffe07211 100644 --- a/linphone-app/ui/views/App/Main/ContactEdit.qml +++ b/linphone-app/ui/views/App/Main/ContactEdit.qml @@ -35,7 +35,7 @@ ColumnLayout { Component.onDestruction: {_vcard=null}// Need to set it to null because of not calling destructor if not. Component.onCompleted:{ var sipAddress = contactEdit.sipAddress - var contact = contactEdit._contact = SipAddressesModel.mapSipAddressToContact(sipAddress) + var contact = contactEdit._contact = ContactsListModel.getContactModelFromAddress(sipAddress) if (!contact) { // Add a new contact. From f8ca666219b4b10186b139fdfa9fc68b47d638a2 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 22 Nov 2022 10:54:07 +0100 Subject: [PATCH 36/61] From Chat room infos: - Fix hidden buzy indicator on participant invitations (from Chat Room infos). - Fix auto removing participant on timeout invitations (30s). --- .../participant/ParticipantProxyModel.cpp | 27 ++++++++++--------- .../Styles/Animations/BusyIndicatorStyle.qml | 1 + .../Linphone/View/ParticipantsView.qml | 27 ++++++++++++------- .../views/App/Main/Dialogs/InfoChatRoom.qml | 2 +- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/linphone-app/src/components/participant/ParticipantProxyModel.cpp b/linphone-app/src/components/participant/ParticipantProxyModel.cpp index 6abab1acd..5e32d4729 100644 --- a/linphone-app/src/components/participant/ParticipantProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantProxyModel.cpp @@ -92,8 +92,11 @@ void ParticipantProxyModel::setChatRoomModel(ChatRoomModel * chatRoomModel){ connect(participants, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged); setSourceModel(participants); emit participantListModelChanged(); - for(int i = 0 ; i < participants->getCount() ; ++i) - emit addressAdded(participants->getAt(i)->getSipAddress()); + for(int i = 0 ; i < participants->getCount() ; ++i) { + auto participant = participants->getAt(i); + connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel); + emit addressAdded(participant->getSipAddress()); + } }else if(!sourceModel()){ auto model = new ParticipantListModel((ChatRoomModel*)nullptr, this); connect(model, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged); @@ -113,8 +116,11 @@ void ParticipantProxyModel::setConferenceModel(ConferenceModel * conferenceModel connect(participants, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged); setSourceModel(participants); emit participantListModelChanged(); - for(int i = 0 ; i < participants->getCount() ; ++i) - emit addressAdded(participants->getAt(i)->getSipAddress()); + for(int i = 0 ; i < participants->getCount() ; ++i) { + auto participant = participants->getAt(i); + connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel); + emit addressAdded(participant->getSipAddress()); + } }else if(!sourceModel()){ auto model = new ParticipantListModel((ConferenceModel*)nullptr, this); connect(model, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged); @@ -144,12 +150,12 @@ void ParticipantProxyModel::addAddress(const QString& address){ ParticipantListModel * participantsModel = qobject_cast(sourceModel()); if(!participantsModel->contains(address)){ QSharedPointer participant = QSharedPointer::create(nullptr); + connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel); participant->setSipAddress(address); participantsModel->add(participant); if(mChatRoomModel && mChatRoomModel->getChatRoom()){// Invite and wait for its creation - mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address)); - connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel); participant->startInvitation(); + mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address)); } if( mConferenceModel && mConferenceModel->getConference()){ auto addressToInvite = Utils::interpretUrl(address); @@ -158,23 +164,18 @@ void ParticipantProxyModel::addAddress(const QString& address){ auto haveCall = std::find_if(currentCalls.begin(), currentCalls.end(), [addressToInvite](const std::shared_ptr& call){ return call->getRemoteAddress()->weakEqual(addressToInvite); }); + participant->startInvitation(); if( haveCall == currentCalls.end()) mConferenceModel->getConference()->addParticipant(addressToInvite); else{ runningCallsToAdd.push_back(*haveCall); mConferenceModel->getConference()->addParticipants(runningCallsToAdd); } - - /* std::list> addressesToInvite; addressesToInvite.push_back(addressToInvite); auto callParameters = CoreManager::getInstance()->getCore()->createCallParams(mConferenceModel->getConference()->getCall()); - mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/ - - connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel); - participant->startInvitation(); - + mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/ } emit countChanged(); emit addressAdded(address); diff --git a/linphone-app/ui/modules/Common/Styles/Animations/BusyIndicatorStyle.qml b/linphone-app/ui/modules/Common/Styles/Animations/BusyIndicatorStyle.qml index 40b95d07a..083f6d463 100644 --- a/linphone-app/ui/modules/Common/Styles/Animations/BusyIndicatorStyle.qml +++ b/linphone-app/ui/modules/Common/Styles/Animations/BusyIndicatorStyle.qml @@ -6,6 +6,7 @@ import ColorsList 1.0 QtObject { property string sectionName: 'Busy' property color color: ColorsList.add(sectionName+'_indicator', 'q').color + property color alternateColor: ColorsList.add(sectionName+'_indicator_alt', 'i').color property int duration: 1250 property int nSpheres: 8 } diff --git a/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml b/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml index fff449043..f38c0b85b 100644 --- a/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml +++ b/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml @@ -6,6 +6,8 @@ import Linphone 1.0 import Linphone.Styles 1.0 import Common.Styles 1.0 +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + // ============================================================================= ScrollableListView { @@ -253,16 +255,7 @@ ScrollableListView { statusText : showAdminStatus ? getStatus() : '' entry: $modelData - onAvatarClicked: sipAddressesView.entryClicked(parent.entry, index, contactView) - - BusyIndicator{ - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - width:15 - height:15 - running: sipAddressesView.showInvitingIndicator && $modelData.inviting - } } @@ -289,6 +282,7 @@ ScrollableListView { } Repeater { + id: actionsRepeater model: sipAddressesView.actions ActionButton { @@ -309,6 +303,21 @@ ScrollableListView { anchors.top:parent.top anchors.horizontalCenter: parent.right } + Loader{ + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + height: parent.height - 2 + width: height + + active: index == actionsRepeater.count -1 && sipAddressesView.showInvitingIndicator && contactView.entry && contactView.entry.inviting + + sourceComponent: Component{ + BusyIndicator{ + color: BusyIndicatorStyle.alternateColor + running: true + } + } + } } } } diff --git a/linphone-app/ui/views/App/Main/Dialogs/InfoChatRoom.qml b/linphone-app/ui/views/App/Main/Dialogs/InfoChatRoom.qml index cdbd607d2..1097334e2 100644 --- a/linphone-app/ui/views/App/Main/Dialogs/InfoChatRoom.qml +++ b/linphone-app/ui/views/App/Main/Dialogs/InfoChatRoom.qml @@ -88,7 +88,7 @@ DialogPlus { secure: chatRoomModel.haveEncryption, visible: true, secureIconVisibleHandler : function(entry) { - return entry.sipAddress && chatRoomModel && chatRoomModel.haveEncryption && UtilsCpp.hasCapability(entry.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh); + return entry && entry.sipAddress && chatRoomModel && chatRoomModel.haveEncryption && UtilsCpp.hasCapability(entry.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh); }, handler: function (entry) { selectedParticipants.addAddress(entry.sipAddress) From 010743aa09ce24bc44175d2da9b27de54dddc45c Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 22 Nov 2022 14:39:16 +0100 Subject: [PATCH 37/61] Display default preset if no one has been selected. --- linphone-app/ui/views/App/Settings/SettingsVideo.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linphone-app/ui/views/App/Settings/SettingsVideo.qml b/linphone-app/ui/views/App/Settings/SettingsVideo.qml index bf28782fa..ed3c22b49 100644 --- a/linphone-app/ui/views/App/Settings/SettingsVideo.qml +++ b/linphone-app/ui/views/App/Settings/SettingsVideo.qml @@ -69,9 +69,10 @@ TabContainer { currentIndex: { var preset = SettingsModel.videoPreset - return Number(Utils.findIndex(model, function (value) { + var index = Number(Utils.findIndex(model, function (value) { return preset === value.value })) + return index>=0 ? index : 0; } model: [{ From f3d3f1ee0b778307abcc3566ed59fbeffb87582a Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 22 Nov 2022 16:10:42 +0100 Subject: [PATCH 38/61] Fix stopping record when going on fullscreen. --- linphone-app/ui/views/App/Calls/Incall.qml | 1 - linphone-app/ui/views/App/Calls/IncallFullscreen.qml | 1 - 2 files changed, 2 deletions(-) diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index 4354dc512..00934308c 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -255,7 +255,6 @@ Rectangle { backgroundRadius: width/2 colorSet: IncallStyle.buttons.record property CallModel callModel: mainItem.callModel - onCallModelChanged: if(!callModel) callModel.stopRecording() visible: SettingsModel.callRecorderEnabled && callModel && (callModel.recording || mainItem.isReady) toggled: callModel.recording diff --git a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml index 61c223364..a1b5a8385 100644 --- a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml +++ b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml @@ -221,7 +221,6 @@ Window { backgroundRadius: width/2 colorSet: IncallStyle.buttons.record property CallModel callModel: conference.callModel - onCallModelChanged: if(callModel) callModel.stopRecording() visible: SettingsModel.callRecorderEnabled && callModel toggled: callModel && callModel.recording From 773b1053b9b607a45c0c02ddf6af5a74ecf12f2c Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 22 Nov 2022 16:30:52 +0100 Subject: [PATCH 39/61] Display participant address on clicking on one (Conference creation) --- linphone-app/ui/views/App/Dialog/NewConference.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linphone-app/ui/views/App/Dialog/NewConference.qml b/linphone-app/ui/views/App/Dialog/NewConference.qml index c84cced70..9048fac9d 100644 --- a/linphone-app/ui/views/App/Dialog/NewConference.qml +++ b/linphone-app/ui/views/App/Dialog/NewConference.qml @@ -557,7 +557,6 @@ DialogPlus { function removeParticipant(entry){ smartSearchBar.removeAddressToIgnore(entry.sipAddress) selectedParticipants.removeModel(entry) - ++lastContacts.reloadCount } @@ -579,7 +578,7 @@ DialogPlus { id:selectedParticipants chatRoomModel:null } - onEntryClicked: actions[0].handler(entry) + onEntryClicked: participantView.showSubtitle = !participantView.showSubtitle } } } From 149fe9ea8eac8e798f29308d3fb2076d9e91255b Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 22 Nov 2022 16:30:16 +0100 Subject: [PATCH 40/61] Synchronization between ICS and participants. --- .../src/components/conferenceInfo/ConferenceInfoModel.cpp | 1 + .../ui/modules/Linphone/Chat/ChatCalendarMessage.qml | 6 +++++- .../Linphone/Chat/ChatConferenceInvitationMessage.qml | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index b04ae22ba..0a8adb8b9 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -260,6 +260,7 @@ void ConferenceInfoModel::setDescription(const QString& description){ void ConferenceInfoModel::setParticipants(ParticipantListModel * participants){ mConferenceInfo->setParticipants(participants->getParticipants()); + emit participantsChanged(); } void ConferenceInfoModel::setTimeZoneModel(TimeZoneModel * model){ diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml index e7022c1f3..61a34add5 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml @@ -212,7 +212,11 @@ Loader{ Layout.alignment: Qt.AlignTop spacing: 0 visible: mainItem.isExpanded - onVisibleChanged: model= mainItem.conferenceInfoModel.getParticipants() + onVisibleChanged: visible ? model= mainItem.conferenceInfoModel.getParticipants() : model = [] + Connections{ + target: mainItem.conferenceInfoModel + onParticipantsChanged: if(expandedParticipantsList.visible) expandedParticipantsList.model = mainItem.conferenceInfoModel.getParticipants() + } delegate: Row{ spacing: 5 diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml index b17b651d1..cced32c2a 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml @@ -204,7 +204,11 @@ Loader{ Layout.leftMargin: 10 spacing: 0 visible: mainItem.isExpanded - onVisibleChanged: model= mainItem.conferenceInfoModel.getParticipants() + onVisibleChanged: visible ? model= mainItem.conferenceInfoModel.getParticipants() : model = [] + Connections{ + target: mainItem.conferenceInfoModel + onParticipantsChanged: if(expandedParticipantsList.visible) expandedParticipantsList.model = mainItem.conferenceInfoModel.getParticipants() + } delegate: Row{ spacing: 5 From c870daf53012b415f1cbbc592481d7d4aa0cb5f0 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Fri, 25 Nov 2022 17:40:04 +0100 Subject: [PATCH 41/61] Fix video crashes on changing layout. - Make as readonly the isVideoEnabled from Camera and let it to do its work. - Use deactivateCamera to temporary deactivate it (preveiw aswell). - Check audio only from callModel video layout. - Deactivate Camera Sticker when changing layout. - Temporize layout changes in order to let time to Qt to shutdown its objects, and to let the SDK to not use/reuse deleted Qt objects. - Dynamic load some items on Sticker only if needed. - Forbid to change layout if previous change has not been done. - Remove old clean layout functions. --- linphone-app/src/components/camera/Camera.cpp | 7 +- .../ui/modules/Linphone/Camera/CameraItem.qml | 11 ++- .../ui/modules/Linphone/Menus/IncallMenu.qml | 34 +++----- .../Linphone/Sticker/DecorationSticker.qml | 36 +++++--- .../ui/modules/Linphone/Sticker/Sticker.qml | 2 +- linphone-app/ui/views/App/Calls/Incall.qml | 82 +++++++++++++++---- .../views/App/Calls/IncallActiveSpeaker.qml | 12 +-- .../ui/views/App/Calls/IncallFullscreen.qml | 69 +++++++++++++--- .../ui/views/App/Calls/IncallGrid.qml | 6 -- 9 files changed, 172 insertions(+), 87 deletions(-) diff --git a/linphone-app/src/components/camera/Camera.cpp b/linphone-app/src/components/camera/Camera.cpp index 5f58d7046..bacbd5afd 100644 --- a/linphone-app/src/components/camera/Camera.cpp +++ b/linphone-app/src/components/camera/Camera.cpp @@ -44,6 +44,7 @@ int Camera::mPreviewCounter; // ============================================================================= Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) { + qDebug() << "[Camera] Camera constructor" << this; updateWindowIdLocation(); setTextureFollowsItemSize(true); // The fbo content must be y-mirrored because the ms rendering is y-inverted. @@ -66,9 +67,11 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) { Camera::~Camera(){ qDebug() << "[Camera] Camera destructor" << this; + mRefreshTimer->stop(); + if(mIsPreview) deactivatePreview(); - setWindowIdLocation(None); + setWindowIdLocation(None);// We need to remove the Qt Buffer from SDK ot avoid to reuse it. } void Camera::resetWindowId() const{ @@ -157,8 +160,6 @@ void Camera::removeParticipantDeviceModel(){ } QQuickFramebufferObject::Renderer *Camera::createRenderer () const { - resetWindowId(); - QQuickFramebufferObject::Renderer * renderer = NULL; if(mWindowIdLocation == CorePreview){ qDebug() << "[Camera] Setting Camera to Preview"; diff --git a/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml b/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml index dcb1ea77d..7e0d04d3b 100644 --- a/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml +++ b/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml @@ -22,10 +22,11 @@ Item { property bool isFullscreen: false property bool hideCamera: false property bool isPaused: false - property bool deactivateCamera: false + property bool deactivateCamera: true property bool isVideoEnabled: !deactivateCamera && (!callModel || callModel.videoEnabled) - && (!container.currentDevice || callModel && (container.currentDevice - && (container.currentDevice.videoEnabled || (container.currentDevice.isMe && callModel.cameraEnabled)))) + && (!container.currentDevice || ( callModel && container.currentDevice && + ( (!container.currentDevice.isMe && container.currentDevice.videoEnabled) + || (container.currentDevice.isMe && callModel.cameraEnabled)))) property bool a : callModel && callModel.videoEnabled property bool b: container.currentDevice && container.currentDevice.videoEnabled @@ -51,6 +52,10 @@ Item { anchors.fill: parent active: !resetActive && container.isVideoEnabled + onActiveChanged: { + console.log("QML Camera status : " + active) + } + sourceComponent: container.isVideoEnabled && !container.isPaused? camera : null Timer{ diff --git a/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml b/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml index 5a4a550f7..115b87b49 100644 --- a/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml +++ b/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml @@ -50,6 +50,14 @@ Rectangle{ onVisibleChanged: if(!visible && contentsStack.nViews > 1) { contentsStack.pop() } + property bool _activateCamera: false + Connections{// Enable camera only when status is ok + target: mainItem.callModel + onStatusChanged: if( mainItem._activateCamera && (status == LinphoneEnums.CallStatusConnected || status == LinphoneEnums.CallStatusIdle)){ + camera._activateCamera = false + callModel.cameraEnabled = true + } + } ButtonGroup{id: modeGroup} ColumnLayout{ anchors.fill: parent @@ -227,6 +235,7 @@ Rectangle{ bottomWidth: IncallMenuStyle.list.border.width Layout.preferredHeight: Math.max(layoutIcon.height, radio.contentItem.implicitHeight) + 20 Layout.fillWidth: true + enabled: mainItem.callModel && !mainItem.callModel.updating RowLayout{ anchors.fill: parent @@ -238,37 +247,16 @@ Rectangle{ Layout.alignment: Qt.AlignVCenter ButtonGroup.group: modeGroup text: modelData.text - property bool isInternallyChecked: mainItem.callModel ? (mainItem.callModel.localVideoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout) || (!mainItem.callModel.localVideoEnabled && modelData.value == LinphoneEnums.ConferenceLayoutAudioOnly) : false // break bind. Radiobutton checked itself without taking care of custom binding. This workaound works as long as we don't really need the binding. onIsInternallyCheckedChanged: checked = isInternallyChecked Component.onCompleted: checked = isInternallyChecked - Timer{ - id: changingLayoutDelay - interval: 100 - onTriggered: {if(modelData.value == 2) mainItem.callModel.videoEnabled = false - else { - mainItem.callModel.conferenceVideoLayout = modelData.value - mainItem.callModel.videoEnabled = true - } - mainItem.enabled = true - } - } - onClicked:{ - // Do changes only if we choose a different layout. - if(! ( mainItem.callModel ? (mainItem.callModel.localVideoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout) - || (!mainItem.callModel.localVideoEnabled && modelData.value == LinphoneEnums.ConferenceLayoutAudioOnly) - : false)){ - mainItem.enabled = false - mainItem.layoutChanging(modelData.value)// Let time to clear cameras - changingLayoutDelay.start() - } - } + onClicked: mainItem.layoutChanging(modelData.value) } Icon{ - id: layoutIcon + id: layoutIcon Layout.minimumWidth: iconWidth Layout.rightMargin: 10 Layout.alignment: Qt.AlignVCenter diff --git a/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml b/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml index 4e7410d7c..c00ed4779 100644 --- a/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml +++ b/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml @@ -101,15 +101,20 @@ Item{ color: "#80000000" source: usernameItem } - ActionButton{ - visible: mainItem._showCloseButton && mainItem._isPreview && mainItem._callModel && mainItem._callModel.videoEnabled + Loader{ + id: closeLoader anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 5 anchors.topMargin: 5 - isCustom: true - colorSet: DecorationStickerStyle.closePreview - onClicked: mainItem.closeRequested() + active: mainItem._showCloseButton && mainItem._isPreview && mainItem._callModel && mainItem._callModel.videoEnabled + sourceComponent: Component{ + ActionButton{ + isCustom: true + colorSet: DecorationStickerStyle.closePreview + onClicked: mainItem.closeRequested() + } + } } ColumnLayout{ anchors.top: parent.top @@ -137,17 +142,22 @@ Item{ iconSize: DecorationStickerStyle.isMuted.button.iconSize } } - BusyIndicator{// Joining spinner + Loader{ + id: busyLoader + property bool delayed : false Layout.preferredHeight: 20 Layout.preferredWidth: 20 - property bool delayed : false - visible: delayed && mainItem._currentDevice && (mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateScheduledForJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateAlerting) - Timer{// Delay starting spinner (Qt bug) - id: indicatorDelay - interval: 100 - onTriggered: parent.delayed = true + active: delayed && mainItem._currentDevice && (mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateScheduledForJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateAlerting) + sourceComponent: Component{ + BusyIndicator{// Joining spinner + Timer{// Delay starting spinner (Qt bug) + id: indicatorDelay + interval: 100 + onTriggered: busyLoader.delayed = true + } + Component.onCompleted: indicatorDelay.start() + } } - Component.onCompleted: indicatorDelay.start() } } } diff --git a/linphone-app/ui/modules/Linphone/Sticker/Sticker.qml b/linphone-app/ui/modules/Linphone/Sticker/Sticker.qml index 1cd2bee2f..7b9dae4d5 100644 --- a/linphone-app/ui/modules/Linphone/Sticker/Sticker.qml +++ b/linphone-app/ui/modules/Linphone/Sticker/Sticker.qml @@ -35,7 +35,7 @@ Item{ property alias showActiveSpeakerOverlay: camera.showActiveSpeakerOverlay property alias isCameraFromDevice: camera.isCameraFromDevice property alias deactivateCamera: camera.deactivateCamera - property alias isVideoEnabled: camera.isVideoEnabled + readonly property alias isVideoEnabled: camera.isVideoEnabled property alias image: avatar.image property alias avatarBackgroundColor: avatar.avatarBackgroundColor diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index 00934308c..94fb64b75 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -27,6 +27,7 @@ Rectangle { property bool cameraIsReady : false property bool previewIsReady : false property bool isFullScreen: false // Use this variable to test if we are in fullscreen. Do not test _fullscreen : we need to clean memory before having the window (see .js file) + property bool layoutChanging: false property var _fullscreen: null on_FullscreenChanged: if( !_fullscreen) isFullScreen = false @@ -40,7 +41,7 @@ Rectangle { : conferenceLayout.item ? conferenceLayout.item.participantCount : 2 // States - property bool isAudioOnly: callModel && callModel.isConference && conferenceLayout.sourceComponent == gridComponent && !callModel.videoEnabled + property bool isAudioOnly: callModel && callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutAudioOnly property bool isReady : mainItem.callModel && (!mainItem.callModel.isConference || (mainItem.conferenceModel && mainItem.conferenceModel.isReady) @@ -308,7 +309,7 @@ Rectangle { Layout.leftMargin: 70 Layout.rightMargin: rightMenu.visible ? 15 : 70 callModel: mainItem.callModel - cameraEnabled: !mainItem.isFullScreen + cameraEnabled: !mainItem.isFullScreen && !mainItem.layoutChanging } } Component{ @@ -318,7 +319,7 @@ Rectangle { callModel: mainItem.callModel isRightReducedLayout: rightMenu.visible isLeftReducedLayout: mainItem.listCallsOpened - cameraEnabled: !mainItem.isFullScreen + cameraEnabled: !mainItem.isFullScreen && !mainItem.layoutChanging } } RowLayout{ @@ -328,12 +329,50 @@ Rectangle { Layout.fillWidth: true Loader{ id: conferenceLayout - anchors.fill: parent - sourceComponent: mainItem.conferenceModel - ? mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker - ? activeSpeakerComponent - : gridComponent - : activeSpeakerComponent + anchors.fill: parent + + Timer{// Avoid Qt crashes when layout changes while videos are on + id: layoutDelay + interval: 100 + property int step : 0 + property var layoutMode + onTriggered: { + switch(step){ + case 2 : step = 0; mainItem.layoutChanging = false; break; + case 1: ++step; conferenceLayout.sourceComponent = conferenceLayout.getLayout(); layoutDelay.restart(); break; + case 0: if( mainItem.callModel.conferenceVideoLayout != layoutMode) + mainItem.callModel.conferenceVideoLayout = layoutMode + else { + ++step; + layoutDelay.restart() + } + break; + } + } + function begin(layoutMode){ + step = 0 + layoutDelay.layoutMode = layoutMode + mainItem.layoutChanging = true + layoutDelay.restart() + } + } + function getLayout(){ + return mainItem.conferenceModel + ? mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker + ? activeSpeakerComponent + : gridComponent + : activeSpeakerComponent + } + + Connections{ + target: mainItem.callModel + + onConferenceVideoLayoutChanged: { + layoutDelay.layoutMode = mainItem.callModel.conferenceVideoLayout + layoutDelay.restart() + } + } + sourceComponent: getLayout() active: mainItem.callModel && !mainItem.isFullScreen } Rectangle{ @@ -342,12 +381,16 @@ Rectangle { visible: !mainItem.isReady ColumnLayout { anchors.fill: parent - BusyIndicator{ + Loader{ Layout.preferredHeight: 40 Layout.preferredWidth: 40 Layout.alignment: Qt.AlignCenter - running: parent.visible - color: IncallStyle.buzyColor + active: parent.visible + sourceComponent: Component{ + BusyIndicator{ + color: IncallStyle.buzyColor + } + } } Text{ Layout.alignment: Qt.AlignCenter @@ -370,8 +413,11 @@ Rectangle { callModel: mainItem.callModel conferenceModel: mainItem.conferenceModel visible: false + enabled: !mainItem.layoutChanging onClose: rightMenu.visible = !rightMenu.visible - onLayoutChanging: conferenceLayout.item.clearAll(layoutMode) + onLayoutChanging: { + layoutDelay.begin(layoutMode) + } } } } @@ -487,14 +533,14 @@ Rectangle { isCustom: true backgroundRadius: 90 colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff - updating: callModel.videoEnabled && callModel.updating + updating: callModel.videoEnabled && callModel.updating && !mainItem.layoutChanging property bool _activateCamera: false - onClicked: if(callModel){ + onClicked: if(callModel && !mainItem.layoutChanging){ if( callModel.isConference){// Only deactivate camera in conference. - if(mainItem.isAudioOnly && SettingsModel.videoConferenceLayout != 2) { + if(mainItem.isAudioOnly) { + var layout = SettingsModel.videoConferenceLayout != LinphoneEnums.ConferenceLayoutAudioOnly ? SettingsModel.videoConferenceLayout : LinphoneEnums.ConferenceLayoutGrid + layoutDelay.being(layout) camera._activateCamera = true - conferenceLayout.item.clearAll(SettingsModel.videoConferenceLayout) - callModel.conferenceVideoLayout = SettingsModel.videoConferenceLayout }else callModel.cameraEnabled = !callModel.cameraEnabled }else{// In one-one, we deactivate all videos. diff --git a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml index 47d84a931..3a0e10a68 100644 --- a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml +++ b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml @@ -37,12 +37,6 @@ Item { onConferenceCreated: cameraView.resetCamera() } - function clearAll(layoutMode){ - if( layoutMode != LinphoneEnums.ConferenceLayoutActiveSpeaker){ - mainItem.cameraEnabled = false - miniViews.model = [] - } - } Sticker{ id: cameraView anchors.fill: parent @@ -54,7 +48,7 @@ Item { : callModel.isConference ? allDevices.activeSpeaker : null - deactivateCamera: isPreview && callModel.pausedByUser + deactivateCamera: !mainItem.cameraEnabled || (isPreview && callModel.pausedByUser) ? true : callModel.isConference ? (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused) ) @@ -63,8 +57,6 @@ Item { || !mainItem.isConferenceReady : (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused || !callModel.videoEnabled) ) || currentDevice && !currentDevice.videoEnabled - - isVideoEnabled: !deactivateCamera isPreview: !preview.visible && mainItem.participantCount == 1 onIsPreviewChanged: {cameraView.resetCamera() } isCameraFromDevice: isPreview @@ -101,7 +93,7 @@ Item { sourceComponent: Sticker{ id: previewSticker - deactivateCamera: !mainItem.callModel || callModel.pausedByUser || !mainItem.callModel.cameraEnabled + deactivateCamera: !mainItem.cameraEnabled || !mainItem.callModel || callModel.pausedByUser || !mainItem.callModel.cameraEnabled currentDevice: allDevices.me isPreview: true callModel: mainItem.callModel diff --git a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml index a1b5a8385..081fc1754 100644 --- a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml +++ b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml @@ -68,6 +68,9 @@ Window { property ConferenceModel conferenceModel: callModel && callModel.conferenceModel property var _fullscreen: null property bool listCallsOpened: false + property bool layoutChanging: false + + property bool isAudioOnly: callModel && callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutAudioOnly signal openListCallsRequest() // --------------------------------------------------------------------------- @@ -238,7 +241,7 @@ Window { isCustom: true backgroundRadius: width/2 colorSet: IncallStyle.buttons.screenshot - visible: SettingsModel.incallScreenshotEnabled && conference.callModel && (!conference.callModel.isConference || mainItem.callModel.snapshotEnabled) + visible: SettingsModel.incallScreenshotEnabled && conference.callModel && (!conference.callModel.isConference || window.callModel.snapshotEnabled) onClicked: conference.callModel && conference.callModel.takeSnapshot() //: 'Take Snapshot' : Tooltip for takking snapshot. tooltipText: qsTr('incallSnapshotTooltip') @@ -279,6 +282,7 @@ Window { Layout.leftMargin: window.hideButtons ? 15 : 70 Layout.rightMargin: rightMenu.visible ? 15 : 70 callModel: conference.callModel + cameraEnabled: !conference.layoutChanging } } Component{ @@ -286,6 +290,7 @@ Window { IncallActiveSpeaker{ id: activeSpeaker callModel: conference.callModel + cameraEnabled: !conference.layoutChanging isRightReducedLayout: rightMenu.visible isLeftReducedLayout: conference.listCallsOpened } @@ -297,13 +302,48 @@ Window { Layout.fillHeight: true Layout.fillWidth: true - sourceComponent: conference.callModel - ? conference.conferenceModel - ? conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker - ? activeSpeakerComponent - : gridComponent - : activeSpeakerComponent - : null + Timer{// Avoid Qt crashes when layout changes while videos are on + id: layoutDelay + interval: 100 + property int step : 0 + property var layoutMode + onTriggered: { + switch(step){ + case 2 : step = 0; conference.layoutChanging = false; break; + case 1: ++step; conferenceLayout.sourceComponent = conferenceLayout.getLayout(); layoutDelay.restart(); break; + case 0: if( conference.callModel.conferenceVideoLayout != layoutMode) + conference.callModel.conferenceVideoLayout = layoutMode + else { + ++step; + layoutDelay.restart() + } + break; + } + } + function begin(layoutMode){ + step = 0 + layoutDelay.layoutMode = layoutMode + conference.layoutChanging = true + layoutDelay.restart() + } + } + function getLayout(){ + return conference.conferenceModel + ? conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker + ? activeSpeakerComponent + : gridComponent + : activeSpeakerComponent + } + + Connections{ + target: conference.callModel + + onConferenceVideoLayoutChanged: { + layoutDelay.layoutMode = conference.callModel.conferenceVideoLayout + layoutDelay.restart() + } + } + sourceComponent: getLayout() active: conference.callModel ColumnLayout { anchors.fill: parent @@ -332,6 +372,9 @@ Window { conferenceModel: conference.conferenceModel visible: false onClose: rightMenu.visible = !rightMenu.visible + onLayoutChanging: { + layoutDelay.begin(layoutMode) + } } } } @@ -450,8 +493,14 @@ Window { backgroundRadius: 90 colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff updating: callModel && callModel.videoEnabled && callModel.updating - enabled: callModel && callModel.videoEnabled - onClicked: if(callModel) callModel.cameraEnabled = !callModel.cameraEnabled + onClicked: if(callModel && !conference.layoutChanging){ + if( callModel.isConference){// Only deactivate camera in conference. + callModel.cameraEnabled = !callModel.cameraEnabled + }else{// In one-one, we deactivate all videos. + if(callModel.videoEnabled ) Qt.callLater(function(){window.exit()}) + callModel.videoEnabled = !callModel.videoEnabled + } + } } } RowLayout{ diff --git a/linphone-app/ui/views/App/Calls/IncallGrid.qml b/linphone-app/ui/views/App/Calls/IncallGrid.qml index 1369bf7ec..56685c608 100644 --- a/linphone-app/ui/views/App/Calls/IncallGrid.qml +++ b/linphone-app/ui/views/App/Calls/IncallGrid.qml @@ -27,12 +27,6 @@ Mosaic { // On grid view, we limit the quality if there are enough participants// The vga mode has been activated from the factory rc //onParticipantCountChanged: participantCount > ConstantsCpp.maxMosaicParticipants ? SettingsModel.setLimitedMosaicQuality() : SettingsModel.setHighMosaicQuality() - function clearAll(layoutMode){ - if( layoutMode != 2 && layoutMode != LinphoneEnums.ConferenceLayoutGrid){ - clear() - gridModel.model = [] - } - } delegateModel: DelegateModel{ id: gridModel property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel { From 53abdf6f063a3c2e5f51d7f83a2a61556d345d32 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Fri, 25 Nov 2022 17:41:46 +0100 Subject: [PATCH 42/61] Fix participant devices leaks. --- linphone-app/src/app/proxyModel/ProxyModel.cpp | 13 +++++++++++++ linphone-app/src/app/proxyModel/ProxyModel.hpp | 5 +++++ .../app/proxyModel/SortFilterProxyModel.cpp | 13 +++++++++++++ .../app/proxyModel/SortFilterProxyModel.hpp | 3 +++ .../chat-room/ChatRoomProxyModel.cpp | 1 + .../conference/ConferenceProxyModel.cpp | 1 + .../other/timeZone/TimeZoneProxyModel.cpp | 1 + .../ParticipantDeviceProxyModel.cpp | 18 ++++++++++++------ .../ParticipantDeviceProxyModel.hpp | 2 +- 9 files changed, 50 insertions(+), 7 deletions(-) diff --git a/linphone-app/src/app/proxyModel/ProxyModel.cpp b/linphone-app/src/app/proxyModel/ProxyModel.cpp index 9734c7ff2..d47472a0c 100644 --- a/linphone-app/src/app/proxyModel/ProxyModel.cpp +++ b/linphone-app/src/app/proxyModel/ProxyModel.cpp @@ -35,6 +35,19 @@ ProxyModel::ProxyModel (QAbstractItemModel * model, const int& defaultFilterMode sort(0, Qt::DescendingOrder); } +ProxyModel::~ProxyModel(){ + if(mDeleteSourceModel) + deleteSourceModel(); +} + +void ProxyModel::deleteSourceModel(){ + auto oldSourceModel = sourceModel(); + if(oldSourceModel) { + oldSourceModel->deleteLater(); + setSourceModel(nullptr); + } +} + int ProxyModel::getFilterMode () const { return mFilterMode; } diff --git a/linphone-app/src/app/proxyModel/ProxyModel.hpp b/linphone-app/src/app/proxyModel/ProxyModel.hpp index d85e950b8..a85bb45bb 100644 --- a/linphone-app/src/app/proxyModel/ProxyModel.hpp +++ b/linphone-app/src/app/proxyModel/ProxyModel.hpp @@ -35,6 +35,9 @@ public: ProxyModel (QObject *parent = Q_NULLPTR); ProxyModel (QAbstractItemModel * list, const int& defaultFilterMode, QObject *parent = Q_NULLPTR); + virtual ~ProxyModel(); + + virtual void deleteSourceModel(); int getFilterMode () const; void setFilterMode (int filterMode); @@ -56,6 +59,8 @@ protected: bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; + bool mDeleteSourceModel = false; + private: int mFilterMode; }; diff --git a/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp b/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp index f60c5149f..cc4da2f43 100644 --- a/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp +++ b/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp @@ -26,6 +26,19 @@ SortFilterProxyModel::SortFilterProxyModel(QObject * parent) : QSortFilterProxyM connect(this, &SortFilterProxyModel::rowsRemoved, this, &SortFilterProxyModel::countChanged); } +SortFilterProxyModel::~SortFilterProxyModel(){ + if(mDeleteSourceModel) + deleteSourceModel(); +} + +void SortFilterProxyModel::deleteSourceModel(){ + auto oldSourceModel = sourceModel(); + if(oldSourceModel) { + oldSourceModel->deleteLater(); + setSourceModel(nullptr); + } +} + int SortFilterProxyModel::getCount() const{ return rowCount(); } diff --git a/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp b/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp index 518593faa..e0df17682 100644 --- a/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp +++ b/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp @@ -30,6 +30,8 @@ public: Q_PROPERTY(int filterType READ getFilterType WRITE setFilterType NOTIFY filterTypeChanged) SortFilterProxyModel(QObject * parent = nullptr); + virtual ~SortFilterProxyModel(); + virtual void deleteSourceModel(); virtual int getCount() const; virtual int getFilterType () const; @@ -47,6 +49,7 @@ signals: protected: int mFilterType; + bool mDeleteSourceModel = false; }; #endif diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp index 50526b763..fd37071b3 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp @@ -57,6 +57,7 @@ ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel } ChatRoomProxyModel::~ChatRoomProxyModel(){ + setSourceModel(nullptr); setChatRoomModel(nullptr); // Do remove process like setting haveCall if is Call. } diff --git a/linphone-app/src/components/conference/ConferenceProxyModel.cpp b/linphone-app/src/components/conference/ConferenceProxyModel.cpp index a2a922a13..bf028b98b 100644 --- a/linphone-app/src/components/conference/ConferenceProxyModel.cpp +++ b/linphone-app/src/components/conference/ConferenceProxyModel.cpp @@ -38,6 +38,7 @@ using namespace std; ConferenceProxyModel::ConferenceProxyModel (QObject *parent) : SortFilterProxyModel(parent) { + mDeleteSourceModel = false; setSourceModel(CoreManager::getInstance()->getCallsListModel()); emit conferenceChanged(); diff --git a/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp index 0d837c0a9..514a7f031 100644 --- a/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp +++ b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp @@ -27,6 +27,7 @@ // ----------------------------------------------------------------------------- TimeZoneProxyModel::TimeZoneProxyModel (QObject *parent) : SortFilterProxyModel(parent) { + mDeleteSourceModel = true; setSourceModel(new TimeZoneListModel(parent)); sort(0); } diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp index 272c25480..b29b4c6bd 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp @@ -31,6 +31,10 @@ // ============================================================================= ParticipantDeviceProxyModel::ParticipantDeviceProxyModel (QObject *parent) : SortFilterProxyModel(parent){ + mDeleteSourceModel = true; +} + +ParticipantDeviceProxyModel::~ParticipantDeviceProxyModel(){ } bool ParticipantDeviceProxyModel::filterAcceptsRow ( @@ -85,18 +89,20 @@ void ParticipantDeviceProxyModel::connectTo(ParticipantDeviceListModel* model){ void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){ setFilterType(1); mCallModel = callModel; - auto sourceModel = new ParticipantDeviceListModel(mCallModel); - connectTo(sourceModel); - setSourceModel(sourceModel); + deleteSourceModel(); + auto newSourceModel = new ParticipantDeviceListModel(mCallModel); + connectTo(newSourceModel); + setSourceModel(newSourceModel); emit countChanged(); emit meChanged(); } void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant){ setFilterType(0); - auto sourceModel = participant->getParticipantDevices().get(); - connectTo(sourceModel); - setSourceModel(sourceModel); + deleteSourceModel(); + auto newSourceModel = participant->getParticipantDevices().get(); + connectTo(newSourceModel); + setSourceModel(newSourceModel); emit countChanged(); emit meChanged(); } diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp index 9a939ac53..dfa0b885f 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp @@ -45,6 +45,7 @@ public: Q_PROPERTY(ParticipantDeviceModel* activeSpeaker READ getActiveSpeakerModel NOTIFY activeSpeakerChanged) ParticipantDeviceProxyModel (QObject *parent = nullptr); + ~ParticipantDeviceProxyModel(); Q_INVOKABLE ParticipantDeviceModel* getAt(int row); ParticipantDeviceModel* getActiveSpeakerModel(); @@ -76,7 +77,6 @@ protected: virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; virtual bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; - QSharedPointer mDevices; CallModel * mCallModel; bool mShowMe = true; }; From 70857601ffe87ab130bc995223b33a2c4236600f Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Fri, 25 Nov 2022 17:42:42 +0100 Subject: [PATCH 43/61] Display hand cursor on radio buttons. Expand click size area on radiobuttons in call menu. --- .../ui/modules/Common/Form/RadioButton.qml | 8 ++++++++ .../ui/modules/Linphone/Menus/IncallMenu.qml | 15 +++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/linphone-app/ui/modules/Common/Form/RadioButton.qml b/linphone-app/ui/modules/Common/Form/RadioButton.qml index 8b27a6d10..449df7852 100644 --- a/linphone-app/ui/modules/Common/Form/RadioButton.qml +++ b/linphone-app/ui/modules/Common/Form/RadioButton.qml @@ -17,6 +17,14 @@ Control.RadioButton{ font.pointSize: RadioButtonStyle.pointSize spacing: 10 FontMetrics{id: fontMetrics} + + MouseArea{ + anchors.fill:parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor + } + indicator: Rectangle { height: fontMetrics.height - 5 width: height diff --git a/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml b/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml index 115b87b49..3a1bf0529 100644 --- a/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml +++ b/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml @@ -166,13 +166,16 @@ Rectangle{ font.pointSize: IncallMenuStyle.list.pointSize color: IncallMenuStyle.list.color } - ActionButton{ + Icon{ Layout.minimumWidth: iconWidth Layout.rightMargin: 10 Layout.alignment: Qt.AlignVCenter - backgroundRadius: width/2 - isCustom: true - colorSet: IncallMenuStyle.buttons.next + //backgroundRadius: width/2 + + icon: IncallMenuStyle.buttons.next.icon + overwriteColor: IncallMenuStyle.buttons.next.backgroundNormalColor + iconWidth: IncallMenuStyle.buttons.next.iconSize + iconHeight: IncallMenuStyle.buttons.next.iconSize } } MouseArea{ @@ -236,6 +239,10 @@ Rectangle{ Layout.preferredHeight: Math.max(layoutIcon.height, radio.contentItem.implicitHeight) + 20 Layout.fillWidth: true enabled: mainItem.callModel && !mainItem.callModel.updating + MouseArea{ + anchors.fill: parent + onClicked: radio.clicked() + } RowLayout{ anchors.fill: parent From 6c1a865b4469630ea865d3ef34bf181e68f4fd66 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Fri, 25 Nov 2022 17:43:56 +0100 Subject: [PATCH 44/61] Update SDK for crash fix on preview. --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 635a5b9c2..730cd63c7 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 635a5b9c2ef7951ce94c422352274c2b7685c215 +Subproject commit 730cd63c7564cc02d5f239764d41ccf5273a168f From 6ad3f0fdd97c6c03a5973bccb049f0ef633f3073 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 28 Nov 2022 10:21:45 +0100 Subject: [PATCH 45/61] Fix black preview camera in Settings. --- linphone-app/ui/modules/Linphone/Camera/CameraView.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/linphone-app/ui/modules/Linphone/Camera/CameraView.qml b/linphone-app/ui/modules/Linphone/Camera/CameraView.qml index 42cd2e201..9d1e00139 100644 --- a/linphone-app/ui/modules/Linphone/Camera/CameraView.qml +++ b/linphone-app/ui/modules/Linphone/Camera/CameraView.qml @@ -79,6 +79,7 @@ Item{ anchors.fill: parent visible: false onVideoDefinitionChanged: mainItem.videoDefinitionChanged() + deactivateCamera: false } OpacityMask{ id: renderedCamera From 8b055b358750afd62dd057875573ae6de1f1e800 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 28 Nov 2022 10:22:48 +0100 Subject: [PATCH 46/61] Feature : Setting audio devices while being incall. (Update from SDK) --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 730cd63c7..475232c30 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 730cd63c7564cc02d5f239764d41ccf5273a168f +Subproject commit 475232c309b0683f0339027712e0403d4fc9fc84 From 05e7ada86eb8c9440bc2a81bddda6f4655d0ed2c Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 1 Dec 2022 11:21:18 +0100 Subject: [PATCH 47/61] Fix spinner for joining participants. --- .../ui/modules/Linphone/Sticker/DecorationSticker.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml b/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml index c00ed4779..f45b33449 100644 --- a/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml +++ b/linphone-app/ui/modules/Linphone/Sticker/DecorationSticker.qml @@ -144,16 +144,18 @@ Item{ } Loader{ id: busyLoader - property bool delayed : false + Layout.preferredHeight: 20 Layout.preferredWidth: 20 - active: delayed && mainItem._currentDevice && (mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateScheduledForJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateAlerting) + active: mainItem._currentDevice && (mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateScheduledForJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateAlerting) sourceComponent: Component{ BusyIndicator{// Joining spinner + id: joiningSpinner + running: false Timer{// Delay starting spinner (Qt bug) id: indicatorDelay interval: 100 - onTriggered: busyLoader.delayed = true + onTriggered: joiningSpinner.running = true } Component.onCompleted: indicatorDelay.start() } From 5b5268ff6055052c84811c3e8dc9c390913c6be8 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 1 Dec 2022 11:25:52 +0100 Subject: [PATCH 48/61] Rework of chat room creations for selections. - Avoid to select a chat room that is creating/terminating. - Add a loading spinner when the state of the chat room is updating. - On creation, wait on chat room state before automatically selecting it. --- .../src/components/calls/CallsListModel.cpp | 4 +--- .../chat-room/ChatRoomInitializer.cpp | 4 ++-- .../chat-room/ChatRoomInitializer.hpp | 3 ++- .../components/chat-room/ChatRoomModel.cpp | 9 +++++-- .../components/chat-room/ChatRoomModel.hpp | 10 ++++++-- .../components/timeline/TimelineListModel.cpp | 5 +++- .../src/components/timeline/TimelineModel.cpp | 24 +++++++++++++++++++ .../src/components/timeline/TimelineModel.hpp | 8 +++++++ linphone-app/src/utils/LinphoneEnums.cpp | 9 +++++++ linphone-app/src/utils/LinphoneEnums.hpp | 22 +++++++++++++++-- .../ui/modules/Linphone/Contact/Contact.qml | 22 +++++++++++++++++ .../Linphone/Timeline/TimelineItem.qml | 5 ++-- .../ui/views/App/Main/ContactEdit.qml | 2 +- 13 files changed, 111 insertions(+), 16 deletions(-) diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp index 924960e97..c858c25fa 100644 --- a/linphone-app/src/components/calls/CallsListModel.cpp +++ b/linphone-app/src/components/calls/CallsListModel.cpp @@ -355,9 +355,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = false; result["chatRoomModel"] = QVariant::fromValue(timeline->getChatRoomModel()); if(selectAfterCreation) {// The timeline here will not receive the first creation event. Set Selected if needed - QTimer::singleShot(200, [timeline](){// Delay process in order to let GUI time for Timeline building/linking before doing actions - timeline->setSelected(true); - }); + timeline->delaySelected(); } } } diff --git a/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp b/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp index 8139f3fc3..97d5c682e 100644 --- a/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp @@ -83,7 +83,7 @@ void ChatRoomInitializer::setAdmins(QList< std::shared_ptr> a void ChatRoomInitializer::start(QSharedPointer initializer){ QObject * context = new QObject(); - QObject::connect(initializer.get(), &ChatRoomInitializer::finished, context, [context, initializer](int state){ + QObject::connect(initializer.get(), &ChatRoomInitializer::finished, context, [context, initializer](LinphoneEnums::ChatRoomState state){ qDebug() << "[ChatRoomInitializer] initialized"; context->deleteLater();// This will destroy context and initializer }); @@ -93,7 +93,7 @@ void ChatRoomInitializer::checkInitialization(){ if( mAdmins.size() > 0 && !mAdminsSet) return; - emit finished((int)mChatRoom->getState()); + emit finished(LinphoneEnums::fromLinphone(mChatRoom->getState())); } void ChatRoomInitializer::onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) { diff --git a/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp b/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp index 3e2efd470..d7852fece 100644 --- a/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp @@ -24,6 +24,7 @@ #include #include "ChatRoomInitializer.hpp" +#include "utils/LinphoneEnums.hpp" #include @@ -54,7 +55,7 @@ public: virtual void onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState); signals: - void finished(int state); // this signal is emit before deletion and give the current linphone::ChatRoom:State of the chat room. + void finished(LinphoneEnums::ChatRoomState state); // this signal is emit before deletion and give the current linphone::ChatRoom:State of the chat room. private: void connectTo(ChatRoomListener * listener); diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 56249f197..725ca62d0 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -149,6 +149,7 @@ ChatRoomModel::ChatRoomModel (const std::shared_ptr& chatRoo QObject::connect(coreManager->getContactsListModel(), &ContactsListModel::contactUpdated, this, &ChatRoomModel::avatarChanged); connect(this, &ChatRoomModel::fullPeerAddressChanged, this, &ChatRoomModel::usernameChanged); + connect(this, &ChatRoomModel::stateChanged, this, &ChatRoomModel::updatingChanged); if(mChatRoom){ mParticipantListModel = QSharedPointer::create(this); @@ -404,8 +405,8 @@ std::list> ChatRoomModel::getParticipants return participantList; } -int ChatRoomModel::getState() const { - return mChatRoom ? (int)mChatRoom->getState() : 0; +LinphoneEnums::ChatRoomState ChatRoomModel::getState() const { + return mChatRoom ? LinphoneEnums::fromLinphone(mChatRoom->getState()) : LinphoneEnums::ChatRoomStateNone; } bool ChatRoomModel::isReadOnly() const{ @@ -481,6 +482,10 @@ bool ChatRoomModel::isBasic() const{ return mChatRoom && mChatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic); } +bool ChatRoomModel::isUpdating() const{ + return getState() == LinphoneEnums::ChatRoomStateCreationPending || getState() == LinphoneEnums::ChatRoomStateTerminationPending; +} + std::shared_ptr ChatRoomModel::getChatRoom(){ return mChatRoom; } diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index 9ec963137..962054cc4 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -25,6 +25,8 @@ #include "app/proxyModel/ProxyListModel.hpp" #include +#include "utils/LinphoneEnums.hpp" + // ============================================================================= // Fetch all N messages of a ChatRoom. // ============================================================================= @@ -73,13 +75,14 @@ public: Q_PROPERTY(bool isComposing READ getIsRemoteComposing NOTIFY isRemoteComposingChanged) Q_PROPERTY(QList composers READ getComposers NOTIFY isRemoteComposingChanged) Q_PROPERTY(bool isReadOnly READ isReadOnly NOTIFY isReadOnlyChanged) + Q_PROPERTY(bool updating READ isUpdating NOTIFY updatingChanged) Q_PROPERTY(QString sipAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged) Q_PROPERTY(QString sipAddressUriOnly READ getPeerAddress NOTIFY fullPeerAddressChanged) Q_PROPERTY(QString username READ getUsername NOTIFY usernameChanged) Q_PROPERTY(QString avatar READ getAvatar NOTIFY avatarChanged) Q_PROPERTY(int presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged) - Q_PROPERTY(int state READ getState NOTIFY stateChanged) + Q_PROPERTY(LinphoneEnums::ChatRoomState state READ getState NOTIFY stateChanged) Q_PROPERTY(long ephemeralLifetime READ getEphemeralLifetime WRITE setEphemeralLifetime NOTIFY ephemeralLifetimeChanged) Q_PROPERTY(bool ephemeralEnabled READ isEphemeralEnabled WRITE setEphemeralEnabled NOTIFY ephemeralEnabledChanged) @@ -116,7 +119,7 @@ public: QString getUsername () const; QString getAvatar () const; int getPresenceStatus() const; - int getState() const; + LinphoneEnums::ChatRoomState getState() const; bool isReadOnly() const; bool isEphemeralEnabled() const; long getEphemeralLifetime() const; @@ -135,6 +138,8 @@ public: bool getIsRemoteComposing () const; bool isEntriesLoading() const; bool isBasic() const; + bool isUpdating() const; + ParticipantListModel* getParticipantListModel() const; std::list> getParticipants(const bool& withMe = true) const; std::shared_ptr getChatRoom(); @@ -273,6 +278,7 @@ signals: void markAsReadEnabledChanged(); void chatRoomDeleted();// Must be connected with DirectConnection mode void replyChanged(); + void updatingChanged(); // Chat Room listener callbacks diff --git a/linphone-app/src/components/timeline/TimelineListModel.cpp b/linphone-app/src/components/timeline/TimelineListModel.cpp index 68a26b0b0..7d5d48f55 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.cpp +++ b/linphone-app/src/components/timeline/TimelineListModel.cpp @@ -328,7 +328,10 @@ void TimelineListModel::select(ChatRoomModel * chatRoomModel){ if(chatRoomModel) { auto timeline = getTimeline(chatRoomModel->getChatRoom(), false); if(timeline){ - timeline->setSelected(true); + if(timeline->isUpdating()) + timeline->delaySelected(); + else + timeline->setSelected(true); } } } diff --git a/linphone-app/src/components/timeline/TimelineModel.cpp b/linphone-app/src/components/timeline/TimelineModel.cpp index 68f020fe9..2cccb3a21 100644 --- a/linphone-app/src/components/timeline/TimelineModel.cpp +++ b/linphone-app/src/components/timeline/TimelineModel.cpp @@ -87,6 +87,8 @@ TimelineModel::TimelineModel (std::shared_ptr chatRoom, cons QObject::connect(this, &TimelineModel::selectedChanged, this, &TimelineModel::updateUnreadCount); QObject::connect(CoreManager::getInstance()->getAccountSettingsModel(), &AccountSettingsModel::defaultAccountChanged, this, &TimelineModel::onDefaultAccountChanged); QObject::connect(mChatRoomModel.get(), &ChatRoomModel::chatRoomDeleted, this, &TimelineModel::onChatRoomDeleted); + QObject::connect(mChatRoomModel.get(), &ChatRoomModel::updatingChanged, this, &TimelineModel::updatingChanged); + QObject::connect(mChatRoomModel.get(), &ChatRoomModel::stateChanged, this, &TimelineModel::onChatRoomStateChanged); } if(chatRoom){ mChatRoomListener = std::make_shared(); @@ -103,6 +105,8 @@ TimelineModel::TimelineModel(const TimelineModel * model){ QObject::connect(this, &TimelineModel::selectedChanged, this, &TimelineModel::updateUnreadCount); QObject::connect(CoreManager::getInstance()->getAccountSettingsModel(), &AccountSettingsModel::defaultAccountChanged, this, &TimelineModel::onDefaultAccountChanged); QObject::connect(mChatRoomModel.get(), &ChatRoomModel::chatRoomDeleted, this, &TimelineModel::onChatRoomDeleted); + QObject::connect(mChatRoomModel.get(), &ChatRoomModel::updatingChanged, this, &TimelineModel::updatingChanged); + QObject::connect(mChatRoomModel.get(), &ChatRoomModel::stateChanged, this, &TimelineModel::onChatRoomStateChanged); } if(mChatRoomModel->getChatRoom()){ mChatRoomListener = model->mChatRoomListener; @@ -141,6 +145,10 @@ int TimelineModel::getPresenceStatus() const{ return 0; } +bool TimelineModel::isUpdating() const{ + return !mChatRoomModel || mChatRoomModel->isUpdating(); +} + ChatRoomModel *TimelineModel::getChatRoomModel() const{ return mChatRoomModel.get(); } @@ -165,6 +173,15 @@ void TimelineModel::setSelected(const bool& selected){ } } +void TimelineModel::delaySelected(){ + if( mChatRoomModel->getState() == LinphoneEnums::ChatRoomStateCreated){ + QTimer::singleShot(200, [&](){// Delay process in order to let GUI time for Timeline building/linking before doing actions + setSelected(true); + }); + }else + mDelaySelection = true; +} + void TimelineModel::updateUnreadCount(){ if(!mSelected){// updateUnreadCount is called when selected has changed;: So if mSelected is false then we are going out of it. mChatRoomModel->resetMessageCount();// The reset will appear when the chat room has "mark as read enabled", that means that we should have read messages when going out. @@ -230,4 +247,11 @@ void TimelineModel::onChatMessageParticipantImdnStateChanged(const std::shared_p void TimelineModel::onChatRoomDeleted(){ emit chatRoomDeleted(); +} + +void TimelineModel::onChatRoomStateChanged(){ + if(mDelaySelection && mChatRoomModel->getState() == LinphoneEnums::ChatRoomStateCreated){ + mDelaySelection = false; + setSelected(true); + } } \ No newline at end of file diff --git a/linphone-app/src/components/timeline/TimelineModel.hpp b/linphone-app/src/components/timeline/TimelineModel.hpp index 1c33560e1..34cc2a044 100644 --- a/linphone-app/src/components/timeline/TimelineModel.hpp +++ b/linphone-app/src/components/timeline/TimelineModel.hpp @@ -52,6 +52,7 @@ public: Q_PROPERTY(ChatRoomModel* chatRoomModel READ getChatRoomModel CONSTANT) Q_PROPERTY(bool selected MEMBER mSelected WRITE setSelected NOTIFY selectedChanged) + Q_PROPERTY(bool updating READ isUpdating NOTIFY updatingChanged) QString getFullPeerAddress() const; @@ -61,7 +62,10 @@ public: QString getAvatar() const; int getPresenceStatus() const; + bool isUpdating() const; + void setSelected(const bool& selected); + void delaySelected(); Q_INVOKABLE ChatRoomModel* getChatRoomModel() const; @@ -102,6 +106,7 @@ public slots: void updateUnreadCount(); void onDefaultAccountChanged(); void onChatRoomDeleted(); + void onChatRoomStateChanged(); signals: void fullPeerAddressChanged(); @@ -112,9 +117,12 @@ signals: void selectedChanged(bool selected); void conferenceLeft(); void chatRoomDeleted(); + void updatingChanged(); private: + bool mDelaySelection = false; + void connectTo(ChatRoomListener * listener); std::shared_ptr mChatRoomListener; diff --git a/linphone-app/src/utils/LinphoneEnums.cpp b/linphone-app/src/utils/LinphoneEnums.cpp index e15cc1395..5b8aa6a7a 100644 --- a/linphone-app/src/utils/LinphoneEnums.cpp +++ b/linphone-app/src/utils/LinphoneEnums.cpp @@ -27,6 +27,7 @@ void LinphoneEnums::registerMetaTypes(){ qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); @@ -67,6 +68,14 @@ LinphoneEnums::ChatMessageState LinphoneEnums::fromLinphone(const linphone::Chat return static_cast(data); } +linphone::ChatRoom::State LinphoneEnums::toLinphone(const LinphoneEnums::ChatRoomState& data){ + return static_cast(data); +} + +LinphoneEnums::ChatRoomState LinphoneEnums::fromLinphone(const linphone::ChatRoom::State& data){ + return static_cast(data); +} + linphone::Call::Status LinphoneEnums::toLinphone(const LinphoneEnums::CallStatus& data){ return static_cast(data); } diff --git a/linphone-app/src/utils/LinphoneEnums.hpp b/linphone-app/src/utils/LinphoneEnums.hpp index f3bffccf0..4fed4a75c 100644 --- a/linphone-app/src/utils/LinphoneEnums.hpp +++ b/linphone-app/src/utils/LinphoneEnums.hpp @@ -95,8 +95,25 @@ enum ChatMessageState { }; Q_ENUM_NS(ChatMessageState) -linphone::ChatMessage::State toLinphone(const LinphoneEnums::ChatMessageState& capability); -LinphoneEnums::ChatMessageState fromLinphone(const linphone::ChatMessage::State& capability); +linphone::ChatMessage::State toLinphone(const LinphoneEnums::ChatMessageState& data); +LinphoneEnums::ChatMessageState fromLinphone(const linphone::ChatMessage::State& data); + +enum ChatRoomState { + ChatRoomStateNone = int(linphone::ChatRoom::State::None), + ChatRoomStateInstantiated = int(linphone::ChatRoom::State::Instantiated), + ChatRoomStateCreationPending = int(linphone::ChatRoom::State::CreationPending), + ChatRoomStateCreated = int(linphone::ChatRoom::State::Created), + ChatRoomStateCreationFailed = int(linphone::ChatRoom::State::CreationFailed), + ChatRoomStateTerminationPending = int(linphone::ChatRoom::State::TerminationPending), + ChatRoomStateTerminated = int(linphone::ChatRoom::State::Terminated), + ChatRoomStateTerminationFailed = int(linphone::ChatRoom::State::TerminationFailed), + ChatRoomStateDeleted = int(linphone::ChatRoom::State::Deleted), +}; +Q_ENUM_NS(ChatRoomState) + +linphone::ChatRoom::State toLinphone(const LinphoneEnums::ChatRoomState& data); +LinphoneEnums::ChatRoomState fromLinphone(const linphone::ChatRoom::State& data); + enum CallStatus { CallStatusDeclined = int(linphone::Call::Status::Declined), @@ -202,6 +219,7 @@ void fromString(const QString& transportType, LinphoneEnums::TransportType *tran Q_DECLARE_METATYPE(LinphoneEnums::CallStatus) Q_DECLARE_METATYPE(LinphoneEnums::ChatMessageState) +Q_DECLARE_METATYPE(LinphoneEnums::ChatRoomState) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceLayout) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceInfoState) Q_DECLARE_METATYPE(LinphoneEnums::ConferenceSchedulerState) diff --git a/linphone-app/ui/modules/Linphone/Contact/Contact.qml b/linphone-app/ui/modules/Linphone/Contact/Contact.qml index 630ee0ab0..5dcc99f93 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Contact.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Contact.qml @@ -25,6 +25,7 @@ Rectangle { property bool displayUnreadMessageCount: false property bool showSubtitle : true + property bool showBusyIndicator: false property string subtitle: '' property string subject: (entry && entry.conferenceInfoModel && entry.conferenceInfoModel.subject @@ -89,6 +90,27 @@ Rectangle { anchors.fill: parent onClicked: item.avatarClicked(mouse) } + + Loader{ + id: busyLoader + + anchors.fill: parent + anchors.margins: 5 + + active: item.showBusyIndicator + sourceComponent: Component{ + BusyIndicator{// Joining spinner + id: joiningSpinner + running: false + Timer{// Delay starting spinner (Qt bug) + id: indicatorDelay + interval: 100 + onTriggered: joiningSpinner.running = true + } + Component.onCompleted: indicatorDelay.start() + } + } + } } ContactDescription { diff --git a/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml b/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml index 3e8f34e42..1f0741eff 100644 --- a/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml +++ b/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml @@ -44,6 +44,7 @@ Item { NumberAnimation { target: optionsView; property: 'x'; to:optionsView.width; duration: 200;} } ] + enabled: !contactView.showBusyIndicator Contact { @@ -68,7 +69,8 @@ Item { ? TimelineStyle.contact.title.color.selected : TimelineStyle.contact.title.color.normal showSubtitle: mainItem.timelineModel && (mainItem.timelineModel.chatRoomModel && (mainItem.timelineModel.chatRoomModel.isOneToOne || !mainItem.timelineModel.chatRoomModel.isConference)) - TooltipArea { + showBusyIndicator: mainItem.timelineModel && mainItem.timelineModel.updating + TooltipArea { id: contactTooltip text: mainItem.timelineModel && UtilsCpp.toDateTimeString(mainItem.timelineModel.chatRoomModel.lastUpdateTime) isClickable: true @@ -160,5 +162,4 @@ Item { } } } - } \ No newline at end of file diff --git a/linphone-app/ui/views/App/Main/ContactEdit.qml b/linphone-app/ui/views/App/Main/ContactEdit.qml index 1ffe07211..d150abf6b 100644 --- a/linphone-app/ui/views/App/Main/ContactEdit.qml +++ b/linphone-app/ui/views/App/Main/ContactEdit.qml @@ -239,7 +239,7 @@ ColumnLayout { sipAddresses: _contact ? _contact.vcard.sipAddresses : [ contactEdit.sipAddress ] function viewConversation(chatRoomModel){ - if( chatRoomModel){ + if( chatRoomModel && !chatRoomModel.updating){ window.setView('Conversation', { chatRoomModel:chatRoomModel }, function(){ From c594ed0315959e69c9bb6e38064b7e9c93f5dfd5 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 1 Dec 2022 11:27:21 +0100 Subject: [PATCH 49/61] Update SDK for accountless subscribes issues. --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 475232c30..3e4c31b64 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 475232c309b0683f0339027712e0403d4fc9fc84 +Subproject commit 3e4c31b645e47b5231a9d9a4a8effc11eecb868b From 4a7caf7fc3a7d55f5de6c32277ebf066f968c86a Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 1 Dec 2022 15:54:39 +0100 Subject: [PATCH 50/61] Display all empty chat rooms if option has been set (empty secure chat rooms were hide on restart) --- .../src/components/timeline/TimelineListModel.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/linphone-app/src/components/timeline/TimelineListModel.cpp b/linphone-app/src/components/timeline/TimelineListModel.cpp index 7d5d48f55..c181d7452 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.cpp +++ b/linphone-app/src/components/timeline/TimelineListModel.cpp @@ -246,7 +246,17 @@ void TimelineListModel::updateTimelines () { allChatRooms.remove_if([](std::shared_ptr chatRoom){ if( ChatRoomModel::isTerminated(chatRoom) && chatRoom->getUnreadMessagesCount() > 0) chatRoom->markAsRead(); - return chatRoom->getState() == linphone::ChatRoom::State::Deleted || (!chatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic) && chatRoom->getConferenceAddress() && chatRoom->getHistoryEventsSize() == 0); + if(chatRoom->getState() == linphone::ChatRoom::State::Deleted) + return true; + if(!chatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic)){ + auto conferenceAddress = chatRoom->getConferenceAddress(); + if( conferenceAddress && conferenceAddress->getDomain() == Constants::LinphoneDomain) { + QString conferenceAddressStr = Utils::coreStringToAppString(conferenceAddress->asStringUriOnly()); + if( conferenceAddressStr.contains("conf-id")) + return true; + } + } + return false; }); //Remove no more chat rooms From 985f77c81586c64d120892eef347957ee24b63c1 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 1 Dec 2022 17:16:48 +0100 Subject: [PATCH 51/61] Disable camera button if paused. --- linphone-app/ui/views/App/Calls/Incall.qml | 1 + linphone-app/ui/views/App/Calls/IncallFullscreen.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index 94fb64b75..8184f30f4 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -534,6 +534,7 @@ Rectangle { backgroundRadius: 90 colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff updating: callModel.videoEnabled && callModel.updating && !mainItem.layoutChanging + enabled: callModel && !callModel.pausedByUser property bool _activateCamera: false onClicked: if(callModel && !mainItem.layoutChanging){ if( callModel.isConference){// Only deactivate camera in conference. diff --git a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml index 081fc1754..27d63c4ce 100644 --- a/linphone-app/ui/views/App/Calls/IncallFullscreen.qml +++ b/linphone-app/ui/views/App/Calls/IncallFullscreen.qml @@ -493,6 +493,7 @@ Window { backgroundRadius: 90 colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff updating: callModel && callModel.videoEnabled && callModel.updating + enabled: callModel && !callModel.pausedByUser onClicked: if(callModel && !conference.layoutChanging){ if( callModel.isConference){// Only deactivate camera in conference. callModel.cameraEnabled = !callModel.cameraEnabled From 1b8b57664c94813a1039b219bda93acaf051bdc6 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 1 Dec 2022 17:39:50 +0100 Subject: [PATCH 52/61] Hide remove participant button for 'me' in conference. --- .../Linphone/View/ParticipantsListView.qml | 5 +- .../Linphone/View/ParticipantsView.qml | 64 +++++++++++-------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/linphone-app/ui/modules/Linphone/View/ParticipantsListView.qml b/linphone-app/ui/modules/Linphone/View/ParticipantsListView.qml index e76785ca2..d6cfbd9cd 100644 --- a/linphone-app/ui/modules/Linphone/View/ParticipantsListView.qml +++ b/linphone-app/ui/modules/Linphone/View/ParticipantsListView.qml @@ -11,7 +11,7 @@ import Linphone.Styles 1.0 import Units 1.0 import UtilsCpp 1.0 - +import 'qrc:/ui/scripts/Utils/utils.js' as Utils // ============================================================================= ColumnLayout { @@ -114,6 +114,9 @@ ColumnLayout { colorSet: ParticipantsListViewStyle.removeParticipant, secure:0, visible:true, + visibleHandler: function(entry){ + return !UtilsCpp.isMe(entry.sipAddress) + }, //: 'Remove this participant from the list' : Tootltip to explain that the action will lead to remove the participant. tooltipText: qsTr('participantsListRemoveTooltip'), handler: function (entry) { diff --git a/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml b/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml index f38c0b85b..697114204 100644 --- a/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml +++ b/linphone-app/ui/modules/Linphone/View/ParticipantsView.qml @@ -122,6 +122,9 @@ ScrollableListView { backgroundRadius: 90 colorSet: modelData.colorSet visible: sipAddressesView.actions[index].visible + && (!sipAddressesView.actions[index].visibleHandler || sipAddressesView.actions[index].visibleHandler({ + sipAddress: sipAddressesView.interpretableSipAddress + })) onClicked: sipAddressesView.actions[index].handler({ sipAddress: sipAddressesView.interpretableSipAddress @@ -285,36 +288,43 @@ ScrollableListView { id: actionsRepeater model: sipAddressesView.actions - ActionButton { - isCustom: true - backgroundRadius: 90 - colorSet: modelData.colorSet + Item{ + height: buttonAction.height + width: buttonAction.width anchors.verticalCenter: parent.verticalCenter - tooltipText: modelData.tooltipText? modelData.tooltipText:'' - visible: sipAddressesView.actions[index].visible - onClicked: { - sipAddressesView.actions[index].handler(contactView.entry) - } - Icon{ - visible: modelData.secure>0 && - (sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$modelData}) : true) - icon: modelData.secure === 2?'secure_level_2':'secure_level_1' - iconSize: parent.height/2 - anchors.top:parent.top - anchors.horizontalCenter: parent.right - } - Loader{ + ActionButton { + id: buttonAction + isCustom: true + backgroundRadius: 90 + colorSet: modelData.colorSet anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - height: parent.height - 2 - width: height + tooltipText: modelData.tooltipText? modelData.tooltipText:'' + visible: sipAddressesView.actions[index].visible && (!sipAddressesView.actions[index].visibleHandler || sipAddressesView.actions[index].visibleHandler(contactView.entry)) - active: index == actionsRepeater.count -1 && sipAddressesView.showInvitingIndicator && contactView.entry && contactView.entry.inviting - - sourceComponent: Component{ - BusyIndicator{ - color: BusyIndicatorStyle.alternateColor - running: true + onClicked: { + sipAddressesView.actions[index].handler(contactView.entry) + } + Icon{ + visible: modelData.secure>0 && + (sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$modelData}) : true) + icon: modelData.secure === 2?'secure_level_2':'secure_level_1' + iconSize: parent.height/2 + anchors.top:parent.top + anchors.horizontalCenter: parent.right + } + Loader{ + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + height: parent.height - 2 + width: height + + active: index == actionsRepeater.count -1 && sipAddressesView.showInvitingIndicator && contactView.entry && contactView.entry.inviting + + sourceComponent: Component{ + BusyIndicator{ + color: BusyIndicatorStyle.alternateColor + running: true + } } } } From e7767224a0831565646413a1a0e90b44fbaf3339 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 5 Dec 2022 12:02:19 +0100 Subject: [PATCH 53/61] Fix time zones with QDateTime fromMSecsSinceEpoch/toMSecsSinceEpoch. Overwrite locale display for qml date to avoid taking account of timezone when using only dates. --- .../ConferenceInfoListModel.cpp | 2 +- .../conferenceInfo/ConferenceInfoModel.cpp | 26 +++++++++-------- .../ui/modules/Common/Picker/DatePicker.qml | 28 +++++++++++-------- linphone-app/ui/scripts/Utils/utils.js | 12 +++++++- .../ui/views/App/Dialog/NewConference.qml | 8 +++--- 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp index 1aa28f80c..764780d37 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp @@ -89,7 +89,7 @@ QVariant ConferenceInfoListModel::data (const QModelIndex &index, int role ) con if (role == Qt::DisplayRole) return QVariant::fromValue(mList[row].get()); else if (role == Qt::DisplayRole +1 ) - return QVariant::fromValue(mList[row].objectCast()->getDateTimeUtc().date()); + return QVariant::fromValue(mList[row].objectCast()->getDateTimeSystem().date()); return QVariant(); } diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index 0a8adb8b9..941556fcd 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -141,14 +141,15 @@ std::shared_ptr ConferenceInfoModel::findConferenceInf //------------------------------------------------------------------------------------------------ -//Note conferenceInfo->getDateTime uses system timezone. -QDateTime ConferenceInfoModel::getDateTimeUtc() const{ - return QDateTime::fromMSecsSinceEpoch(mConferenceInfo->getDateTime() * 1000).toUTC(); +//Note conferenceInfo->getDateTime uses system timezone and fromMSecsSinceEpoch need a UTC +QDateTime ConferenceInfoModel::getDateTimeSystem() const{ + QDateTime reference(QDateTime::fromMSecsSinceEpoch(mConferenceInfo->getDateTime() * 1000));// Get a reference for timezone offset computing + qint64 utcMs = (mConferenceInfo->getDateTime() - QTimeZone::systemTimeZone().offsetFromUtc(reference)) * 1000;// Remove system timezone offset to get UTC + return QDateTime::fromMSecsSinceEpoch(utcMs, QTimeZone::systemTimeZone()); // Return a System Timezone datetime based } -QDateTime ConferenceInfoModel::getDateTimeSystem() const{ - QDateTime utc = getDateTimeUtc(); - return utc.addSecs(QTimeZone::systemTimeZone().offsetFromUtc(utc)); +QDateTime ConferenceInfoModel::getDateTimeUtc() const{ + return getDateTimeSystem().toUTC(); } int ConferenceInfoModel::getDuration() const{ @@ -230,11 +231,13 @@ LinphoneEnums::ConferenceSchedulerState ConferenceInfoModel::getConferenceSchedu } //------------------------------------------------------------------------------------------------ -// Convert into UTC with TimeZone and pass system timezone to conference info +// Datetime is in Custom (Locale/UTC/System). Convert into system timezone for conference info void ConferenceInfoModel::setDateTime(const QDateTime& dateTime){ - QDateTime utc = dateTime.addSecs( -mTimeZone.offsetFromUtc(dateTime)); - QDateTime system = utc.addSecs(QTimeZone::systemTimeZone().offsetFromUtc(utc)); - mConferenceInfo->setDateTime(system.toMSecsSinceEpoch() / 1000); + QDateTime system = dateTime.toTimeZone(QTimeZone::systemTimeZone());//System + int offset = QTimeZone::systemTimeZone().offsetFromUtc(system);//Get UTC offset in system coordinate + system = system.addSecs( offset - mTimeZone.offsetFromUtc(dateTime));// Delta on offsets + mConferenceInfo->setDateTime(system.toMSecsSinceEpoch() / 1000 + offset);// toMSecsSinceEpoch() is UTC, add system reference. + emit dateTimeChanged(); } @@ -321,12 +324,11 @@ void ConferenceInfoModel::createConference(const int& securityLevel) { CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = false; shared_ptr core = CoreManager::getInstance()->getCore(); static std::shared_ptr conference; - qInfo() << "Conference creation of " << getSubject() << " at " << securityLevel << " security, organized by " << getOrganizer(); + qInfo() << "Conference creation of " << getSubject() << " at " << securityLevel << " security, organized by " << getOrganizer() << " for " << getDateTimeSystem().toString(); qInfo() << "Participants:"; for(auto p : mConferenceInfo->getParticipants()) qInfo() << "\t" << p->asString().c_str(); - mConferenceScheduler = ConferenceScheduler::create(); mConferenceScheduler->mSendInvite = mInviteMode; connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent); diff --git a/linphone-app/ui/modules/Common/Picker/DatePicker.qml b/linphone-app/ui/modules/Common/Picker/DatePicker.qml index f740d478b..0d816ac55 100644 --- a/linphone-app/ui/modules/Common/Picker/DatePicker.qml +++ b/linphone-app/ui/modules/Common/Picker/DatePicker.qml @@ -5,6 +5,8 @@ import Common 1.0 import Common.Styles 1.0 import Units 1.0 +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + Item{ id: mainItem property bool allYears : false // if false : years from today @@ -33,9 +35,10 @@ Item{ Layout.fillWidth: true Layout.alignment: Qt.AlignCenter horizontalAlignment: Qt.AlignCenter - text: new Date(monthList.currentYear, monthList.currentMonth, 1).toLocaleString(Qt.locale(), 'MMMM yyyy') + text: new Date(monthList.currentYear, monthList.currentMonth, 15).toLocaleString(Qt.locale(), 'MMMM yyyy')// 15 because of timezones that can change the date for localeString color: DatePickerStyle.title.color font.pointSize: DatePickerStyle.title.pointSize + font.capitalization: Font.Capitalize } ActionButton{ isCustom: true @@ -62,7 +65,7 @@ Item{ } property date selectedDate: new Date() - property int minYear: mainItem.allYears ? new Date(0,0,0).getFullYear() : new Date().getFullYear() + property int minYear: mainItem.allYears ? new Date(0,0,1).getFullYear() : new Date().getFullYear() snapMode: ListView.SnapOneItem orientation: Qt.Horizontal @@ -70,7 +73,7 @@ Item{ // One model per month model: (new Date().getFullYear()- minYear + maxYears) * 12 - + currentIndex: 0 property int currentYear: Math.floor(currentIndex / 12) + minYear property int currentMonth: currentIndex % 12 @@ -87,7 +90,7 @@ Item{ property int year: Math.floor(index / 12) + monthList.minYear property int month: index % 12 property int firstDay: new Date(year, month, 1).getDay() - + GridLayout { // 1 month calender id: grid @@ -105,9 +108,12 @@ Item{ delegate: Item{ id: cellItem - property int day: index - 7 // 0 = top left below Sunday (-7 to 41) + property int day: index - 7 // 0 = top left below Sunday (-7 to 41) property int date: day - firstDay + 1 // 1-31 - property bool selected : text.text != '-' && new Date(year, month, date).toDateString() == monthList.selectedDate.toDateString() && text.text && day >= 0 + property date cellDate: new Date(year, month, date) + property bool selected : text.text != '-' + && Utils.equalDate(cellDate, monthList.selectedDate) + && text.text && day >= 0 width: grid.cellMinSize height: width @@ -132,12 +138,12 @@ Item{ : cellItem.day < 0 ? DatePickerStyle.cell.dayHeaderPointSize : DatePickerStyle.cell.dayPointSize - font.bold: cellItem.day < 0 || cellItem.selected || new Date(year, month, cellItem.date).toDateString() == new Date().toDateString() // today + font.bold: cellItem.day < 0 || cellItem.selected || Utils.equalDate(cellItem.cellDate, new Date()) // today text: { - if(cellItem.day < 0) + if(cellItem.day < 0){ // Magic date to set day names in this order : 'S', 'M', 'T', 'W', 'T', 'F', 'S' in Locale - return new Date(1,3,index).toLocaleString(Qt.locale(), 'ddd')[0] - else if(new Date(year, month, cellItem.date).getMonth() == month && (!hideOldDates || new Date(year, month, cellItem.date+1) >= new Date())) // new Date use time too + return Utils.exactDate(new Date(2000,9,index+1)).toLocaleString(Qt.locale(), 'ddd')[0].toUpperCase() + }else if(cellItem.cellDate.getMonth() == month && (!hideOldDates || new Date(year, month, cellItem.date+1) >= new Date())) // new Date use time too return cellItem.date else return '-' @@ -152,7 +158,7 @@ Item{ enabled: text.text && text.text != '-' && cellItem.day >= 0 onClicked: { - monthList.selectedDate = new Date(year, month, cellItem.date) + monthList.selectedDate = cellItem.cellDate mainItem.clicked(monthList.selectedDate) } } diff --git a/linphone-app/ui/scripts/Utils/utils.js b/linphone-app/ui/scripts/Utils/utils.js index d82ed2452..3b8c80bc8 100644 --- a/linphone-app/ui/scripts/Utils/utils.js +++ b/linphone-app/ui/scripts/Utils/utils.js @@ -563,12 +563,22 @@ function buildDate(date, time){ return dateTime } +function equalDate(date1, date2){ + return date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate() +} function fromUTC(date){ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds())); } +// return EXACTLY what date has been set (not take account of Locale timezones, eg. Date(2000,0,1) will print january and not december if timezone lead there.) +// Use this function for toLocaleString/toLocaleDateString or other +function exactDate(date) { + var timeOffset = date.getTimezoneOffset() * 60000 + var exactDate = new Date(date.valueOf() - timeOffset) + return exactDate +} // ----------------------------------------------------------------------------- @@ -796,4 +806,4 @@ function printObject(o) { out += p + ': ' + o[p] + '\n'; } return out; -} \ No newline at end of file +} diff --git a/linphone-app/ui/views/App/Dialog/NewConference.qml b/linphone-app/ui/views/App/Dialog/NewConference.qml index 9048fac9d..94c3c652b 100644 --- a/linphone-app/ui/views/App/Dialog/NewConference.qml +++ b/linphone-app/ui/views/App/Dialog/NewConference.qml @@ -20,8 +20,8 @@ DialogPlus { property bool isNew: !conferenceInfoModel || conferenceInfoModel.uri === '' property ConferenceInfoModel conferenceInfoModel: ConferenceInfoModel{} onConferenceInfoModelChanged: { - dateField.setDate(conferenceManager.conferenceInfoModel.dateTimeUtc); - timeField.setTime(conferenceManager.conferenceInfoModel.dateTimeUtc); + dateField.setDate(conferenceManager.conferenceInfoModel.dateTime); + timeField.setTime(conferenceManager.conferenceInfoModel.dateTime); selectedParticipants.setAddresses(conferenceInfoModel) } property bool forceSchedule : false @@ -299,9 +299,9 @@ DialogPlus { } function setDate(date){ currentDate = date - text = date.toLocaleDateString(scheduleForm.locale, Qt.ISODate) + text = Utils.exactDate(date).toLocaleDateString(scheduleForm.locale, Qt.ISODate) } - text: conferenceManager.conferenceInfoModel ? conferenceManager.conferenceInfoModel.dateTime.toLocaleDateString(scheduleForm.locale, Qt.ISODate) : '' + text: conferenceManager.conferenceInfoModel ? Utils.exactDate(conferenceManager.conferenceInfoModel.dateTime).toLocaleDateString(scheduleForm.locale, Qt.ISODate) : '' icon: 'drop_down_custom' MouseArea{ anchors.fill: parent From 6f673554e4271f777d8d5e87040dea367b17702d Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 5 Dec 2022 15:13:10 +0100 Subject: [PATCH 54/61] Display all participants count in ICS (all = SDK participants + organizer) --- .../conferenceInfo/ConferenceInfoModel.cpp | 18 ++++++++++++++++++ .../conferenceInfo/ConferenceInfoModel.hpp | 3 +++ .../Linphone/Chat/ChatCalendarMessage.qml | 4 ++-- .../Chat/ChatConferenceInvitationMessage.qml | 6 +++--- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index 941556fcd..2ee413582 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -207,11 +207,29 @@ QVariantList ConferenceInfoModel::getParticipants() const{ } return addresses; } +QVariantList ConferenceInfoModel::getAllParticipants() const{ + QVariantList addresses = getParticipants(); + QString organizerAddress = QString::fromStdString(mConferenceInfo->getOrganizer()->asStringUriOnly()); + for(auto item : addresses){ + if( item.toMap()["address"] == organizerAddress) + return addresses; + } + QVariantMap participant; + participant["displayName"] = Utils::getDisplayName(mConferenceInfo->getOrganizer()); + participant["address"] = organizerAddress; + addresses << participant; + return addresses; +} + int ConferenceInfoModel::getParticipantCount()const{ return mConferenceInfo->getParticipants().size(); } +int ConferenceInfoModel::getAllParticipantCount()const{ + return getAllParticipants().size(); +} + TimeZoneModel* ConferenceInfoModel::getTimeZoneModel() const{ TimeZoneModel * model = new TimeZoneModel(mTimeZone); App::getInstance()->getEngine()->setObjectOwnership(model, QQmlEngine::JavaScriptOwnership); diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp index da7f01fc4..7f2ec0e27 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp @@ -50,6 +50,7 @@ public: Q_PROPERTY(bool isScheduled READ isScheduled WRITE setIsScheduled NOTIFY isScheduledChanged) Q_PROPERTY(int inviteMode READ getInviteMode WRITE setInviteMode NOTIFY inviteModeChanged) Q_PROPERTY(int participantCount READ getParticipantCount NOTIFY participantsChanged) + Q_PROPERTY(int allParticipantCount READ getAllParticipantCount NOTIFY participantsChanged) Q_PROPERTY(LinphoneEnums::ConferenceInfoState state READ getConferenceInfoState NOTIFY conferenceInfoStateChanged) Q_PROPERTY(LinphoneEnums::ConferenceSchedulerState conferenceSchedulerState READ getConferenceSchedulerState NOTIFY conferenceSchedulerStateChanged) @@ -74,7 +75,9 @@ public: bool isScheduled() const; int getInviteMode() const; Q_INVOKABLE QVariantList getParticipants() const; + Q_INVOKABLE QVariantList getAllParticipants() const; Q_INVOKABLE int getParticipantCount()const; + Q_INVOKABLE int getAllParticipantCount()const; Q_INVOKABLE TimeZoneModel* getTimeZoneModel() const; Q_INVOKABLE QString getIcalendarString() const; LinphoneEnums::ConferenceInfoState getConferenceInfoState() const; diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml index 61a34add5..b6c53e37d 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml @@ -212,10 +212,10 @@ Loader{ Layout.alignment: Qt.AlignTop spacing: 0 visible: mainItem.isExpanded - onVisibleChanged: visible ? model= mainItem.conferenceInfoModel.getParticipants() : model = [] + onVisibleChanged: visible ? model= mainItem.conferenceInfoModel.getAllParticipants() : model = [] Connections{ target: mainItem.conferenceInfoModel - onParticipantsChanged: if(expandedParticipantsList.visible) expandedParticipantsList.model = mainItem.conferenceInfoModel.getParticipants() + onParticipantsChanged: if(expandedParticipantsList.visible) expandedParticipantsList.model = mainItem.conferenceInfoModel.getAllParticipants() } delegate: Row{ diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml index cced32c2a..750bf9de1 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatConferenceInvitationMessage.qml @@ -109,7 +109,7 @@ Loader{ } RowLayout { id: participantsRow - property int participantCount: mainItem.conferenceInfoModel.participantCount + property int participantCount: mainItem.conferenceInfoModel.allParticipantCount Layout.fillWidth: true Layout.preferredHeight: ChatCalendarMessageStyle.participants.iconSize Layout.leftMargin: 5 @@ -204,10 +204,10 @@ Loader{ Layout.leftMargin: 10 spacing: 0 visible: mainItem.isExpanded - onVisibleChanged: visible ? model= mainItem.conferenceInfoModel.getParticipants() : model = [] + onVisibleChanged: visible ? model= mainItem.conferenceInfoModel.getAllParticipants() : model = [] Connections{ target: mainItem.conferenceInfoModel - onParticipantsChanged: if(expandedParticipantsList.visible) expandedParticipantsList.model = mainItem.conferenceInfoModel.getParticipants() + onParticipantsChanged: if(expandedParticipantsList.visible) expandedParticipantsList.model = mainItem.conferenceInfoModel.getAllParticipants() } delegate: Row{ From d1027f401d9d3f96dd6ed40eae0f21bd5c7f0dae Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 6 Dec 2022 17:31:53 +0100 Subject: [PATCH 55/61] Fix reply message shortcut: - move to a better location where the message is supposed to be. - avoid to refresh view when loading chat items. --- .../components/chat-room/ChatRoomModel.cpp | 21 ++++++++++++++----- .../components/chat-room/ChatRoomModel.hpp | 1 + .../ui/modules/Linphone/Chat/Chat.qml | 11 ++++++++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 725ca62d0..02a52440b 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -858,23 +858,31 @@ int ChatRoomModel::loadTillMessage(ChatMessageModel * message){ }); // if not find, load more entries and find it in new entries. if( entry == mList.end()){ + mPostModelChangedEvents = false; + beginResetModel(); int newEntries = loadMoreEntries(); while( newEntries > 0){// no more new entries int entryCount = 0; entry = mList.begin(); - auto chatEventEntry = entry->objectCast(); + auto chatEventEntry = entry->objectCast(); while(entryCount < newEntries && (chatEventEntry->mType != ChatRoomModel::EntryType::MessageEntry || chatEventEntry.objectCast()->getChatMessage() != linphoneMessage) ){ ++entryCount; ++entry; + if( entry != mList.end()) + chatEventEntry = entry->objectCast(); } if( entryCount < newEntries){// We got it qDebug() << "Find message at " << entryCount << " after loading new entries"; + mPostModelChangedEvents = true; + endResetModel(); return entryCount; }else newEntries = loadMoreEntries();// continue } + mPostModelChangedEvents = true; + endResetModel(); }else{ int entryCount = entry - mList.begin(); qDebug() << "Find message at " << entryCount; @@ -1029,18 +1037,21 @@ int ChatRoomModel::loadMoreEntries(){ EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this); if(entries.size() >0){ - beginInsertRows(QModelIndex(), 0, entries.size()-1); + if(mPostModelChangedEvents) + beginInsertRows(QModelIndex(), 0, entries.size()-1); for(auto entry : entries) mList.prepend(entry); - endInsertRows(); + if(mPostModelChangedEvents) + endInsertRows(); //emit layoutChanged(); updateLastUpdateTime(); } newEntries = entries.size(); }while( newEntries>0 && currentRowCount == rowCount()); - currentRowCount = rowCount() - currentRowCount + 1; + currentRowCount = rowCount() - currentRowCount; setEntriesLoading(false); - emit moreEntriesLoaded(currentRowCount); + if(mPostModelChangedEvents) + emit moreEntriesLoaded(currentRowCount); return currentRowCount; } diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index 962054cc4..4c25d05e6 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -311,6 +311,7 @@ private: QSharedPointer mReplyModel; QSharedPointer mUnreadMessageNotice; int mBindingCalls = 0; + bool mPostModelChangedEvents = true; QWeakPointer mSelf; }; diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.qml b/linphone-app/ui/modules/Linphone/Chat/Chat.qml index 6637251d6..3e8c4a35e 100644 --- a/linphone-app/ui/modules/Linphone/Chat/Chat.qml +++ b/linphone-app/ui/modules/Linphone/Chat/Chat.qml @@ -33,10 +33,17 @@ Rectangle { color: ChatStyle.color clip: true - + Timer{// Let some time to have a better cell sizes + id: repositionerDelay + property int indexToMove + interval: 100 + onTriggered: chat.positionViewAtIndex(indexToMove, ListView.Center) + } function positionViewAtIndex(index){ chat.bindToEnd = false - chat.positionViewAtIndex(index, ListView.Beginning) + chat.positionViewAtIndex(index, ListView.Center) + repositionerDelay.indexToMove = index + repositionerDelay.restart() } function goToMessage(message){ From 19e59ae0215d7955281840ab9e752232466e9961 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 6 Dec 2022 17:32:22 +0100 Subject: [PATCH 56/61] Fix typo on camera switch in audio-only. --- linphone-app/ui/views/App/Calls/Incall.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index 8184f30f4..9b0bec8f0 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -540,7 +540,7 @@ Rectangle { if( callModel.isConference){// Only deactivate camera in conference. if(mainItem.isAudioOnly) { var layout = SettingsModel.videoConferenceLayout != LinphoneEnums.ConferenceLayoutAudioOnly ? SettingsModel.videoConferenceLayout : LinphoneEnums.ConferenceLayoutGrid - layoutDelay.being(layout) + layoutDelay.begin(layout) camera._activateCamera = true }else callModel.cameraEnabled = !callModel.cameraEnabled From 75bcdc3fb77f01aec092e2805f043e64bbd8ba2f Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 6 Dec 2022 17:33:00 +0100 Subject: [PATCH 57/61] Update SDK to 5.2 --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index 3e4c31b64..d4f5ed995 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 3e4c31b645e47b5231a9d9a4a8effc11eecb868b +Subproject commit d4f5ed99578e94e2c25bffc7e0d62e3cb96aab73 From 1849bd08e448ec94df51321b9784a65304789a25 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 7 Dec 2022 11:25:10 +0100 Subject: [PATCH 58/61] Short term design choice on meetings list : display all for all accounts. As of 5.2.0 SDK and on cancel, there are no more more links between conference info and current account. Fix translations on cancelled meetings. --- linphone-app/assets/languages/da.ts | 5 +++++ linphone-app/assets/languages/de.ts | 5 +++++ linphone-app/assets/languages/en.ts | 5 +++++ linphone-app/assets/languages/es.ts | 5 +++++ linphone-app/assets/languages/fr_FR.ts | 17 +++++++++++------ linphone-app/assets/languages/hu.ts | 5 +++++ linphone-app/assets/languages/it.ts | 5 +++++ linphone-app/assets/languages/ja.ts | 5 +++++ linphone-app/assets/languages/lt.ts | 5 +++++ linphone-app/assets/languages/pt_BR.ts | 5 +++++ linphone-app/assets/languages/ru.ts | 5 +++++ linphone-app/assets/languages/sv.ts | 5 +++++ linphone-app/assets/languages/tr.ts | 5 +++++ linphone-app/assets/languages/uk.ts | 5 +++++ linphone-app/assets/languages/zh_CN.ts | 5 +++++ .../conferenceInfo/ConferenceInfoListModel.cpp | 8 ++++---- .../conferenceInfo/ConferenceInfoListModel.hpp | 5 +++-- .../Linphone/Chat/ChatCalendarMessage.qml | 4 ++-- 18 files changed, 90 insertions(+), 14 deletions(-) diff --git a/linphone-app/assets/languages/da.ts b/linphone-app/assets/languages/da.ts index 9aa50fa99..ef140d3c4 100644 --- a/linphone-app/assets/languages/da.ts +++ b/linphone-app/assets/languages/da.ts @@ -569,6 +569,11 @@ Server url ikke konfigureret. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/de.ts b/linphone-app/assets/languages/de.ts index 695bad434..978ccf4a7 100644 --- a/linphone-app/assets/languages/de.ts +++ b/linphone-app/assets/languages/de.ts @@ -569,6 +569,11 @@ Server URL ist nicht konfiguriert. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/en.ts b/linphone-app/assets/languages/en.ts index 80206faa0..5f69dff3a 100644 --- a/linphone-app/assets/languages/en.ts +++ b/linphone-app/assets/languages/en.ts @@ -569,6 +569,11 @@ Server URL not configured. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. Do you really want do cancel this meeting? + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + Meeting has been cancelled + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/es.ts b/linphone-app/assets/languages/es.ts index 659fa342d..039bd89a1 100644 --- a/linphone-app/assets/languages/es.ts +++ b/linphone-app/assets/languages/es.ts @@ -569,6 +569,11 @@ URL del servidor no configurada. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts index 64d39b8da..57547d66e 100644 --- a/linphone-app/assets/languages/fr_FR.ts +++ b/linphone-app/assets/languages/fr_FR.ts @@ -173,7 +173,7 @@ usernameStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). usernameStatusInvalid @@ -189,7 +189,7 @@ passwordStatusInvalidCharacters - Caractères invalides détectés (regex : `%1`). + Caractères invalides détectés (regex : `%1`). passwordStatusMissingCharacters @@ -569,6 +569,11 @@ URL du serveur non configurée. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. Voulez-vous supprimer cette réunion ? + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + La réunion a été annulée + ChatConferenceInvitationMessage @@ -1236,7 +1241,7 @@ URL du serveur non configurée. ephemeralNotInConference! 'Ephemeral message is only supported in conference based chat room!' - Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! + Les messages éphémères ne sont disponibles que pour une conversation définie en mode conférence ! Warning about not being in conference based chat room. @@ -2020,7 +2025,7 @@ Cliquez ici : <a href="%1">%1</a> newConferenceScheduleTitle 'Would you like to schedule your meeting?' : Ask about setting the meeting as scheduled. - Voulez-vous programmer cette réunion ? + Voulez-vous programmer cette réunion ? newConferenceDate @@ -2600,7 +2605,7 @@ Cliquez ici : <a href="%1">%1</a> serverTooltip - Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ + Serveur LDAP. ie : ldap:// pour un serveur local ou ldap://ldap.example.org/ bindDNLabel @@ -3546,7 +3551,7 @@ Cliquez ici : <a href="%1">%1</a> deleteTimeline 'Are you sure you want to delete and leave this timeline?' - Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? + Êtes-vous certain de vouloir tout effacer et de quitter cette conversation ? deleteTimelineTooltip diff --git a/linphone-app/assets/languages/hu.ts b/linphone-app/assets/languages/hu.ts index 9a20f7ba0..ce392ee15 100644 --- a/linphone-app/assets/languages/hu.ts +++ b/linphone-app/assets/languages/hu.ts @@ -568,6 +568,11 @@ A kiszolgáló URL-je nincs konfigurálva. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/it.ts b/linphone-app/assets/languages/it.ts index 36fe51dec..c4d768163 100644 --- a/linphone-app/assets/languages/it.ts +++ b/linphone-app/assets/languages/it.ts @@ -569,6 +569,11 @@ URL del server non configurato. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/ja.ts b/linphone-app/assets/languages/ja.ts index d8bce574f..557a37a20 100644 --- a/linphone-app/assets/languages/ja.ts +++ b/linphone-app/assets/languages/ja.ts @@ -568,6 +568,11 @@ 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/lt.ts b/linphone-app/assets/languages/lt.ts index 360c55639..29cb489f1 100644 --- a/linphone-app/assets/languages/lt.ts +++ b/linphone-app/assets/languages/lt.ts @@ -570,6 +570,11 @@ Nesukonfigūruotas serverio url. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/pt_BR.ts b/linphone-app/assets/languages/pt_BR.ts index 96a09ec62..aaced721e 100644 --- a/linphone-app/assets/languages/pt_BR.ts +++ b/linphone-app/assets/languages/pt_BR.ts @@ -569,6 +569,11 @@ URL do servidor não configurado. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/ru.ts b/linphone-app/assets/languages/ru.ts index 2509e66ac..770bd2d14 100644 --- a/linphone-app/assets/languages/ru.ts +++ b/linphone-app/assets/languages/ru.ts @@ -570,6 +570,11 @@ 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/sv.ts b/linphone-app/assets/languages/sv.ts index 0f5b48209..da6160940 100644 --- a/linphone-app/assets/languages/sv.ts +++ b/linphone-app/assets/languages/sv.ts @@ -569,6 +569,11 @@ Serverwebbadressen är inte konfigurerad. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/tr.ts b/linphone-app/assets/languages/tr.ts index d4ab8547c..9b6612885 100644 --- a/linphone-app/assets/languages/tr.ts +++ b/linphone-app/assets/languages/tr.ts @@ -568,6 +568,11 @@ Sunucu url'si yapılandırılmadı. 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/uk.ts b/linphone-app/assets/languages/uk.ts index 603506eca..5f7d0b467 100644 --- a/linphone-app/assets/languages/uk.ts +++ b/linphone-app/assets/languages/uk.ts @@ -570,6 +570,11 @@ 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/assets/languages/zh_CN.ts b/linphone-app/assets/languages/zh_CN.ts index faa1aa2d5..f715c304e 100644 --- a/linphone-app/assets/languages/zh_CN.ts +++ b/linphone-app/assets/languages/zh_CN.ts @@ -568,6 +568,11 @@ 'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting. + + icsCancelledMeetingInvite + 'Meeting has been cancelled' : ICS Title for cancelled meetings + + ChatConferenceInvitationMessage diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp index 764780d37..b889ecf02 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp @@ -43,7 +43,7 @@ ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : ProxyListMo auto conferenceInfos = coreManager->getCore()->getConferenceInformationList(); QList > items; for(auto conferenceInfo : conferenceInfos){ - auto item = build(conferenceInfo); + auto item = build(conferenceInfo, mBuildAll); if(item) items << item; } @@ -53,10 +53,10 @@ ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : ProxyListMo // ----------------------------------------------------------------------------- -QSharedPointer ConferenceInfoListModel::build(const std::shared_ptr & conferenceInfo) const{ +QSharedPointer ConferenceInfoListModel::build(const std::shared_ptr & conferenceInfo, const bool& buildAll) const{ auto me = CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress(); std::list> participants = conferenceInfo->getParticipants(); - bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me); + bool haveMe = buildAll || conferenceInfo->getOrganizer()->weakEqual(me); if(!haveMe) haveMe = (std::find_if(participants.begin(), participants.end(), [me](const std::shared_ptr& address){ return me->weakEqual(address); @@ -70,7 +70,7 @@ QSharedPointer ConferenceInfoListModel::build(const std::sh } void ConferenceInfoListModel::add(const std::shared_ptr & conferenceInfo, const bool& sendEvents){ - auto item = build(conferenceInfo); + auto item = build(conferenceInfo, mBuildAll); if( item) ProxyListModel::add(item); } diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp index c7ee051f5..abf586002 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp @@ -37,7 +37,7 @@ class ConferenceInfoListModel : public ProxyListModel { public: ConferenceInfoListModel (QObject *parent = Q_NULLPTR); - QSharedPointer build(const std::shared_ptr & conferenceInfo) const; + QSharedPointer build(const std::shared_ptr & conferenceInfo, const bool& buildAll) const; void add(const std::shared_ptr & conferenceInfo, const bool& sendEvents = true); @@ -50,7 +50,8 @@ public slots: void onRemoved(bool byUser); signals: void filterTypeChanged(int filterType); - +private: + bool mBuildAll = true; // Short term design choice : display all. As of 5.2.0 SDK and on cancel, there are no more more links between conference info and current account. }; Q_DECLARE_METATYPE(ConferenceInfoListModel*) #endif diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml index b6c53e37d..85373bb74 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml @@ -144,10 +144,10 @@ Loader{ color: ChatCalendarMessageStyle.type.cancelledColor font.pointSize: ChatCalendarMessageStyle.type.pointSize font.weight: Font.Bold - text: 'You have cancelled the conference' + //: 'Meeting has been cancelled' : ICS Title for cancelled meetings + text:qsTr('icsCancelledMeetingInvite') } - Text{ id: title Layout.fillWidth: true From c7481fb8402949f77e493e9ea1e8d76fd3eb6d7b Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 7 Dec 2022 14:49:24 +0100 Subject: [PATCH 59/61] Update SDK for fixing filename with special characters (Windows) --- linphone-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linphone-sdk b/linphone-sdk index d4f5ed995..3a5f2c321 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit d4f5ed99578e94e2c25bffc7e0d62e3cb96aab73 +Subproject commit 3a5f2c32145cc925dbc067f17d7d25c45fef1518 From eb88267d5c73da4361ea7c4c435b4f05d09b02c1 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 7 Dec 2022 15:07:24 +0100 Subject: [PATCH 60/61] Fix starting a meeting when it has been cancelled. --- linphone-app/src/components/calls/CallsListModel.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp index c858c25fa..4ab22c46b 100644 --- a/linphone-app/src/components/calls/CallsListModel.cpp +++ b/linphone-app/src/components/calls/CallsListModel.cpp @@ -367,9 +367,11 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se } void CallsListModel::prepareConferenceCall(ConferenceInfoModel * model){ - auto app = App::getInstance(); - app->smartShowWindow(app->getCallsWindow()); - emit callConferenceAsked(model); + if(model->getConferenceInfoState() != LinphoneEnums::ConferenceInfoStateCancelled) { + auto app = App::getInstance(); + app->smartShowWindow(app->getCallsWindow()); + emit callConferenceAsked(model); + } } int CallsListModel::addAllToConference(){ From 8d153c240a8d2232d6de5851323e8091d3b191ca Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Wed, 7 Dec 2022 15:07:35 +0100 Subject: [PATCH 61/61] Update changelogs --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30ff3da58..0ccfeacda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 5.0.0 - [undefined] +## 5.0.0 - 2022-12-07 ### Added - Video conference and iCalendars. @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Read contacts from all friends lists. - Option to set the display name in "using an account" tab of assistant. - Long pressed buttons. +- Date and Time pickers. - Phone dialpad on main window. - Animated file in chats/notifications. - Round progress bar for transferring a file and allow to cancel it. @@ -26,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mark as Read synchronized between devices. - Merge messages into one notification to avoid spam. - Design overhaul on calls. +- Audio devices can be changed while being in call. - Use a cryptographic checksum when downloading openH264 from CISCO (Update to 2.2.0) ### Fixed