verify friend device (TODO : add an automatic update when sdk allows it, for now it is done when call ends)

This commit is contained in:
Gaelle Braud 2024-06-11 17:51:49 +02:00
parent 1e065cfa72
commit 891f9acd8c
12 changed files with 565 additions and 344 deletions

View file

@ -37,6 +37,14 @@ QVariant createFriendAddressVariant(const QString &label, const QString &address
return map; return map;
} }
QVariant createFriendDevice(const QString &name, const QString &address, LinphoneEnums::SecurityLevel level) {
QVariantMap map;
map.insert("name", name);
map.insert("address", address);
map.insert("securityLevel", QVariant::fromValue(level));
return map;
}
QSharedPointer<FriendCore> FriendCore::create(const std::shared_ptr<linphone::Friend> &contact) { QSharedPointer<FriendCore> FriendCore::create(const std::shared_ptr<linphone::Friend> &contact) {
auto sharedPointer = QSharedPointer<FriendCore>(new FriendCore(contact), &QObject::deleteLater); auto sharedPointer = QSharedPointer<FriendCore>(new FriendCore(contact), &QObject::deleteLater);
sharedPointer->setSelf(sharedPointer); sharedPointer->setSelf(sharedPointer);
@ -75,6 +83,15 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact) : QObje
Utils::coreStringToAppString(phoneNumber->getPhoneNumber()))); Utils::coreStringToAppString(phoneNumber->getPhoneNumber())));
} }
auto devices = contact->getDevices();
for (auto &device : devices) {
mDeviceList.append(createFriendDevice(Utils::coreStringToAppString(device->getDisplayName()),
// do not use uri only as we want the unique device
Utils::coreStringToAppString(device->getAddress()->asString()),
LinphoneEnums::fromLinphone(device->getSecurityLevel())));
}
updateVerifiedDevicesCount();
mStarred = contact->getStarred(); mStarred = contact->getStarred();
mIsSaved = true; mIsSaved = true;
} else { } else {
@ -110,16 +127,28 @@ void FriendCore::setSelf(SafeSharedPointer<FriendCore> me) {
void FriendCore::setSelf(QSharedPointer<FriendCore> me) { void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
if (me) { if (me) {
if (mFriendModel) { if (mFriendModel) {
mCoreModelConnection = nullptr; // No more needed
mFriendModelConnection = QSharedPointer<SafeConnection<FriendCore, FriendModel>>( mFriendModelConnection = QSharedPointer<SafeConnection<FriendCore, FriendModel>>(
new SafeConnection<FriendCore, FriendModel>(me, mFriendModel), &QObject::deleteLater); new SafeConnection<FriendCore, FriendModel>(me, mFriendModel), &QObject::deleteLater);
mFriendModelConnection->makeConnectToModel( mFriendModelConnection->makeConnectToModel(
&FriendModel::presenceReceived, &FriendModel::presenceReceived,
[this](LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp) { [this](LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp) {
mFriendModelConnection->invokeToCore([this, consolidatedPresence, presenceTimestamp]() { auto devices = mFriendModel->getDevices();
setConsolidatedPresence(consolidatedPresence); QVariantList devicesList;
setPresenceTimestamp(presenceTimestamp); for (auto &device : devices) {
}); devicesList.append(
createFriendDevice(Utils::coreStringToAppString(device->getDisplayName()),
// do not use uri only as we want the unique device
Utils::coreStringToAppString(device->getAddress()->asString()),
LinphoneEnums::fromLinphone(device->getSecurityLevel())));
}
mFriendModelConnection->invokeToCore(
[this, consolidatedPresence, presenceTimestamp, devicesList]() {
setConsolidatedPresence(consolidatedPresence);
setPresenceTimestamp(presenceTimestamp);
setDevices(devicesList);
updateVerifiedDevicesCount();
});
}); });
mFriendModelConnection->makeConnectToModel(&FriendModel::pictureUriChanged, [this](const QString &uri) { mFriendModelConnection->makeConnectToModel(&FriendModel::pictureUriChanged, [this](const QString &uri) {
mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); }); mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
@ -165,6 +194,29 @@ void FriendCore::setSelf(QSharedPointer<FriendCore> me) {
mFriendModelConnection->makeConnectToCore(&FriendCore::lSetStarred, [this](bool starred) { mFriendModelConnection->makeConnectToCore(&FriendCore::lSetStarred, [this](bool starred) {
mFriendModelConnection->invokeToModel([this, starred]() { mFriendModel->setStarred(starred); }); mFriendModelConnection->invokeToModel([this, starred]() { mFriendModel->setStarred(starred); });
}); });
if (!mCoreModelConnection) {
mCoreModelConnection = QSharedPointer<SafeConnection<FriendCore, CoreModel>>(
new SafeConnection<FriendCore, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
}
mCoreModelConnection->makeConnectToModel(
&CoreModel::callStateChanged,
[this](const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Call> &call,
linphone::Call::State state, const std::string &message) {
if (state != linphone::Call::State::End && state != linphone::Call::State::Released) return;
auto devices = mFriendModel->getDevices();
QVariantList devicesList;
for (auto &device : devices) {
devicesList.append(
createFriendDevice(Utils::coreStringToAppString(device->getDisplayName()),
// do not use uri only as we want the unique device
Utils::coreStringToAppString(device->getAddress()->asString()),
LinphoneEnums::fromLinphone(device->getSecurityLevel())));
}
mCoreModelConnection->invokeToCore([this, devicesList]() {
setDevices(devicesList);
updateVerifiedDevicesCount();
});
});
} else { // Create } else { // Create
mCoreModelConnection = QSharedPointer<SafeConnection<FriendCore, CoreModel>>( mCoreModelConnection = QSharedPointer<SafeConnection<FriendCore, CoreModel>>(
@ -332,6 +384,27 @@ QList<QVariant> FriendCore::getAllAddresses() const {
return mAddressList + mPhoneNumberList; return mAddressList + mPhoneNumberList;
} }
QList<QVariant> FriendCore::getDevices() const {
return mDeviceList;
}
void FriendCore::updateVerifiedDevicesCount() {
mVerifiedDeviceCount = 0;
for (auto &device : mDeviceList) {
auto map = device.toMap();
if (map["securityLevel"].value<LinphoneEnums::SecurityLevel>() ==
LinphoneEnums::SecurityLevel::EndToEndEncryptedAndVerified)
++mVerifiedDeviceCount;
}
emit verifiedDevicesChanged();
}
void FriendCore::setDevices(QVariantList devices) {
mDeviceList.clear();
mDeviceList.append(devices);
emit devicesChanged();
}
QString FriendCore::getDefaultAddress() const { QString FriendCore::getDefaultAddress() const {
return mDefaultAddress; return mDefaultAddress;
} }

View file

@ -41,12 +41,20 @@
class CoreModel; class CoreModel;
class FriendCore; class FriendCore;
struct FriendDevice {
QString name;
QString address;
LinphoneEnums::SecurityLevel securityLevel;
};
class FriendCore : public QObject, public AbstractObject { class FriendCore : public QObject, public AbstractObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QList<QVariant> allAddresses READ getAllAddresses NOTIFY allAddressesChanged) Q_PROPERTY(QList<QVariant> allAddresses READ getAllAddresses NOTIFY allAddressesChanged)
Q_PROPERTY(QList<QVariant> phoneNumbers READ getPhoneNumbers NOTIFY phoneNumberChanged) Q_PROPERTY(QList<QVariant> phoneNumbers READ getPhoneNumbers NOTIFY phoneNumberChanged)
Q_PROPERTY(QList<QVariant> addresses READ getAddresses NOTIFY addressChanged) Q_PROPERTY(QList<QVariant> addresses READ getAddresses NOTIFY addressChanged)
Q_PROPERTY(QList<QVariant> devices READ getDevices NOTIFY devicesChanged)
Q_PROPERTY(int verifiedDeviceCount MEMBER mVerifiedDeviceCount NOTIFY verifiedDevicesChanged)
Q_PROPERTY(QString givenName READ getGivenName WRITE setGivenName NOTIFY givenNameChanged) Q_PROPERTY(QString givenName READ getGivenName WRITE setGivenName NOTIFY givenNameChanged)
Q_PROPERTY(QString familyName READ getFamilyName WRITE setFamilyName NOTIFY familyNameChanged) Q_PROPERTY(QString familyName READ getFamilyName WRITE setFamilyName NOTIFY familyNameChanged)
Q_PROPERTY(QString displayName READ getDisplayName NOTIFY displayNameChanged) Q_PROPERTY(QString displayName READ getDisplayName NOTIFY displayNameChanged)
@ -106,6 +114,10 @@ public:
QList<QVariant> getAllAddresses() const; QList<QVariant> getAllAddresses() const;
QList<QVariant> getDevices() const;
void updateVerifiedDevicesCount();
void setDevices(QVariantList devices);
LinphoneEnums::ConsolidatedPresence getConsolidatedPresence() const; LinphoneEnums::ConsolidatedPresence getConsolidatedPresence() const;
void setConsolidatedPresence(LinphoneEnums::ConsolidatedPresence presence); void setConsolidatedPresence(LinphoneEnums::ConsolidatedPresence presence);
@ -147,7 +159,8 @@ signals:
void removed(FriendCore *contact); void removed(FriendCore *contact);
void defaultAddressChanged(); void defaultAddressChanged();
void allAddressesChanged(); void allAddressesChanged();
void devicesChanged();
void verifiedDevicesChanged();
void lSetStarred(bool starred); void lSetStarred(bool starred);
protected: protected:
@ -163,6 +176,8 @@ protected:
bool mStarred; bool mStarred;
QList<QVariant> mPhoneNumberList; QList<QVariant> mPhoneNumberList;
QList<QVariant> mAddressList; QList<QVariant> mAddressList;
QList<QVariant> mDeviceList;
int mVerifiedDeviceCount;
QString mDefaultAddress; QString mDefaultAddress;
QString mPictureUri; QString mPictureUri;
bool mIsSaved; bool mIsSaved;

View file

@ -275,6 +275,10 @@ QString FriendModel::getVCardAsString() const {
return Utils::coreStringToAppString(mMonitor->getVcard()->asVcard4String()); return Utils::coreStringToAppString(mMonitor->getVcard()->asVcard4String());
} }
std::list<std::shared_ptr<linphone::FriendDevice>> FriendModel::getDevices() const {
return mMonitor->getDevices();
}
void FriendModel::setPictureUri(const QString &uri) { void FriendModel::setPictureUri(const QString &uri) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto oldPictureUri = Utils::coreStringToAppString(mMonitor->getPhoto()); auto oldPictureUri = Utils::coreStringToAppString(mMonitor->getPhoto());

View file

@ -54,6 +54,7 @@ public:
std::shared_ptr<linphone::Friend> getFriend() const; std::shared_ptr<linphone::Friend> getFriend() const;
QString getPictureUri() const; QString getPictureUri() const;
QString getVCardAsString() const; QString getVCardAsString() const;
std::list<std::shared_ptr<linphone::FriendDevice>> getDevices() const;
protected: protected:
void setAddress(const std::shared_ptr<linphone::Address> &address); void setAddress(const std::shared_ptr<linphone::Address> &address);

View file

@ -29,6 +29,7 @@
void LinphoneEnums::registerMetaTypes() { void LinphoneEnums::registerMetaTypes() {
qRegisterMetaType<LinphoneEnums::CallState>(); qRegisterMetaType<LinphoneEnums::CallState>();
qRegisterMetaType<LinphoneEnums::CallStatus>(); qRegisterMetaType<LinphoneEnums::CallStatus>();
qRegisterMetaType<LinphoneEnums::SecurityLevel>();
qRegisterMetaType<LinphoneEnums::ChatMessageState>(); qRegisterMetaType<LinphoneEnums::ChatMessageState>();
qRegisterMetaType<LinphoneEnums::ChatRoomState>(); qRegisterMetaType<LinphoneEnums::ChatRoomState>();
qRegisterMetaType<LinphoneEnums::ConferenceLayout>(); qRegisterMetaType<LinphoneEnums::ConferenceLayout>();
@ -118,6 +119,14 @@ QString LinphoneEnums::toString(const LinphoneEnums::CallStatus &data) {
} }
} }
linphone::SecurityLevel LinphoneEnums::toLinphone(const LinphoneEnums::SecurityLevel &level) {
return static_cast<linphone::SecurityLevel>(level);
}
LinphoneEnums::SecurityLevel LinphoneEnums::fromLinphone(const linphone::SecurityLevel &level) {
return static_cast<LinphoneEnums::SecurityLevel>(level);
}
LinphoneEnums::CallDir LinphoneEnums::fromLinphone(const linphone::Call::Dir &data) { LinphoneEnums::CallDir LinphoneEnums::fromLinphone(const linphone::Call::Dir &data) {
return static_cast<LinphoneEnums::CallDir>(data); return static_cast<LinphoneEnums::CallDir>(data);
} }

View file

@ -36,9 +36,9 @@ void registerMetaTypes();
enum class MediaEncryption { enum class MediaEncryption {
None = int(linphone::MediaEncryption::None), None = int(linphone::MediaEncryption::None),
Dtls = int(linphone::MediaEncryption::DTLS),
Srtp = int(linphone::MediaEncryption::SRTP), Srtp = int(linphone::MediaEncryption::SRTP),
Zrtp = int(linphone::MediaEncryption::ZRTP) Zrtp = int(linphone::MediaEncryption::ZRTP),
Dtls = int(linphone::MediaEncryption::DTLS)
}; };
Q_ENUM_NS(MediaEncryption) Q_ENUM_NS(MediaEncryption)
@ -159,6 +159,18 @@ linphone::Call::Status toLinphone(const LinphoneEnums::CallStatus &data);
LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status &data); LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status &data);
QString toString(const LinphoneEnums::CallStatus &data); QString toString(const LinphoneEnums::CallStatus &data);
enum class SecurityLevel {
None = int(linphone::SecurityLevel::None),
Unsafe = int(linphone::SecurityLevel::Unsafe),
EndToEndEncrypted = int(linphone::SecurityLevel::EndToEndEncrypted),
EndToEndEncryptedAndVerified = int(linphone::SecurityLevel::EndToEndEncryptedAndVerified),
PointToPointEncrypted = int(linphone::SecurityLevel::PointToPointEncrypted)
};
Q_ENUM_NS(SecurityLevel)
linphone::SecurityLevel toLinphone(const LinphoneEnums::SecurityLevel &level);
LinphoneEnums::SecurityLevel fromLinphone(const linphone::SecurityLevel &level);
enum class CallDir { Outgoing = int(linphone::Call::Dir::Outgoing), Incoming = int(linphone::Call::Dir::Incoming) }; enum class CallDir { Outgoing = int(linphone::Call::Dir::Outgoing), Incoming = int(linphone::Call::Dir::Incoming) };
Q_ENUM_NS(CallDir) Q_ENUM_NS(CallDir)
@ -308,6 +320,8 @@ Q_ENUM_NS(TransportType)
linphone::TransportType toLinphone(const LinphoneEnums::TransportType &type); linphone::TransportType toLinphone(const LinphoneEnums::TransportType &type);
LinphoneEnums::TransportType fromLinphone(const linphone::TransportType &type); LinphoneEnums::TransportType fromLinphone(const linphone::TransportType &type);
QString toString(const LinphoneEnums::TransportType &type);
void fromString(const QString &transportType, LinphoneEnums::TransportType *transport);
enum VideoSourceScreenSharingType { enum VideoSourceScreenSharingType {
VideoSourceScreenSharingTypeArea = int(linphone::VideoSourceScreenSharingType::Area), VideoSourceScreenSharingTypeArea = int(linphone::VideoSourceScreenSharingType::Area),
@ -319,8 +333,6 @@ Q_ENUM_NS(VideoSourceScreenSharingType)
linphone::VideoSourceScreenSharingType toLinphone(const LinphoneEnums::VideoSourceScreenSharingType &type); linphone::VideoSourceScreenSharingType toLinphone(const LinphoneEnums::VideoSourceScreenSharingType &type);
LinphoneEnums::VideoSourceScreenSharingType fromLinphone(const linphone::VideoSourceScreenSharingType &type); LinphoneEnums::VideoSourceScreenSharingType fromLinphone(const linphone::VideoSourceScreenSharingType &type);
QString toString(const LinphoneEnums::TransportType &type);
void fromString(const QString &transportType, LinphoneEnums::TransportType *transport);
} // namespace LinphoneEnums } // namespace LinphoneEnums
/* /*
Q_DECLARE_METATYPE(LinphoneEnums::CallState) Q_DECLARE_METATYPE(LinphoneEnums::CallState)

View file

@ -105,13 +105,14 @@ QString Utils::getInitials(const QString &username) {
void Utils::createCall(const QString &sipAddress, void Utils::createCall(const QString &sipAddress,
QVariantMap options, QVariantMap options,
LinphoneEnums::MediaEncryption mediaEncryption,
const QString &prepareTransfertAddress, const QString &prepareTransfertAddress,
const QHash<QString, QString> &headers) { const QHash<QString, QString> &headers) {
lDebug() << "[Utils] create call with uri :" << sipAddress; lDebug() << "[Utils] create call with uri :" << sipAddress << mediaEncryption;
App::postModelAsync([sipAddress, options, prepareTransfertAddress, headers]() { App::postModelAsync([sipAddress, options, mediaEncryption, prepareTransfertAddress, headers]() {
QString errorMessage; QString errorMessage;
bool success = ToolModel::createCall(sipAddress, options, prepareTransfertAddress, headers, bool success = ToolModel::createCall(sipAddress, options, prepareTransfertAddress, headers,
linphone::MediaEncryption::None, &errorMessage); LinphoneEnums::toLinphone(mediaEncryption), &errorMessage);
if (!success) { if (!success) {
if (errorMessage.isEmpty()) errorMessage = tr("L'appel n'a pas pu être créé"); if (errorMessage.isEmpty()) errorMessage = tr("L'appel n'a pas pu être créé");
showInformationPopup("Erreur", errorMessage, false); showInformationPopup("Erreur", errorMessage, false);

View file

@ -26,6 +26,7 @@
#include <QString> #include <QString>
#include "Constants.hpp" #include "Constants.hpp"
#include "tool/LinphoneEnums.hpp"
// ============================================================================= // =============================================================================
@ -59,10 +60,12 @@ public:
Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName); Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName);
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32 Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
Q_INVOKABLE static void createCall(const QString &sipAddress, Q_INVOKABLE static void
QVariantMap options = {}, createCall(const QString &sipAddress,
const QString &prepareTransfertAddress = "", QVariantMap options = {},
const QHash<QString, QString> &headers = {}); LinphoneEnums::MediaEncryption mediaEncryption = LinphoneEnums::MediaEncryption::None,
const QString &prepareTransfertAddress = "",
const QHash<QString, QString> &headers = {});
Q_INVOKABLE static void openCallsWindow(CallGui *call); Q_INVOKABLE static void openCallsWindow(CallGui *call);
Q_INVOKABLE static void setupConference(ConferenceInfoGui *confGui); Q_INVOKABLE static void setupConference(ConferenceInfoGui *confGui);
Q_INVOKABLE static QQuickWindow *getMainWindow(); Q_INVOKABLE static QQuickWindow *getMainWindow();

View file

@ -74,6 +74,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Item/PhoneNumberInput.qml view/Item/PhoneNumberInput.qml
view/Item/Popup.qml view/Item/Popup.qml
view/Item/PopupButton.qml view/Item/PopupButton.qml
view/Item/ProgressBar.qml
view/Item/SecurityRadioButton.qml view/Item/SecurityRadioButton.qml
view/Item/RadioButton.qml view/Item/RadioButton.qml
view/Item/RectangleTest.qml view/Item/RectangleTest.qml

View file

@ -0,0 +1,41 @@
import QtQuick
import QtQuick.Controls
import Linphone
ProgressBar {
id: mainItem
padding: 3 * DefaultStyle.dp
property color backgroundColor: DefaultStyle.main2_100
property color innerColor: DefaultStyle.info_500_main
property color innerTextColor: DefaultStyle.grey_0
property bool innerTextVisible: true
property string innerText: Number.parseFloat(value*100).toFixed(0) + "%"
background: Rectangle {
color: mainItem.backgroundColor
radius: 50 * DefaultStyle.dp
anchors.fill: mainItem
width: mainItem.width
height: mainItem.height
}
contentItem: Item {
Rectangle {
color: mainItem.innerColor
radius: 50 * DefaultStyle.dp
width: mainItem.visualPosition * mainItem.width
height: parent.height
Text {
visible: innerTextVisible && mainItem.value > 0
text: mainItem.innerText
anchors.centerIn: parent
color: mainItem.innerTextColor
font {
pixelSize: 10 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
}
}
}

View file

@ -4,6 +4,8 @@ import QtQuick.Layouts
import QtQuick.Controls as Control import QtQuick.Controls as Control
import Linphone import Linphone
import UtilsCpp 1.0 import UtilsCpp 1.0
import EnumsToStringCpp 1.0
import SettingsCpp 1.0
AbstractMainPage { AbstractMainPage {
id: mainItem id: mainItem
@ -266,357 +268,415 @@ AbstractMainPage {
Component { Component {
id: contactDetail id: contactDetail
RowLayout { Item {
property string objectName: "contactDetail" property string objectName: "contactDetail"
visible: mainItem.selectedContact != undefined
Layout.fillWidth: true
Layout.fillHeight: true
Control.StackView.onActivated: mainItem.leftPanelEnabled = true Control.StackView.onActivated: mainItem.leftPanelEnabled = true
Control.StackView.onDeactivated: mainItem.leftPanelEnabled = false Control.StackView.onDeactivated: mainItem.leftPanelEnabled = false
ContactLayout { RowLayout {
Layout.fillWidth: true visible: mainItem.selectedContact != undefined
Layout.fillHeight: true anchors.fill: parent
Layout.alignment: Qt.AlignLeft | Qt.AlignTop anchors.topMargin: 45 * DefaultStyle.dp
Layout.topMargin: 45 * DefaultStyle.dp anchors.bottomMargin: 23 * DefaultStyle.dp
contact: mainItem.selectedContact ContactLayout {
Layout.preferredWidth: 360 * DefaultStyle.dp Layout.fillWidth: true
buttonContent: Button { Layout.fillHeight: true
width: 24 * DefaultStyle.dp Layout.alignment: Qt.AlignLeft | Qt.AlignTop
height: 24 * DefaultStyle.dp contact: mainItem.selectedContact
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
background: Item{}
onClicked: mainItem.editContact(mainItem.selectedContact)
icon.source: AppIcons.pencil
}
detailContent: ColumnLayout {
Layout.fillWidth: false
Layout.preferredWidth: 360 * DefaultStyle.dp Layout.preferredWidth: 360 * DefaultStyle.dp
spacing: 32 * DefaultStyle.dp buttonContent: Button {
width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
background: Item{}
onClicked: mainItem.editContact(mainItem.selectedContact)
icon.source: AppIcons.pencil
}
detailContent: ColumnLayout {
Layout.fillWidth: false
Layout.preferredWidth: 360 * DefaultStyle.dp
spacing: 32 * DefaultStyle.dp
ColumnLayout {
spacing: 9 * DefaultStyle.dp
Text {
Layout.leftMargin: 10 * DefaultStyle.dp
text: qsTr("Informations")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
RoundedBackgroundControl {
Layout.preferredHeight: Math.min(226 * DefaultStyle.dp, addrList.contentHeight + topPadding + bottomPadding)
height: Math.min(226 * DefaultStyle.dp, addrList.contentHeight)
Layout.fillWidth: true
topPadding: 12 * DefaultStyle.dp
bottomPadding: 12 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
contentItem: ListView {
id: addrList
width: 360 * DefaultStyle.dp
height: contentHeight
clip: true
spacing: 9 * DefaultStyle.dp
model: VariantList {
model: mainItem.selectedContact ? mainItem.selectedContact.core.allAddresses : []
}
delegate: Item {
width: addrList.width
height: 46 * DefaultStyle.dp
ColumnLayout {
anchors.fill: parent
// anchors.topMargin: 5 * DefaultStyle.dp
RowLayout {
Layout.fillWidth: true
// Layout.fillHeight: true
// Layout.alignment: Qt.AlignVCenter
// Layout.topMargin: 10 * DefaultStyle.dp
// Layout.bottomMargin: 10 * DefaultStyle.dp
ColumnLayout {
Layout.fillWidth: true
Text {
Layout.fillWidth: true
text: modelData.label
font {
pixelSize: 13 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
Text {
Layout.fillWidth: true
text: modelData.address
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
Item {
Layout.fillWidth: true
}
Button {
background: Item{}
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
icon.source: AppIcons.phone
width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
onClicked: {
UtilsCpp.createCall(modelData.address)
}
}
}
Rectangle {
visible: index != addrList.model.count - 1
Layout.fillWidth: true
Layout.preferredHeight: 1 * DefaultStyle.dp
Layout.rightMargin: 3 * DefaultStyle.dp
Layout.leftMargin: 3 * DefaultStyle.dp
color: DefaultStyle.main2_200
clip: true
}
}
}
}
}
}
RoundedBackgroundControl {
visible: companyText.text.length != 0 || jobText.text.length != 0
Layout.fillWidth: true
topPadding: 17 * DefaultStyle.dp
bottomPadding: 17 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
// Layout.fillHeight: true
contentItem: ColumnLayout {
// height: 100 * DefaultStyle.dp
RowLayout {
height: 50 * DefaultStyle.dp
Text {
text: qsTr("Company :")
font {
pixelSize: 13 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
Text {
id: companyText
text: mainItem.selectedContact && mainItem.selectedContact.core.organization
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
RowLayout {
height: 50 * DefaultStyle.dp
Text {
text: qsTr("Job :")
font {
pixelSize: 13 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
Text {
id: jobText
text: mainItem.selectedContact && mainItem.selectedContact.core.job
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
}
ColumnLayout {
visible: false
Text {
text: qsTr("Medias")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
Button {
Rectangle {
anchors.fill: parent
color: DefaultStyle.grey_0
radius: 15 * DefaultStyle.dp
}
contentItem: RowLayout {
Image {
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
source: AppIcons.shareNetwork
}
Text {
text: qsTr("Show media shared")
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
onClicked: console.debug("TODO : go to shared media")
}
}
}
}
}
ColumnLayout {
spacing: 10 * DefaultStyle.dp
Layout.rightMargin: 90 * DefaultStyle.dp
ColumnLayout {
RowLayout {
Text {
text: qsTr("Confiance")
Layout.leftMargin: 10 * DefaultStyle.dp
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
}
RoundedBackgroundControl {
contentItem: ColumnLayout {
spacing: 13 * DefaultStyle.dp
Text {
text: qsTr("Niveau de confiance - Appareils vérifiés")
font {
pixelSize: 13 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
Text {
visible: deviceList.count === 0
text: qsTr("Aucun appareil")
}
ProgressBar {
visible: deviceList.count > 0
Layout.preferredWidth: 320 * DefaultStyle.dp
Layout.preferredHeight: 28 * DefaultStyle.dp
value: mainItem.selectedContact ? mainItem.selectedContact.core.verifiedDeviceCount / deviceList.count : 0
}
ListView {
id: deviceList
Layout.fillWidth: true
Layout.preferredHeight: Math.min(200 * DefaultStyle.dp, contentHeight)
clip: true
model: mainItem.selectedContact ? mainItem.selectedContact.core.devices : []
spacing: 16 * DefaultStyle.dp
delegate: RowLayout {
id: deviceDelegate
width: deviceList.width
height: 30 * DefaultStyle.dp
property var callObj
property CallGui deviceCall: callObj ? callObj.value : null
Text {
text: modelData.name.length != 0 ? modelData.name : qsTr("Appareil sans nom")
font.pixelSize: 14 * DefaultStyle.dp
}
Item{Layout.fillWidth: true}
Image{
visible: modelData.securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
source: AppIcons.trusted
width: 22 * DefaultStyle.dp
height: 22 * DefaultStyle.dp
}
Button {
visible: modelData.securityLevel != LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
color: DefaultStyle.main1_100
icon.source: AppIcons.warningCircle
contentImageColor: DefaultStyle.main1_500_main
textColor: DefaultStyle.main1_500_main
textSize: 13 * DefaultStyle.dp
text: qsTr("Vérifier")
leftPadding: 12 * DefaultStyle.dp
rightPadding: 12 * DefaultStyle.dp
topPadding: 6 * DefaultStyle.dp
bottomPadding: 6 * DefaultStyle.dp
onClicked: {
UtilsCpp.createCall(modelData.address, {}, LinphoneEnums.MediaEncryption.Zrtp)
parent.callObj = UtilsCpp.getCallByAddress(modelData.address)
}
}
}
}
}
}
}
ColumnLayout { ColumnLayout {
spacing: 9 * DefaultStyle.dp spacing: 9 * DefaultStyle.dp
Text { Text {
Layout.preferredHeight: 22 * DefaultStyle.dp
Layout.leftMargin: 10 * DefaultStyle.dp Layout.leftMargin: 10 * DefaultStyle.dp
text: qsTr("Informations") text: qsTr("Other actions")
font { font {
pixelSize: 16 * DefaultStyle.dp pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp weight: 800 * DefaultStyle.dp
} }
} }
RoundedBackgroundControl { RoundedBackgroundControl {
Layout.preferredHeight: Math.min(226 * DefaultStyle.dp, addrList.contentHeight + topPadding + bottomPadding) Layout.preferredWidth: 360 * DefaultStyle.dp
height: Math.min(226 * DefaultStyle.dp, addrList.contentHeight) contentItem: ColumnLayout {
Layout.fillWidth: true width: parent.width
topPadding: 12 * DefaultStyle.dp
bottomPadding: 12 * DefaultStyle.dp IconLabelButton {
leftPadding: 20 * DefaultStyle.dp Layout.fillWidth: true
rightPadding: 20 * DefaultStyle.dp Layout.leftMargin: 15 * DefaultStyle.dp
contentItem: ListView { Layout.rightMargin: 15 * DefaultStyle.dp
id: addrList Layout.preferredHeight: 50 * DefaultStyle.dp
width: 360 * DefaultStyle.dp iconSize: 24 * DefaultStyle.dp
height: contentHeight iconSource: AppIcons.pencil
clip: true text: qsTr("Edit")
spacing: 9 * DefaultStyle.dp onClicked: mainItem.editContact(mainItem.selectedContact)
model: VariantList {
model: mainItem.selectedContact ? mainItem.selectedContact.core.allAddresses : []
} }
delegate: Item { Rectangle {
width: addrList.width Layout.fillWidth: true
height: 46 * DefaultStyle.dp Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
ColumnLayout { Layout.preferredHeight: 1 * DefaultStyle.dp
anchors.fill: parent color: DefaultStyle.main2_200
// anchors.topMargin: 5 * DefaultStyle.dp }
RowLayout { IconLabelButton {
Layout.fillWidth: true Layout.fillWidth: true
// Layout.fillHeight: true Layout.leftMargin: 15 * DefaultStyle.dp
// Layout.alignment: Qt.AlignVCenter Layout.rightMargin: 15 * DefaultStyle.dp
// Layout.topMargin: 10 * DefaultStyle.dp Layout.preferredHeight: 50 * DefaultStyle.dp
// Layout.bottomMargin: 10 * DefaultStyle.dp iconSize: 24 * DefaultStyle.dp
ColumnLayout { iconSource: mainItem.selectedContact && mainItem.selectedContact.core.starred ? AppIcons.heartFill : AppIcons.heart
Layout.fillWidth: true text: mainItem.selectedContact && mainItem.selectedContact.core.starred ? qsTr("Remove from favourites") : qsTr("Add to favourites")
Text { onClicked: if (mainItem.selectedContact) mainItem.selectedContact.core.lSetStarred(!mainItem.selectedContact.core.starred)
Layout.fillWidth: true }
text: modelData.label Rectangle {
font { Layout.fillWidth: true
pixelSize: 13 * DefaultStyle.dp Layout.leftMargin: 15 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp Layout.rightMargin: 15 * DefaultStyle.dp
} Layout.preferredHeight: 1 * DefaultStyle.dp
} color: DefaultStyle.main2_200
Text { }
Layout.fillWidth: true IconLabelButton {
text: modelData.address Layout.fillWidth: true
font { Layout.leftMargin: 15 * DefaultStyle.dp
pixelSize: 14 * DefaultStyle.dp Layout.rightMargin: 15 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp Layout.preferredHeight: 50 * DefaultStyle.dp
} iconSize: 24 * DefaultStyle.dp
} iconSource: AppIcons.shareNetwork
} text: qsTr("Share")
Item { onClicked: {
Layout.fillWidth: true if (mainItem.selectedContact) {
} var vcard = mainItem.selectedContact.core.getVCard()
Button { UtilsCpp.copyToClipboard(vcard)
background: Item{} UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("VCard copiée dans le presse-papier"))
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
icon.source: AppIcons.phone
width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
onClicked: {
UtilsCpp.createCall(modelData.address)
}
}
}
Rectangle {
visible: index != addrList.model.count - 1
Layout.fillWidth: true
Layout.preferredHeight: 1 * DefaultStyle.dp
Layout.rightMargin: 3 * DefaultStyle.dp
Layout.leftMargin: 3 * DefaultStyle.dp
color: DefaultStyle.main2_200
clip: true
} }
} }
} }
} Rectangle {
} Layout.fillWidth: true
} Layout.leftMargin: 15 * DefaultStyle.dp
RoundedBackgroundControl { Layout.rightMargin: 15 * DefaultStyle.dp
visible: companyText.text.length != 0 || jobText.text.length != 0 Layout.preferredHeight: 1 * DefaultStyle.dp
Layout.fillWidth: true color: DefaultStyle.main2_200
topPadding: 17 * DefaultStyle.dp }
bottomPadding: 17 * DefaultStyle.dp IconLabelButton {
leftPadding: 20 * DefaultStyle.dp Layout.fillWidth: true
rightPadding: 20 * DefaultStyle.dp Layout.leftMargin: 15 * DefaultStyle.dp
// Layout.fillHeight: true Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
contentItem: ColumnLayout { iconSize: 24 * DefaultStyle.dp
// height: 100 * DefaultStyle.dp iconSource: AppIcons.bellSlash
RowLayout { text: qsTr("Mute")
height: 50 * DefaultStyle.dp onClicked: console.log("TODO : mute contact")
Text { }
text: qsTr("Company :") Rectangle {
font { Layout.fillWidth: true
pixelSize: 13 * DefaultStyle.dp Layout.leftMargin: 15 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.empty
text: qsTr("Block")
onClicked: console.log("TODO : block contact")
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.trashCan
color: DefaultStyle.danger_500main
text: qsTr("Delete this contact")
onClicked: {
// mainItem.selectedContact.core.remove()
dialog.contact = mainItem.selectedContact
dialog.open()
} }
} }
Text {
id: companyText
text: mainItem.selectedContact && mainItem.selectedContact.core.organization
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
RowLayout {
height: 50 * DefaultStyle.dp
Text {
text: qsTr("Job :")
font {
pixelSize: 13 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
Text {
id: jobText
text: mainItem.selectedContact && mainItem.selectedContact.core.job
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
}
}
ColumnLayout {
visible: false
Text {
text: qsTr("Medias")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
Button {
Rectangle {
anchors.fill: parent
color: DefaultStyle.grey_0
radius: 15 * DefaultStyle.dp
}
contentItem: RowLayout {
Image {
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
source: AppIcons.shareNetwork
}
Text {
text: qsTr("Show media shared")
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
onClicked: console.debug("TODO : go to shared media")
}
}
}
}
ColumnLayout {
spacing: 10 * DefaultStyle.dp
Layout.rightMargin: 90 * DefaultStyle.dp
ColumnLayout {
visible: false
RowLayout {
Text {
text: qsTr("Confiance")
Layout.leftMargin: 10 * DefaultStyle.dp
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
}
RoundedBackgroundControl {
contentItem: ColumnLayout {
Text {
text: qsTr("Niveau de confiance - Appareils vérifiés")
}
}
}
}
ColumnLayout {
spacing: 9 * DefaultStyle.dp
Text {
Layout.preferredHeight: 22 * DefaultStyle.dp
Layout.leftMargin: 10 * DefaultStyle.dp
text: qsTr("Other actions")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
RoundedBackgroundControl {
Layout.preferredWidth: 360 * DefaultStyle.dp
contentItem: ColumnLayout {
width: parent.width
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.pencil
text: qsTr("Edit")
onClicked: mainItem.editContact(mainItem.selectedContact)
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: mainItem.selectedContact && mainItem.selectedContact.core.starred ? AppIcons.heartFill : AppIcons.heart
text: mainItem.selectedContact && mainItem.selectedContact.core.starred ? qsTr("Remove from favourites") : qsTr("Add to favourites")
onClicked: if (mainItem.selectedContact) mainItem.selectedContact.core.lSetStarred(!mainItem.selectedContact.core.starred)
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.shareNetwork
text: qsTr("Share")
onClicked: {
if (mainItem.selectedContact) {
var vcard = mainItem.selectedContact.core.getVCard()
UtilsCpp.copyToClipboard(vcard)
UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("VCard copiée dans le presse-papier"))
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.bellSlash
text: qsTr("Mute")
onClicked: console.log("TODO : mute contact")
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.empty
text: qsTr("Block")
onClicked: console.log("TODO : block contact")
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200
}
IconLabelButton {
Layout.fillWidth: true
Layout.leftMargin: 15 * DefaultStyle.dp
Layout.rightMargin: 15 * DefaultStyle.dp
Layout.preferredHeight: 50 * DefaultStyle.dp
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.trashCan
color: DefaultStyle.danger_500main
text: qsTr("Delete this contact")
onClicked: {
// mainItem.selectedContact.core.remove()
dialog.contact = mainItem.selectedContact
dialog.open()
}
} }
} }
} }
} }
// TODO : find device by friend
} }
} }
} }

View file

@ -98,4 +98,5 @@ QtObject {
property string debug: "image://internal/debug.svg" property string debug: "image://internal/debug.svg"
property string world: "image://internal/world.svg" property string world: "image://internal/world.svg"
property string detective: "image://internal/detective.svg" property string detective: "image://internal/detective.svg"
property string warningCircle: "image://internal/warning-circle.svg"
} }