improve unencrypted conversations warning indicator #LINQT-2061

allow user to choose an address for sending message when multiple addresses in contact #LINQT-2054

verify friend has a core to avoid crash in liblinphone #LINQT-1933

wait for window to be active before calling markAsRead (fix #LINQT-2048)

fix button text color (fix #LINQT-1832)

change format for mkv #LINQT-2056

Registration : check phone number format #LINQT-2044

fix window closing even if a new call is started #LINQT-2055

display popup to delete meetings on right click in meeting list item (allow to delete canceled meetings which cannot be displayed in the right panel)
This commit is contained in:
Gaelle Braud 2025-10-14 12:42:53 +02:00
parent a9a78cb4bf
commit 97b1d11adb
33 changed files with 1865 additions and 1682 deletions

View file

@ -1045,7 +1045,7 @@ void App::setCallsWindowProperty(const char *id, QVariant property) {
} }
void App::closeCallsWindow() { void App::closeCallsWindow() {
if (mCallsWindow) { if (mCallsWindow && mCallList && !mCallList->getHaveCall()) {
mCallsWindow->close(); mCallsWindow->close();
mCallsWindow->deleteLater(); mCallsWindow->deleteLater();
mCallsWindow = nullptr; mCallsWindow = nullptr;

View file

@ -29,6 +29,8 @@
#include "model/tool/ToolModel.hpp" #include "model/tool/ToolModel.hpp"
#include "tool/Utils.hpp" #include "tool/Utils.hpp"
#include <QQuickWindow>
DEFINE_ABSTRACT_OBJECT(ChatCore) DEFINE_ABSTRACT_OBJECT(ChatCore)
/***********************************************************************/ /***********************************************************************/
@ -232,7 +234,16 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
}); });
mChatModelConnection->makeConnectToCore(&ChatCore::lMarkAsRead, [this]() { mChatModelConnection->makeConnectToCore(&ChatCore::lMarkAsRead, [this]() {
mChatModelConnection->invokeToModel([this]() { mChatModel->markAsRead(); }); auto mainWindow = Utils::getMainWindow();
if (mainWindow->isActive()) mChatModelConnection->invokeToModel([this]() { mChatModel->markAsRead(); });
else {
connect(mainWindow, &QQuickWindow::activeChanged, this, [this, mainWindow] {
if (mainWindow->isActive()) {
disconnect(mainWindow, &QQuickWindow::activeChanged, this, nullptr);
mChatModelConnection->invokeToModel([this, mainWindow] { mChatModel->markAsRead(); });
}
});
}
}); });
mChatModelConnection->makeConnectToModel(&ChatModel::messagesRead, [this]() { mChatModelConnection->makeConnectToModel(&ChatModel::messagesRead, [this]() {
auto unread = mChatModel->getUnreadMessagesCount(); auto unread = mChatModel->getUnreadMessagesCount();

View file

@ -22,6 +22,8 @@
#include "core/App.hpp" #include "core/App.hpp"
#include "model/tool/ToolModel.hpp" #include "model/tool/ToolModel.hpp"
#include <QQuickWindow>
DEFINE_ABSTRACT_OBJECT(ChatMessageCore) DEFINE_ABSTRACT_OBJECT(ChatMessageCore)
/***********************************************************************/ /***********************************************************************/
@ -213,7 +215,17 @@ void ChatMessageCore::setSelf(QSharedPointer<ChatMessageCore> me) {
}); });
}); });
mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lMarkAsRead, [this] { mChatMessageModelConnection->makeConnectToCore(&ChatMessageCore::lMarkAsRead, [this] {
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->markAsRead(); }); auto mainWindow = Utils::getMainWindow();
if (mainWindow->isActive())
mChatMessageModelConnection->invokeToModel([this] { mChatMessageModel->markAsRead(); });
else {
connect(mainWindow, &QQuickWindow::activeChanged, this, [this, mainWindow] {
if (mainWindow->isActive()) {
disconnect(mainWindow, &QQuickWindow::activeChanged, this, nullptr);
mChatMessageModelConnection->invokeToModel([this, mainWindow] { mChatMessageModel->markAsRead(); });
}
});
}
}); });
mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageRead, [this]() { mChatMessageModelConnection->makeConnectToModel(&ChatMessageModel::messageRead, [this]() {
mChatMessageModelConnection->invokeToCore([this] { setIsRead(true); }); mChatMessageModelConnection->invokeToCore([this] { setIsRead(true); });

View file

@ -54,8 +54,8 @@ ParticipantCore::ParticipantCore(const std::shared_ptr<linphone::Participant> &p
mDisplayName = Utils::coreStringToAppString(participantAddress->getDisplayName()); mDisplayName = Utils::coreStringToAppString(participantAddress->getDisplayName());
if (mDisplayName.isEmpty()) mDisplayName = ToolModel::getDisplayName(participantAddress); if (mDisplayName.isEmpty()) mDisplayName = ToolModel::getDisplayName(participantAddress);
auto isFriend = ToolModel::findFriendByAddress(participantAddress); auto isFriend = ToolModel::findFriendByAddress(participantAddress);
mSecurityLevel = if (isFriend && isFriend->getCore()) mSecurityLevel = LinphoneEnums::fromLinphone(isFriend->getSecurityLevel());
isFriend ? LinphoneEnums::fromLinphone(isFriend->getSecurityLevel()) : LinphoneEnums::SecurityLevel::None; else mSecurityLevel = LinphoneEnums::SecurityLevel::None;
for (auto &device : participant->getDevices()) { for (auto &device : participant->getDevices()) {
auto name = Utils::coreStringToAppString(device->getName()); auto name = Utils::coreStringToAppString(device->getName());
auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly()); auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly());

View file

@ -38,15 +38,18 @@ RegisterPage::~RegisterPage() {
void RegisterPage::registerNewAccount(const QString &username, void RegisterPage::registerNewAccount(const QString &username,
const QString &password, const QString &password,
const QString &email, const QString &email,
const QString &countryCallingCode,
const QString &phoneNumber) { const QString &phoneNumber) {
App::postModelAsync([=]() { App::postModelAsync([=]() {
// Create on Model thread. // Create on Model thread.
// registrationFailed(error); });
AccountManager::RegisterType registerType; AccountManager::RegisterType registerType;
QString address; QString address;
if (email.isEmpty()) { if (email.isEmpty()) {
registerType = AccountManager::RegisterType::PhoneNumber; registerType = AccountManager::RegisterType::PhoneNumber;
address = phoneNumber; auto dialPlan = linphone::DialPlan::byCcc(Utils::appStringToCoreString(countryCallingCode));
auto formattedPhoneNumber = dialPlan->formatPhoneNumber(Utils::appStringToCoreString(phoneNumber), false);
address = Utils::coreStringToAppString(formattedPhoneNumber);
} else { } else {
registerType = AccountManager::RegisterType::Email; registerType = AccountManager::RegisterType::Email;
address = email; address = email;

View file

@ -39,8 +39,9 @@ public:
Q_INVOKABLE void registerNewAccount(const QString &username, Q_INVOKABLE void registerNewAccount(const QString &username,
const QString &password, const QString &password,
const QString &email, const QString &email = QString(),
const QString &phoneNumber); const QString &countryCallingCode = QString(),
const QString &phoneNumber = QString());
Q_INVOKABLE void Q_INVOKABLE void
linkNewAccountUsingCode(const QString &code, bool registerWithEmail, const QString &sipIdentityAddress); linkNewAccountUsingCode(const QString &code, bool registerWithEmail, const QString &sipIdentityAddress);

View file

@ -1 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,80H96V56a32,32,0,0,1,32-32c15.37,0,29.2,11,32.16,25.59a8,8,0,0,0,15.68-3.18C171.32,24.15,151.2,8,128,8A48.05,48.05,0,0,0,80,56V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80Zm0,128H48V96H208V208Z"></path></svg> <svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1_2)">
<path d="M208 88H48C43.5817 88 40 91.5817 40 96V208C40 212.418 43.5817 216 48 216H208C212.418 216 216 212.418 216 208V96C216 91.5817 212.418 88 208 88Z" stroke="black" stroke-width="16" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M88 88V56C88 45.3913 83.7857 35.2172 76.2843 27.7157C68.7828 20.2143 58.6087 16 48 16C28.65 16 11.71 29.74 8 48" stroke="black" stroke-width="16" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_1_2">
<rect width="256" height="256" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 682 B

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -56,7 +56,7 @@ void CallModel::accept(bool withVideo) {
params->setRecordFile( params->setRecordFile(
Paths::getCapturesDirPath() Paths::getCapturesDirPath()
.append(Utils::generateSavedFilename(QString::fromStdString(mMonitor->getToAddress()->getUsername()), "")) .append(Utils::generateSavedFilename(QString::fromStdString(mMonitor->getToAddress()->getUsername()), ""))
.append(".smff") .append(".mkv")
.toStdString()); .toStdString());
// Answer with local call address. // Answer with local call address.
auto localAddress = mMonitor->getCallLog()->getLocalAddress(); auto localAddress = mMonitor->getCallLog()->getLocalAddress();

View file

@ -36,8 +36,8 @@ ChatModel::ChatModel(const std::shared_ptr<linphone::ChatRoom> &chatroom, QObjec
mustBeInLinphoneThread(getClassName()); mustBeInLinphoneThread(getClassName());
auto coreModel = CoreModel::getInstance(); auto coreModel = CoreModel::getInstance();
if (coreModel) if (coreModel)
connect(coreModel.get(), &CoreModel::messageReadInChatRoom, this, connect(coreModel.get(), &CoreModel::chatRoomRead, this,
[this](std::shared_ptr<linphone::ChatRoom> chatroom) { [this](const std::shared_ptr<linphone::Core> &core, std::shared_ptr<linphone::ChatRoom> chatroom) {
if (chatroom == mMonitor) emit messagesRead(); if (chatroom == mMonitor) emit messagesRead();
}); });
} }
@ -90,7 +90,7 @@ std::list<std::shared_ptr<linphone::ChatMessage>> ChatModel::getChatMessageHisto
return res; return res;
} }
int ChatModel::getHistorySizeEvents() { int ChatModel::getHistorySizeEvents() const {
return mMonitor->getHistoryEventsSize(); return mMonitor->getHistoryEventsSize();
} }

View file

@ -57,7 +57,7 @@ public:
std::list<std::shared_ptr<linphone::EventLog>> std::list<std::shared_ptr<linphone::EventLog>>
getHistoryRangeNear(int before, int after, const std::shared_ptr<linphone::EventLog> firstEvent, int filters); getHistoryRangeNear(int before, int after, const std::shared_ptr<linphone::EventLog> firstEvent, int filters);
std::list<std::shared_ptr<linphone::ChatMessage>> getChatMessageHistory() const; std::list<std::shared_ptr<linphone::ChatMessage>> getChatMessageHistory() const;
int getHistorySizeEvents(); int getHistorySizeEvents() const;
QString getIdentifier() const; QString getIdentifier() const;
void deleteHistory(); void deleteHistory();
void deleteMessage(std::shared_ptr<linphone::ChatMessage> message); void deleteMessage(std::shared_ptr<linphone::ChatMessage> message);

View file

@ -330,7 +330,7 @@ bool ToolModel::createCall(const QString &sipAddress,
params->setRecordFile( params->setRecordFile(
Paths::getCapturesDirPath() Paths::getCapturesDirPath()
.append(Utils::generateSavedFilename(QString::fromStdString(address->getUsername()), "")) .append(Utils::generateSavedFilename(QString::fromStdString(address->getUsername()), ""))
.append(".smff") .append(".mkv")
.toStdString()); .toStdString());
} }

View file

@ -233,8 +233,7 @@ void Utils::closeCallsWindow() {
} }
QQuickWindow *Utils::getMainWindow() { QQuickWindow *Utils::getMainWindow() {
auto win = App::getInstance()->getMainWindow(); return App::getInstance()->getMainWindow();
return win;
} }
QQuickWindow *Utils::getLastActiveWindow() { QQuickWindow *Utils::getLastActiveWindow() {

View file

@ -120,13 +120,11 @@ Control.Button {
text: mainItem.text text: mainItem.text
textFormat: mainItem.textFormat textFormat: mainItem.textFormat
maximumLineCount: 1 maximumLineCount: 1
color: mainItem.checkable && mainItem.checked color: mainItem.checkable && mainItem.checked || mainItem.pressed
? mainItem.checkedColor || mainItem.pressedColor ? mainItem.pressedTextColor
: mainItem.pressed : mainItem.hovered
? mainItem.pressedTextColor ? mainItem.hoveredTextColor
: mainItem.hovered : mainItem.textColor
? mainItem.hoveredTextColor
: mainItem.textColor
font { font {
pixelSize: mainItem.textSize pixelSize: mainItem.textSize
weight: mainItem.textWeight weight: mainItem.textWeight

View file

@ -4,210 +4,193 @@ import QtQuick.Layouts
import QtQuick.Effects import QtQuick.Effects
import Linphone import Linphone
ColumnLayout { Control.ComboBox {
id: mainItem id: mainItem
property string label: ""
readonly property string currentText: combobox.model.getAt(combobox.currentIndex) ? "+" + combobox.model.getAt(combobox.currentIndex).countryCallingCode : ""
property string defaultCallingCode: "" property string defaultCallingCode: ""
property bool enableBackgroundColors: false property bool enableBackgroundColors: false
property string text: combobox.model.getAt(combobox.currentIndex) ? combobox.model.getAt(combobox.currentIndex).countryCallingCode : ""
Text { currentIndex: phoneNumberModel.count > 0 ? Math.max(0, phoneNumberModel.findIndexByCountryCallingCode(defaultCallingCode)) : -1
visible: mainItem.label.length > 0 Accessible.name: mainItem.Accessible.name
verticalAlignment: Text.AlignVCenter model: PhoneNumberProxy {
text: mainItem.label id: phoneNumberModel
color: combobox.activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.main2_600 }
font { background: Rectangle {
pixelSize: Typography.p2.pixelSize anchors.fill: parent
weight: Typography.p2.weight radius: Math.round(63 * DefaultStyle.dp)
bold: true color: mainItem.enableBackgroundColor ? DefaultStyle.grey_100 : "transparent"
border.color: mainItem.enableBackgroundColors
? (mainItem.errorMessage.length > 0
? DefaultStyle.danger_500_main
: textField.activeFocus
? DefaultStyle.main1_500_main
: DefaultStyle.grey_200)
: "transparent"
}
contentItem: RowLayout {
readonly property var currentItem: combobox.model.getAt(combobox.currentIndex)
spacing: 0// Math.round(5 * DefaultStyle.dp)
Text {
id: selectedItemFlag
visible: text.length > 0
font.pixelSize: Math.round(21 * DefaultStyle.dp)
text: parent.currentItem ? parent.currentItem.flag : ""
font.family: DefaultStyle.flagFont
}
// Rectangle{
// id: mask
// visible: false
// layer.enabled: true
// anchors.centerIn: selectedItemFlag
// radius: Math.round(600 * DefaultStyle.dp)
// width: selectedItemFlag.width/2
// height: selectedItemFlag.height/2
// }
// MultiEffect {
// visible: selectedItemFlag.text.length > 0
// anchors.centerIn: selectedItemFlag
// clip: true
// source: selectedItemFlag
// maskEnabled: true
// width: selectedItemFlag.width/2
// height: selectedItemFlag.height/2
// maskSource: mask
// }
Text {
id: countryCallingcode
text: parent.currentItem ? "+" + parent.currentItem.countryCallingCode : ""
color: DefaultStyle.main2_600
elide: Text.ElideRight
font: Typography.p1
} }
} }
Control.ComboBox { indicator: EffectImage {
id: combobox id: indicImage
currentIndex: phoneNumberModel.count > 0 ? Math.max(0, phoneNumberModel.findIndexByCountryCallingCode(defaultCallingCode)) : -1 z: 1
Accessible.name: mainItem.Accessible.name anchors.right: parent.right
model: PhoneNumberProxy { anchors.rightMargin: Math.round(15 * DefaultStyle.dp)
id: phoneNumberModel anchors.verticalCenter: parent.verticalCenter
} imageSource: AppIcons.downArrow
background: Rectangle { width: Math.round(15 * DefaultStyle.dp)
implicitWidth: mainItem.implicitWidth height: Math.round(15 * DefaultStyle.dp)
implicitHeight: mainItem.implicitHeight fillMode: Image.PreserveAspectFit
radius: Math.round(63 * DefaultStyle.dp) colorizationColor: mainItem.indicatorColor
color: mainItem.enableBackgroundColor ? DefaultStyle.grey_100 : "transparent" }
border.color: mainItem.enableBackgroundColors
? (mainItem.errorMessage.length > 0 popup: Control.Popup {
? DefaultStyle.danger_500_main id: listPopup
: textField.activeFocus y: combobox.height - 1
? DefaultStyle.main1_500_main width: Math.round(311 * DefaultStyle.dp)
: DefaultStyle.grey_200) height: Math.round(250 * DefaultStyle.dp)
: "transparent"
} contentItem: ListView {
contentItem: Item { id: listView
readonly property var currentItem: combobox.model.getAt(combobox.currentIndex) clip: true
anchors.leftMargin: Math.round(15 * DefaultStyle.dp) anchors.fill: parent
Text { model: PhoneNumberProxy{}
id: selectedItemFlag currentIndex: combobox.highlightedIndex >= 0 ? combobox.highlightedIndex : 0
visible: text.length > 0 keyNavigationEnabled: true
font.pixelSize: Math.round(21 * DefaultStyle.dp) keyNavigationWraps: true
text: parent.currentItem ? parent.currentItem.flag : "" maximumFlickVelocity: 1500
font.family: DefaultStyle.flagFont spacing: Math.round(10 * DefaultStyle.dp)
anchors.rightMargin: Math.round(5 * DefaultStyle.dp) highlight: Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left
}
// Rectangle{
// id: mask
// visible: false
// layer.enabled: true
// anchors.centerIn: selectedItemFlag
// radius: Math.round(600 * DefaultStyle.dp)
// width: selectedItemFlag.width/2
// height: selectedItemFlag.height/2
// }
// MultiEffect {
// visible: selectedItemFlag.text.length > 0
// anchors.centerIn: selectedItemFlag
// clip: true
// source: selectedItemFlag
// maskEnabled: true
// width: selectedItemFlag.width/2
// height: selectedItemFlag.height/2
// maskSource: mask
// }
Text {
leftPadding: Math.round(5 * DefaultStyle.dp)
text: parent.currentItem ? "+" + parent.currentItem.countryCallingCode : ""
color: DefaultStyle.main2_600
anchors.right: parent.right anchors.right: parent.right
anchors.left: selectedItemFlag.right width: listView.width
anchors.verticalCenter: parent.verticalCenter height: listView.height
elide: Text.ElideRight color: DefaultStyle.main2_300
font: Typography.p1 // radius: Math.round(15 * DefaultStyle.dp)
}
}
indicator: EffectImage {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
imageSource: AppIcons.downArrow
colorizationColor: DefaultStyle.main2_600
}
popup: Control.Popup {
id: listPopup
y: combobox.height - 1
width: Math.round(311 * DefaultStyle.dp)
height: Math.round(250 * DefaultStyle.dp)
contentItem: ListView {
id: listView
clip: true
anchors.fill: parent
model: PhoneNumberProxy{}
currentIndex: combobox.highlightedIndex >= 0 ? combobox.highlightedIndex : 0
keyNavigationEnabled: true
keyNavigationWraps: true
maximumFlickVelocity: 1500
spacing: Math.round(10 * DefaultStyle.dp)
highlight: Rectangle {
anchors.left: parent.left
anchors.right: parent.right
width: listView.width
height: listView.height
color: DefaultStyle.main2_300
// radius: Math.round(15 * DefaultStyle.dp)
}
delegate: Item {
width: listView.width
height: contentLayout.implicitHeight
RowLayout {
id: contentLayout
anchors.fill: parent
anchors.leftMargin: Math.round(20 * DefaultStyle.dp)
spacing: 0
Text {
id: delegateImg
visible: text.length > 0
text: $modelData.flag
font {
pixelSize: Math.round(28 * DefaultStyle.dp)
family: DefaultStyle.flagFont
}
}
Text {
id: countryText
text: $modelData.country
elide: Text.ElideRight
color: DefaultStyle.main2_500_main
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
}
Rectangle {
id: separator
width: Math.max(Math.round(1 * DefaultStyle.dp), 1)
height: combobox.height / 2
color: DefaultStyle.main2_500_main
}
Text {
text: "+" + $modelData.countryCallingCode
elide: Text.ElideRight
color: DefaultStyle.main2_500_main
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
}
Item {
Layout.fillWidth: true
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
Rectangle {
anchors.fill: parent
opacity: 0.1
radius: Math.round(15 * DefaultStyle.dp)
color: DefaultStyle.main2_500_main
visible: parent.containsMouse
}
onClicked: {
combobox.currentIndex = index
listPopup.close()
}
}
}
Control.ScrollIndicator.vertical: Control.ScrollIndicator { }
} }
onOpened: { delegate: Item {
listView.positionViewAtIndex(listView.currentIndex, ListView.Center) width: listView.width
} height: contentLayout.implicitHeight
RowLayout {
background: Item { id: contentLayout
anchors.fill: parent
Rectangle {
id: popupBg
anchors.fill: parent anchors.fill: parent
radius: Math.round(15 * DefaultStyle.dp) anchors.leftMargin: Math.round(20 * DefaultStyle.dp)
color: DefaultStyle.grey_100 spacing: Math.round(5 * DefaultStyle.dp)
Text {
id: delegateImg
visible: text.length > 0
text: $modelData.flag
font {
pixelSize: Math.round(28 * DefaultStyle.dp)
family: DefaultStyle.flagFont
}
}
Text {
id: countryText
text: $modelData.country
elide: Text.ElideRight
color: DefaultStyle.main2_500_main
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
}
Rectangle {
id: separator
width: Math.max(Math.round(1 * DefaultStyle.dp), 1)
height: combobox.height / 2
color: DefaultStyle.main2_500_main
}
Text {
text: "+" + $modelData.countryCallingCode
elide: Text.ElideRight
color: DefaultStyle.main2_500_main
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
}
Item {
Layout.fillWidth: true
}
} }
MultiEffect { MouseArea {
anchors.fill: popupBg anchors.fill: parent
source: popupBg hoverEnabled: true
shadowEnabled: true Rectangle {
shadowColor: DefaultStyle.grey_1000 anchors.fill: parent
shadowBlur: 0.1 opacity: 0.1
shadowOpacity: 0.1 radius: Math.round(15 * DefaultStyle.dp)
color: DefaultStyle.main2_500_main
visible: parent.containsMouse
}
onClicked: {
combobox.currentIndex = index
listPopup.close()
}
} }
} }
Control.ScrollIndicator.vertical: Control.ScrollIndicator { }
}
onOpened: {
listView.positionViewAtIndex(listView.currentIndex, ListView.Center)
}
background: Item {
anchors.fill: parent
Rectangle {
id: popupBg
anchors.fill: parent
radius: Math.round(15 * DefaultStyle.dp)
color: DefaultStyle.grey_100
}
MultiEffect {
anchors.fill: popupBg
source: popupBg
shadowEnabled: true
shadowColor: DefaultStyle.grey_1000
shadowBlur: 0.1
shadowOpacity: 0.1
}
} }
} }
} }

View file

@ -149,8 +149,12 @@ ColumnLayout {
button.onClicked: { button.onClicked: {
console.debug("[CallHistoryLayout.qml] Open conversation") console.debug("[CallHistoryLayout.qml] Open conversation")
if (mainItem.specificAddress === "") { if (mainItem.specificAddress === "") {
mainWindow.displayChatPage(mainItem.contact.core.defaultAddress) mainWindow.sendMessageToContact(mainItem.contact)
} else mainWindow.displayChatPage(mainItem.specificAddress) }
else {
console.log("specific address", mainItem.specificAddress)
mainWindow.displayChatPage(mainItem.specificAddress)
}
} }
} }
LabelButton { LabelButton {

View file

@ -319,7 +319,7 @@ ListView {
visible: modelData != undefined && modelData?.core.isBasic visible: modelData != undefined && modelData?.core.isBasic
Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0 Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0
Layout.preferredHeight: 14 * DefaultStyle.dp Layout.preferredHeight: 14 * DefaultStyle.dp
colorizationColor: DefaultStyle.warning_500_main colorizationColor: DefaultStyle.warning_700
imageSource: AppIcons.lockSimpleOpen imageSource: AppIcons.lockSimpleOpen
} }
EffectImage { EffectImage {

View file

@ -16,6 +16,7 @@ ListView {
property int lastIndexFoundWithFilter: -1 property int lastIndexFoundWithFilter: -1
property real busyIndicatorSize: Math.round(60 * DefaultStyle.dp) property real busyIndicatorSize: Math.round(60 * DefaultStyle.dp)
property bool loading: false property bool loading: false
property bool isEncrypted: chat && chat.core.isEncrypted
verticalLayoutDirection: ListView.BottomToTop verticalLayoutDirection: ListView.BottomToTop
signal showReactionsForMessageRequested(ChatMessageGui chatMessage) signal showReactionsForMessageRequested(ChatMessageGui chatMessage)
@ -127,7 +128,7 @@ ListView {
} }
footer: Item { footer: Item {
visible: mainItem.chat && !mainItem.loading && mainItem.chat.core.isEncrypted && !eventLogProxy.haveMore visible: mainItem.chat && !mainItem.loading
height: visible ? headerMessage.height + headerMessage.topMargin + headerMessage.bottomMargin : Math.round(30 * DefaultStyle.dp) height: visible ? headerMessage.height + headerMessage.topMargin + headerMessage.bottomMargin : Math.round(30 * DefaultStyle.dp)
width: headerMessage.width width: headerMessage.width
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@ -149,24 +150,30 @@ ListView {
EffectImage { EffectImage {
Layout.preferredWidth: Math.round(23 * DefaultStyle.dp) Layout.preferredWidth: Math.round(23 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(23 * DefaultStyle.dp) Layout.preferredHeight: Math.round(23 * DefaultStyle.dp)
imageSource: AppIcons.lockSimple imageSource: mainItem.isEncrypted ? AppIcons.lockSimple : AppIcons.lockSimpleOpen
colorizationColor: DefaultStyle.info_500_main colorizationColor: mainItem.isEncrypted ? DefaultStyle.info_500_main : DefaultStyle.warning_700
} }
ColumnLayout { ColumnLayout {
spacing: Math.round(2 * DefaultStyle.dp) spacing: Math.round(2 * DefaultStyle.dp)
Text { Text {
//: End to end encrypted chat text: mainItem.isEncrypted
text: qsTr("chat_message_list_encrypted_header_title") //: End to end encrypted chat
? qsTr("chat_message_list_encrypted_header_title")
//: This conversation is not encrypted !
: qsTr("unencrypted_conversation_warning")
Layout.fillWidth: true Layout.fillWidth: true
color: DefaultStyle.info_500_main color: mainItem.isEncrypted ? DefaultStyle.info_500_main : DefaultStyle.warning_700
font { font {
pixelSize: Typography.p2.pixelSize pixelSize: Typography.p2.pixelSize
weight: Typography.p2.weight weight: Typography.p2.weight
} }
} }
Text { Text {
//: Les messages de cette conversation sont chiffrés de bout \n en bout. Seul votre correspondant peut les déchiffrer. text: mainItem.isEncrypted
text: qsTr("chat_message_list_encrypted_header_message") //: Messages in this conversation are e2e encrypted. \n Only your correspondent can decrypt them.
? qsTr("chat_message_list_encrypted_header_message")
//: Messages are not end to end encrypted, \n may sure you don't share any sensitive information !
: qsTr("chat_message_list_not_encrypted_header_message")
Layout.fillWidth: true Layout.fillWidth: true
color: DefaultStyle.grey_400 color: DefaultStyle.grey_400
font { font {
@ -178,7 +185,7 @@ ListView {
} }
} }
} }
footerPositioning: ListView.PullBackFooter footerPositioning: mainItem.contentHeight > mainItem.height ? ListView.InlineFooter : ListView.PullBackFooter
headerPositioning: ListView.OverlayHeader headerPositioning: ListView.OverlayHeader
header: Control.Control { header: Control.Control {
visible: composeLayout.composingName !== "" && composeLayout.composingName !== undefined visible: composeLayout.composingName !== "" && composeLayout.composingName !== undefined

View file

@ -119,7 +119,7 @@ Item {
width: Math.round(24 * DefaultStyle.dp) width: Math.round(24 * DefaultStyle.dp)
height: Math.round(24 * DefaultStyle.dp) height: Math.round(24 * DefaultStyle.dp)
imageSource: AppIcons.playFill imageSource: AppIcons.playFill
colorizationColor: DefaultStyle.main2_000 colorizationColor: DefaultStyle.main2_0
} }
Text { Text {
z: parent.z + 1 z: parent.z + 1

View file

@ -8,6 +8,7 @@ import QtQml
import UtilsCpp import UtilsCpp
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
ListView { ListView {
id: mainItem id: mainItem
@ -24,6 +25,8 @@ ListView {
spacing: Math.round(8 * DefaultStyle.dp) spacing: Math.round(8 * DefaultStyle.dp)
highlightFollowsCurrentItem: false highlightFollowsCurrentItem: false
signal meetingDeletionRequested(ConferenceInfoGui confInfo, bool canCancel)
function selectIndex(index){ function selectIndex(index){
mainItem.currentIndex = index mainItem.currentIndex = index
@ -163,7 +166,7 @@ ListView {
visible: !mainItem.loading visible: !mainItem.loading
height: Math.round(63 * DefaultStyle.dp) + (!isFirst && dateDay.visible ? topOffset : 0) height: Math.round(63 * DefaultStyle.dp) + (!isFirst && dateDay.visible ? topOffset : 0)
width: mainItem.width width: mainItem.width
enabled: !isCanceled && haveModel enabled: haveModel
property var itemGui: $modelData property var itemGui: $modelData
// Do not use itemAtIndex because of caching items. Using getAt ensure to have a GUI // Do not use itemAtIndex because of caching items. Using getAt ensure to have a GUI
@ -307,12 +310,42 @@ ListView {
} }
} }
MouseArea { MouseArea {
id: mouseArea
hoverEnabled: mainItem.hoverEnabled hoverEnabled: mainItem.hoverEnabled
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: itemDelegate.isCanceled ? Qt.ArrowCursor : Qt.PointingHandCursor
visible: itemDelegate.haveModel visible: itemDelegate.haveModel
onClicked: { acceptedButtons: Qt.LeftButton | Qt.RightButton
mainItem.selectIndex(index) onClicked: (mouse) => {
console.log("clicked", mouse.button)
if (mouse.button === Qt.RightButton) {
console.log("open popup")
deletePopup.x = mouse.x
deletePopup.y = mouse.y
deletePopup.open()
}
else if (!itemDelegate.isCanceled) mainItem.selectIndex(index)
}
Popup {
id: deletePopup
parent: mouseArea
padding: Utils.getSizeWithScreenRatio(10)
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnPressOutside | Popup.CloseOnEscape
contentItem: IconLabelButton {
style: ButtonStyle.hoveredBackgroundRed
property var isMeObj: UtilsCpp.isMe(itemDelegate.itemGui?.core?.organizerAddress)
property bool canCancel: isMeObj && isMeObj.value && itemDelegate.itemGui?.core?.state !== LinphoneEnums.ConferenceInfoState.Cancelled
icon.source: AppIcons.trashCan
//: "Supprimer la réunion"
text: qsTr("meeting_info_delete")
onClicked: {
if (itemDelegate.itemGui) {
mainItem.meetingDeletionRequested(itemDelegate.itemGui, canCancel)
deletePopup.close()
}
}
}
} }
} }
} }

View file

@ -277,7 +277,7 @@ Control.Control {
Rectangle { Rectangle {
id: hoverContent id: hoverContent
anchors.fill: parent anchors.fill: parent
color: DefaultStyle.main2_000 color: DefaultStyle.main2_0
visible: false visible: false
radius: Math.round(20 * DefaultStyle.dp) radius: Math.round(20 * DefaultStyle.dp)

View file

@ -1,5 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Controls.Basic import QtQuick.Controls.Basic as Control
import QtQuick.Layouts import QtQuick.Layouts
import Linphone import Linphone
import CustomControls 1.0 import CustomControls 1.0
@ -15,10 +15,12 @@ ColumnLayout {
property real textInputWidth: width property real textInputWidth: width
property string initialPhoneNumber property string initialPhoneNumber
readonly property string phoneNumber: textField.text readonly property string phoneNumber: textField.text
readonly property string countryCode: combobox.currentText readonly property string countryCode: combobox.text
property string defaultCallingCode property string defaultCallingCode
property bool keyboardFocus: FocusHelper.keyboardFocus property bool keyboardFocus: FocusHelper.keyboardFocus
spacing: Math.round(5 * DefaultStyle.dp)
Text { Text {
visible: label.length > 0 visible: label.length > 0
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@ -30,13 +32,13 @@ ColumnLayout {
} }
} }
Item { Control.Control {
Layout.preferredWidth: contentBackground.width Layout.preferredWidth: mainItem.width
Layout.preferredHeight: contentBackground.height Layout.preferredHeight: Math.round(49 * DefaultStyle.dp)
Rectangle { leftPadding: Math.round(16 * DefaultStyle.dp)
background: Rectangle {
id: contentBackground id: contentBackground
width: mainItem.textInputWidth anchors.fill: parent
height: Math.round(49 * DefaultStyle.dp)
radius: Math.round(63 * DefaultStyle.dp) radius: Math.round(63 * DefaultStyle.dp)
color: DefaultStyle.grey_100 color: DefaultStyle.grey_100
border.color: mainItem.errorMessage.length > 0 border.color: mainItem.errorMessage.length > 0
@ -44,52 +46,51 @@ ColumnLayout {
: (textField.hasActiveFocus || combobox.hasActiveFocus) : (textField.hasActiveFocus || combobox.hasActiveFocus)
? DefaultStyle.main1_500_main ? DefaultStyle.main1_500_main
: DefaultStyle.grey_200 : DefaultStyle.grey_200
RowLayout { }
anchors.fill: parent contentItem: RowLayout {
CountryIndicatorCombobox { CountryIndicatorCombobox {
id: combobox id: combobox
implicitWidth: Math.round(110 * DefaultStyle.dp) implicitWidth: Math.round(110 * DefaultStyle.dp)
defaultCallingCode: mainItem.defaultCallingCode Layout.fillHeight: true
property bool keyboardFocus: FocusHelper.keyboardFocus defaultCallingCode: mainItem.defaultCallingCode
//: %1 prefix property bool keyboardFocus: FocusHelper.keyboardFocus
Accessible.name: qsTr("prefix_phone_number_accessible_name").arg(mainItem.Accessible.name) //: %1 prefix
} Accessible.name: qsTr("prefix_phone_number_accessible_name").arg(mainItem.Accessible.name)
Rectangle { }
Layout.preferredWidth: Math.max(Math.round(1 * DefaultStyle.dp), 1) Rectangle {
Layout.fillHeight: true Layout.preferredWidth: Math.max(Math.round(1 * DefaultStyle.dp), 1)
Layout.topMargin: Math.round(10 * DefaultStyle.dp) Layout.fillHeight: true
Layout.bottomMargin: Math.round(10 * DefaultStyle.dp) Layout.topMargin: Math.round(10 * DefaultStyle.dp)
color: DefaultStyle.main2_600 Layout.bottomMargin: Math.round(10 * DefaultStyle.dp)
} color: DefaultStyle.main2_600
TextField { }
id: textField TextField {
Layout.fillWidth: true id: textField
placeholderText: mainItem.placeholderText Layout.fillWidth: true
background: Item{} placeholderText: mainItem.placeholderText
initialText: initialPhoneNumber background: Item{}
validator: RegularExpressionValidator{ regularExpression: /[0-9]+/} initialText: initialPhoneNumber
property bool keyboardFocus: FocusHelper.keyboardFocus validator: RegularExpressionValidator{ regularExpression: /[0-9]+/}
//: %1 number property bool keyboardFocus: FocusHelper.keyboardFocus
Accessible.name: qsTr("number_phone_number_accessible_name").arg(mainItem.Accessible.name) //: %1 number
} Accessible.name: qsTr("number_phone_number_accessible_name").arg(mainItem.Accessible.name)
} }
} }
TemporaryText { }
id: errorText TemporaryText {
anchors.top: contentBackground.bottom id: errorText
// visible: mainItem.enableErrorText Layout.fillWidth: true
text: mainItem.errorMessage Layout.topMargin: Math.round(-3 * DefaultStyle.dp)
color: DefaultStyle.danger_500_main // visible: mainItem.enableErrorText
verticalAlignment: Text.AlignVCenter text: mainItem.errorMessage
elide: Text.ElideRight color: DefaultStyle.danger_500_main
wrapMode: Text.Wrap verticalAlignment: Text.AlignVCenter
font { elide: Text.ElideRight
pixelSize: Math.round(13 * DefaultStyle.dp) wrapMode: Text.Wrap
family: DefaultStyle.defaultFont font {
bold: true pixelSize: Math.round(13 * DefaultStyle.dp)
} family: DefaultStyle.defaultFont
Layout.preferredWidth: mainItem.textInputWidth bold: true
// Layout.preferredWidth: implicitWidth
} }
} }
} }

View file

@ -102,14 +102,23 @@ FocusScope {
capitalization: Font.Capitalize capitalization: Font.Capitalize
} }
} }
EffectImage { RowLayout {
visible: mainItem.chat != undefined && mainItem.chat.core.isBasic visible: mainItem.chat != undefined && mainItem.chat.core.isBasic
Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0 spacing: Math.round(8 * DefaultStyle.dp)
Layout.preferredHeight: 14 * DefaultStyle.dp EffectImage {
colorizationColor: DefaultStyle.warning_500_main Layout.preferredWidth: visible ? 14 * DefaultStyle.dp : 0
imageSource: AppIcons.lockSimpleOpen Layout.preferredHeight: 14 * DefaultStyle.dp
colorizationColor: DefaultStyle.warning_700
imageSource: AppIcons.lockSimpleOpen
}
Text {
Layout.fillWidth: true
color: DefaultStyle.warning_700
//: This conversation is not encrypted !
text: qsTr("unencrypted_conversation_warning")
font: Typography.p2
}
} }
Layout.fillWidth: true
EffectImage { EffectImage {
visible: mainItem.chat?.core.muted || false visible: mainItem.chat?.core.muted || false
Layout.preferredWidth: 20 * DefaultStyle.dp Layout.preferredWidth: 20 * DefaultStyle.dp

View file

@ -321,9 +321,9 @@ LoginLayout {
console.log("[RegisterPage] User: Call register") console.log("[RegisterPage] User: Call register")
mainItem.browserValidationRequested() mainItem.browserValidationRequested()
if (bar.currentIndex === 0) if (bar.currentIndex === 0)
RegisterPageCpp.registerNewAccount(usernameInput.text, pwdInput.text, "", phoneNumberInput.completePhoneNumber) RegisterPageCpp.registerNewAccount(usernameInput.text, pwdInput.text, "", phoneNumberInput.countryCode, phoneNumberInput.phoneNumber)
else else
RegisterPageCpp.registerNewAccount(usernameInput.text, pwdInput.text, emailInput.text, "") RegisterPageCpp.registerNewAccount(usernameInput.text, pwdInput.text, emailInput.text)
} }
} }
} }

View file

@ -153,7 +153,7 @@ Control.Page {
padding: 0 padding: 0
contentItem: Loader { contentItem: Loader {
id: contentLoader id: contentLoader
width: contentcontrol.width - contentControl.rightPadding width: contentControl.width - contentControl.rightPadding
} }
} }
} }

View file

@ -411,7 +411,7 @@ FriendGui{
button.icon.height: Math.round(24 * DefaultStyle.dp) button.icon.height: Math.round(24 * DefaultStyle.dp)
button.onClicked: { button.onClicked: {
console.debug("[ContactLayout.qml] Open conversation") console.debug("[ContactLayout.qml] Open conversation")
mainWindow.displayChatPage(contactDetail.contact.core.defaultAddress) mainWindow.sendMessageToContact(contactDetail.contact)
} }
} }
LabelButton { LabelButton {

View file

@ -81,6 +81,7 @@ AbstractMainPage {
Dialog { Dialog {
id: cancelAndDeleteConfDialog id: cancelAndDeleteConfDialog
property ConferenceInfoGui confInfoToDelete
property bool cancel: false property bool cancel: false
signal cancelRequested() signal cancelRequested()
// width: Math.round(278 * DefaultStyle.dp) // width: Math.round(278 * DefaultStyle.dp)
@ -88,6 +89,13 @@ AbstractMainPage {
text: cancel ? qsTr("meeting_schedule_cancel_dialog_message") text: cancel ? qsTr("meeting_schedule_cancel_dialog_message")
//: Souhaitez-vous supprimer cette réunion ? //: Souhaitez-vous supprimer cette réunion ?
: qsTr("meeting_schedule_delete_dialog_message") : qsTr("meeting_schedule_delete_dialog_message")
onCancelRequested: {
confInfoToDelete.core.lCancelConferenceInfo()
}
onAccepted: {
confInfoToDelete.core.lDeleteConferenceInfo()
}
buttons: [ buttons: [
BigButton { BigButton {
visible: cancelAndDeleteConfDialog.cancel visible: cancelAndDeleteConfDialog.cancel
@ -261,6 +269,11 @@ AbstractMainPage {
onSelectedConferenceChanged: { onSelectedConferenceChanged: {
mainItem.selectedConference = selectedConference mainItem.selectedConference = selectedConference
} }
onMeetingDeletionRequested: (confInfo, canCancel) => {
cancelAndDeleteConfDialog.confInfoToDelete = confInfo
cancelAndDeleteConfDialog.cancel = canCancel
cancelAndDeleteConfDialog.open()
}
Keys.onPressed: (event) => { Keys.onPressed: (event) => {
if(event.key == Qt.Key_Escape){ if(event.key == Qt.Key_Escape){
@ -691,21 +704,12 @@ AbstractMainPage {
onClicked: { onClicked: {
if (mainItem.selectedConference) { if (mainItem.selectedConference) {
cancelAndDeleteConfDialog.confInfoToDelete = mainItem.selectedConference
cancelAndDeleteConfDialog.cancel = canCancel cancelAndDeleteConfDialog.cancel = canCancel
cancelAndDeleteConfDialog.open() cancelAndDeleteConfDialog.open()
// mainItem.contactDeletionRequested(mainItem.selectedConference)
deletePopup.close() deletePopup.close()
} }
} }
Connections {
target: cancelAndDeleteConfDialog
function onCancelRequested() {
mainItem.selectedConference.core.lCancelConferenceInfo()
}
function onAccepted() {
mainItem.selectedConference.core.lDeleteConferenceInfo()
}
}
} }
} }
} }

View file

@ -51,96 +51,92 @@ ApplicationWindow {
} }
} }
Popup { Component {
id: startCallPopup id: addressChooserPopupComp
property FriendGui contact Popup {
property bool videoEnabled id: addressChooserPopup
// if currentCall, transfer call to contact property FriendGui contact
property CallGui currentCall signal addressChosen(string address)
onContactChanged: { underlineColor: DefaultStyle.main1_500_main
console.log("contact changed", contact) anchors.centerIn: parent
} width: Math.round(370 * DefaultStyle.dp)
underlineColor: DefaultStyle.main1_500_main modal: true
anchors.centerIn: parent leftPadding: Math.round(15 * DefaultStyle.dp)
width: Math.round(370 * DefaultStyle.dp) rightPadding: Math.round(15 * DefaultStyle.dp)
modal: true topPadding: Math.round(20 * DefaultStyle.dp)
leftPadding: Math.round(15 * DefaultStyle.dp) bottomPadding: Math.round(25 * DefaultStyle.dp)
rightPadding: Math.round(15 * DefaultStyle.dp) contentItem: ColumnLayout {
topPadding: Math.round(20 * DefaultStyle.dp) spacing: Math.round(16 * DefaultStyle.dp)
bottomPadding: Math.round(25 * DefaultStyle.dp) RowLayout {
contentItem: ColumnLayout { spacing: Math.round(5 * DefaultStyle.dp)
spacing: Math.round(16 * DefaultStyle.dp) width: addressChooserPopup.width
RowLayout { Text {
spacing: Math.round(5 * DefaultStyle.dp) //: "Choisissez un numéro ou adresse SIP"
width: startCallPopup.width text: qsTr("contact_dialog_pick_phone_number_or_sip_address_title")
Text { wrapMode: Text.Wrap
//: "Choisissez un numéro ou adresse SIP" Layout.fillWidth: true
text: qsTr("contact_dialog_pick_phone_number_or_sip_address_title") font {
wrapMode: Text.Wrap pixelSize: Typography.h4.pixelSize
weight: Typography.h4.weight
}
}
RoundButton {
Layout.alignment: Qt.AlignVCenter
style: ButtonStyle.noBackground
Layout.preferredWidth: Math.round(24 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(24 * DefaultStyle.dp)
icon.source:AppIcons.closeX
onClicked: addressChooserPopup.close()
}
}
ListView {
id: popuplist
model: VariantList {
model: addressChooserPopup.contact && addressChooserPopup.contact.core.allAddresses || []
}
Layout.fillWidth: true Layout.fillWidth: true
font { Layout.preferredHeight: contentHeight
pixelSize: Typography.h4.pixelSize spacing: Math.round(10 * DefaultStyle.dp)
weight: Typography.h4.weight delegate: Item {
}
}
RoundButton {
Layout.alignment: Qt.AlignVCenter
style: ButtonStyle.noBackground
Layout.preferredWidth: Math.round(24 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(24 * DefaultStyle.dp)
icon.source:AppIcons.closeX
onClicked: startCallPopup.close()
}
}
ListView {
id: popuplist
model: VariantList {
model: startCallPopup.contact && startCallPopup.contact.core.allAddresses || []
}
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
spacing: Math.round(10 * DefaultStyle.dp)
delegate: Item {
width: popuplist.width
height: Math.round(56 * DefaultStyle.dp)
ColumnLayout {
width: popuplist.width width: popuplist.width
anchors.verticalCenter: parent.verticalCenter height: Math.round(56 * DefaultStyle.dp)
spacing: Math.round(10 * DefaultStyle.dp)
ColumnLayout { ColumnLayout {
spacing: Math.round(7 * DefaultStyle.dp) width: popuplist.width
Text { anchors.verticalCenter: parent.verticalCenter
Layout.leftMargin: Math.round(5 * DefaultStyle.dp) spacing: Math.round(10 * DefaultStyle.dp)
text: modelData.label + " :" ColumnLayout {
font { spacing: Math.round(7 * DefaultStyle.dp)
pixelSize: Typography.p2.pixelSize Text {
weight: Typography.p2.weight Layout.leftMargin: Math.round(5 * DefaultStyle.dp)
text: modelData.label + " :"
font {
pixelSize: Typography.p2.pixelSize
weight: Typography.p2.weight
}
}
Text {
Layout.leftMargin: Math.round(5 * DefaultStyle.dp)
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(modelData.address) : modelData.address
font {
pixelSize: Typography.p1.pixelSize
weight: Typography.p1.weight
}
} }
} }
Text { Rectangle {
Layout.leftMargin: Math.round(5 * DefaultStyle.dp) visible: index != popuplist.model.count - 1
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(modelData.address) : modelData.address Layout.fillWidth: true
font { Layout.preferredHeight: Math.max(Math.round(1 * DefaultStyle.dp), 1)
pixelSize: Typography.p1.pixelSize color: DefaultStyle.main2_200
weight: Typography.p1.weight
}
} }
} }
Rectangle { MouseArea {
visible: index != popuplist.model.count - 1 anchors.fill: parent
Layout.fillWidth: true hoverEnabled: true
Layout.preferredHeight: Math.max(Math.round(1 * DefaultStyle.dp), 1) cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
color: DefaultStyle.main2_200 onClicked: {
} addressChooserPopup.addressChosen(modelData.address)
} }
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
if (startCallPopup.currentCall) startCallPopup.currentCall.core.lTransferCall(modelData.address)
else UtilsCpp.createCall(modelData.address, {'localVideoEnabled': startCallPopup.videoEnabled})
startCallPopup.close()
} }
} }
} }
@ -150,13 +146,17 @@ ApplicationWindow {
function startCallWithContact(contact, videoEnabled, parentItem) { function startCallWithContact(contact, videoEnabled, parentItem) {
if (parentItem == undefined) parentItem = mainWindow.contentItem if (parentItem == undefined) parentItem = mainWindow.contentItem
startCallPopup.parent = parentItem
if (contact) { if (contact) {
console.log("START CALL WITH", contact.core.fullName, "addresses count", contact.core.allAddresses.length) console.log("START CALL WITH", contact.core.fullName, "addresses count", contact.core.allAddresses.length)
if (contact.core.allAddresses.length > 1) { if (contact.core.allAddresses.length > 1) {
startCallPopup.contact = contact var addressPopup = addressChooserPopupComp.createObject()
startCallPopup.videoEnabled = videoEnabled addressPopup.parent = parentItem
startCallPopup.open() addressPopup.contact = contact
addressPopup.addressChosen.connect(function(address) {
UtilsCpp.createCall(address, {'localVideoEnabled': videoEnabled})
addressPopup.close()
})
addressPopup.open()
} else { } else {
var addressToCall = contact.core.defaultAddress.length === 0 var addressToCall = contact.core.defaultAddress.length === 0
@ -169,16 +169,41 @@ ApplicationWindow {
} }
} }
function sendMessageToContact(contact, parentItem) {
if (parentItem == undefined) parentItem = mainWindow.contentItem
if (contact) {
console.log("SEND MESSAGE TO", contact.core.fullName, "addresses count", contact.core.allAddresses.length)
if (contact.core.allAddresses.length > 1) {
var addressPopup = addressChooserPopupComp.createObject()
addressPopup.parent = parentItem
addressPopup.contact = contact
addressPopup.addressChosen.connect(function(address) {
displayChatPage(address)
addressPopup.close()
})
addressPopup.open()
} else {
displayChatPage(contact.core.defaultAddress)
if (addressToCall.length != 0) UtilsCpp.createCall(addressToCall, {'localVideoEnabled':videoEnabled})
}
}
}
function transferCallToContact(call, contact, parentItem) { function transferCallToContact(call, contact, parentItem) {
if (!call || !contact) return if (!call || !contact) return
if (parentItem == undefined) parentItem = mainWindow.contentItem if (parentItem == undefined) parentItem = mainWindow.contentItem
startCallPopup.parent = parentItem
if (contact) { if (contact) {
console.log("[AbstractWindow] Transfer call to", contact.core.fullName, "addresses count", contact.core.allAddresses.length, call) console.log("[AbstractWindow] Transfer call to", contact.core.fullName, "addresses count", contact.core.allAddresses.length, call)
if (contact.core.allAddresses.length > 1) { if (contact.core.allAddresses.length > 1) {
startCallPopup.contact = contact var addressPopup = addressChooserPopupComp.createObject()
startCallPopup.currentCall = call addressPopup.parent = parentItem
startCallPopup.open() addressPopup.contact = contact
addressPopup.addressChosen.connect(function(address) {
call.core.lTransferCall(address)
addressPopup.close()
})
addressPopup.open()
} else { } else {
var addressToCall = contact.core.defaultAddress.length === 0 var addressToCall = contact.core.defaultAddress.length === 0

View file

@ -218,6 +218,8 @@ AbstractWindow {
onHaveCallChanged: { onHaveCallChanged: {
if (!haveCall) { if (!haveCall) {
mainWindow.callEnded() mainWindow.callEnded()
} else {
bottomButtonsLayout.setButtonsEnabled(true)
} }
} }
} }
@ -1277,7 +1279,7 @@ AbstractWindow {
} }
function setButtonsEnabled(enabled) { function setButtonsEnabled(enabled) {
for (var i = 0; i < children.length; ++i) { for (var i = 0; i < children.length; ++i) {
children[i].enabled = false children[i].enabled = enabled
} }
} }

View file

@ -15,7 +15,7 @@ QtObject {
property color main1_600: currentTheme.main600 property color main1_600: currentTheme.main600
property color main1_700: currentTheme.main700 property color main1_700: currentTheme.main700
property color main2_000: "#FAFEFF" property color main2_0: "#FAFEFF"
property color main2_100: "#EEF6F8" property color main2_100: "#EEF6F8"
property color main2_200: "#DFECF2" property color main2_200: "#DFECF2"
property color main2_300: "#C0D1D9" property color main2_300: "#C0D1D9"
@ -38,6 +38,7 @@ QtObject {
property color grey_1000: "#000000" property color grey_1000: "#000000"
property color warning_600: "#DBB820" property color warning_600: "#DBB820"
property color warning_700: "#AF9308"
property color danger_500_main: "#DD5F5F" property color danger_500_main: "#DD5F5F"
property color warning_500_main: "#FFDC2E" property color warning_500_main: "#FFDC2E"
property color danger_700: "#9E3548" property color danger_700: "#9E3548"

View file

@ -21,7 +21,7 @@
} }
var mainLightBorder = Object.assign({ var mainLightBorder = Object.assign({
borderColor : { borderColor : {
keybaordFocused: Linphone.DefaultStyle.main2_000 keybaordFocused: Linphone.DefaultStyle.main2_0
} }
}, main) }, main)
@ -116,7 +116,7 @@
} }
var phoneRedLightBorder = Object.assign({ var phoneRedLightBorder = Object.assign({
borderColor : { borderColor : {
keybaordFocused: Linphone.DefaultStyle.main2_000 keybaordFocused: Linphone.DefaultStyle.main2_0
} }
}, phoneRed) }, phoneRed)
@ -151,7 +151,7 @@
pressed: Linphone.DefaultStyle.grey_0 pressed: Linphone.DefaultStyle.grey_0
}, },
borderColor: { borderColor: {
keybaordFocused: Linphone.DefaultStyle.main2_000 keybaordFocused: Linphone.DefaultStyle.main2_0
}, },
image: { image: {
normal: Linphone.DefaultStyle.grey_0, normal: Linphone.DefaultStyle.grey_0,
@ -205,7 +205,7 @@
} }
var noBackgroundLightBorder = Object.assign({ var noBackgroundLightBorder = Object.assign({
borderColor : { borderColor : {
keybaordFocused: Linphone.DefaultStyle.main2_000 keybaordFocused: Linphone.DefaultStyle.main2_0
} }
}, noBackground) }, noBackground)