From 517c6b96a52d1b7dd3ad79a8dc551b34e1ce9711 Mon Sep 17 00:00:00 2001 From: Gaelle Braud Date: Wed, 10 Jan 2024 17:39:21 +0100 Subject: [PATCH] FIXES: error text display show welcome page on first launch only try to fix crash in variant object (to fix properly) forbid connection if account already connected contacts list first row size + contact selected signal accounts layout rm layout rearrange warning login error messages layout trust circle avatar no error message on status ok busy indicator on login --- Linphone/core/App.cpp | 14 +- Linphone/core/App.hpp | 6 + Linphone/core/login/LoginPage.cpp | 28 +++- Linphone/core/login/LoginPage.hpp | 6 + Linphone/model/account/AccountManager.cpp | 12 +- Linphone/model/account/AccountManager.hpp | 3 +- Linphone/model/object/VariantObject.cpp | 10 +- Linphone/tool/LinphoneEnums.hpp | 1 - Linphone/tool/Utils.cpp | 9 ++ Linphone/tool/Utils.hpp | 2 + Linphone/view/App/Main.qml | 35 ++--- Linphone/view/Item/Account/Accounts.qml | 12 +- Linphone/view/Item/BusyIndicator.qml | 1 + Linphone/view/Item/Call/CallContactsLists.qml | 14 +- Linphone/view/Item/Contact/Avatar.qml | 24 ++++ Linphone/view/Item/Contact/Contact.qml | 123 ++++++++++-------- .../view/Item/Contact/ContactDescription.qml | 14 +- Linphone/view/Item/ContactsList.qml | 7 +- Linphone/view/Item/ErrorText.qml | 12 +- Linphone/view/Item/Form/LoginForm.qml | 91 +++++++++---- Linphone/view/Item/TextInput.qml | 11 +- .../view/Page/Login/RegisterCheckingPage.qml | 1 - Linphone/view/Page/Login/WelcomePage.qml | 12 +- 23 files changed, 304 insertions(+), 144 deletions(-) diff --git a/Linphone/core/App.cpp b/Linphone/core/App.cpp index e63c03bce..adae50d04 100644 --- a/Linphone/core/App.cpp +++ b/Linphone/core/App.cpp @@ -81,6 +81,7 @@ void App::init() { // Core. Manage the logger so it must be instantiate at first. auto coreModel = CoreModel::create("", mLinphoneThread); connect(mLinphoneThread, &QThread::started, coreModel.get(), &CoreModel::start); + mFirstLaunch = mSettings.value("firstLaunch", 1).toInt(); // Console Commands createCommandParser(); mParser->parse(this->arguments()); @@ -264,6 +265,17 @@ void App::closeCallsWindow() { } } +void App::setFirstLaunch(bool first) { + if (mFirstLaunch != first) { + mFirstLaunch = first; + mSettings.setValue("firstLaunch", first); + } +} + +bool App::getFirstLaunch() const { + return mFirstLaunch; +} + QQuickWindow *App::getMainWindow() { return mMainWindow; -} \ No newline at end of file +} diff --git a/Linphone/core/App.hpp b/Linphone/core/App.hpp index 1f7b62264..04f73a0a6 100644 --- a/Linphone/core/App.hpp +++ b/Linphone/core/App.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include "core/singleapplication/singleapplication.h" @@ -93,6 +94,9 @@ public: QQuickWindow *getCallsWindow(QVariant callGui); void closeCallsWindow(); + bool getFirstLaunch() const; + void setFirstLaunch(bool first); + QQuickWindow *getMainWindow(); QQmlApplicationEngine *mEngine = nullptr; @@ -108,6 +112,8 @@ private: Notifier *mNotifier = nullptr; QQuickWindow *mMainWindow = nullptr; QQuickWindow *mCallsWindow = nullptr; + QSettings mSettings; + bool mFirstLaunch = true; // TODO : changer ce count lorsqu'on aura liste d'appels int callsCount = 0; diff --git a/Linphone/core/login/LoginPage.cpp b/Linphone/core/login/LoginPage.cpp index a3ef4438c..e9eaa7fae 100644 --- a/Linphone/core/login/LoginPage.cpp +++ b/Linphone/core/login/LoginPage.cpp @@ -49,28 +49,48 @@ void LoginPage::setRegistrationState(linphone::RegistrationState status) { } } +QString LoginPage::getErrorMessage() const { + return mErrorMessage; +} + +void LoginPage::setErrorMessage(const QString &error) { + // force signal emission to display the error even if it doesn't change + mErrorMessage = error; + emit errorMessageChanged(); +} + void LoginPage::login(const QString &username, const QString &password) { App::postModelAsync([=]() { + QString *error = new QString(tr("Le couple identifiant mot de passe ne correspont pas")); // Create on Model thread. AccountManager *accountManager = new AccountManager(); connect(accountManager, &AccountManager::registrationStateChanged, this, - [accountManager, this](linphone::RegistrationState state) mutable { + [accountManager, this, error](linphone::RegistrationState state) mutable { // View thread setRegistrationState(state); switch (state) { - case linphone::RegistrationState::Ok: - case linphone::RegistrationState::Cleared: case linphone::RegistrationState::Failed: { + emit accountManager->errorMessageChanged(*error); accountManager->deleteLater(); break; } + case linphone::RegistrationState::Ok: { + emit accountManager->errorMessageChanged(""); + break; + } + case linphone::RegistrationState::Cleared: case linphone::RegistrationState::None: case linphone::RegistrationState::Progress: case linphone::RegistrationState::Refreshing: break; } }); - if (!accountManager->login(username, password)) { + connect(accountManager, &AccountManager::errorMessageChanged, this, + [this](QString errorMessage) { setErrorMessage(errorMessage); }); + + connect(accountManager, &AccountManager::destroyed, [error]() { delete error; }); + + if (!accountManager->login(username, password, error)) { emit accountManager->registrationStateChanged(linphone::RegistrationState::Failed); } }); diff --git a/Linphone/core/login/LoginPage.hpp b/Linphone/core/login/LoginPage.hpp index edda6c8c6..0eb118ddb 100644 --- a/Linphone/core/login/LoginPage.hpp +++ b/Linphone/core/login/LoginPage.hpp @@ -33,17 +33,23 @@ public: ~LoginPage(); Q_PROPERTY(linphone::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged) + Q_PROPERTY(QString errorMessage READ getErrorMessage NOTIFY errorMessageChanged) Q_INVOKABLE void login(const QString &username, const QString &password); linphone::RegistrationState getRegistrationState() const; void setRegistrationState(linphone::RegistrationState status); + QString getErrorMessage() const; + void setErrorMessage(const QString &error); + signals: void registrationStateChanged(); + void errorMessageChanged(); private: linphone::RegistrationState mRegistrationState = linphone::RegistrationState::None; + QString mErrorMessage; DECLARE_ABSTRACT_OBJECT }; diff --git a/Linphone/model/account/AccountManager.cpp b/Linphone/model/account/AccountManager.cpp index 06c5d8d42..a71bf4e8f 100644 --- a/Linphone/model/account/AccountManager.cpp +++ b/Linphone/model/account/AccountManager.cpp @@ -48,7 +48,7 @@ std::shared_ptr AccountManager::createAccount(const QString & return core->createAccount(core->createAccountParams()); } -bool AccountManager::login(QString username, QString password) { +bool AccountManager::login(QString username, QString password, QString *errorMessage) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); auto factory = linphone::Factory::get(); @@ -56,13 +56,23 @@ bool AccountManager::login(QString username, QString password) { auto params = account->getParams()->clone(); // Sip address. auto identity = params->getIdentityAddress()->clone(); + if (mAccountModel) return false; + auto accounts = core->getAccountList(); + for (auto account : accounts) { + if (account->getParams()->getIdentityAddress()->getUsername() == Utils::appStringToCoreString(username)) { + *errorMessage = tr("Le compte est déjà connecté"); + return false; + } + } identity->setUsername(Utils::appStringToCoreString(username)); if (params->setIdentityAddress(identity)) { qWarning() << log() .arg(QStringLiteral("Unable to set identity address: `%1`.")) .arg(Utils::coreStringToAppString(identity->asStringUriOnly())); + *errorMessage = + tr("Unable to set identity address: `%1`.").arg(Utils::coreStringToAppString(identity->asStringUriOnly())); return false; } diff --git a/Linphone/model/account/AccountManager.hpp b/Linphone/model/account/AccountManager.hpp index 4b9f02a47..3b337e592 100644 --- a/Linphone/model/account/AccountManager.hpp +++ b/Linphone/model/account/AccountManager.hpp @@ -33,7 +33,7 @@ public: AccountManager(QObject *parent = nullptr); ~AccountManager(); - bool login(QString username, QString password); + bool login(QString username, QString password, QString *errorMessage = nullptr); std::shared_ptr createAccount(const QString &assistantFile); @@ -42,6 +42,7 @@ public: const std::string &message); signals: void registrationStateChanged(linphone::RegistrationState state); + void errorMessageChanged(const QString &errorMessage); private: std::shared_ptr mAccountModel; diff --git a/Linphone/model/object/VariantObject.cpp b/Linphone/model/object/VariantObject.cpp index b12d87561..d93b0f960 100644 --- a/Linphone/model/object/VariantObject.cpp +++ b/Linphone/model/object/VariantObject.cpp @@ -37,10 +37,16 @@ VariantObject::VariantObject(QVariant defaultValue, QObject *parent) { new SafeConnection(mCoreObject, mModelObject), &QObject::deleteLater); mConnection->makeConnectToCore(&SafeObject::setValue, [this](QVariant value) { - mConnection->invokeToModel([this, value]() { mModelObject->onSetValue(value); }); + mConnection->invokeToModel([this, value]() { + // TODO : fix this properly + if (mModelObject) mModelObject->onSetValue(value); + }); }); mConnection->makeConnectToModel(&SafeObject::setValue, [this](QVariant value) { - mConnection->invokeToCore([this, value]() { mCoreObject->onSetValue(value); }); + mConnection->invokeToCore([this, value]() { + // TODO : fix this properly + if (mCoreObject) mCoreObject->onSetValue(value); + }); }); mConnection->makeConnectToModel(&SafeObject::valueChanged, [this](QVariant value) { mConnection->invokeToCore([this, value]() { mCoreObject->valueChanged(value); }); diff --git a/Linphone/tool/LinphoneEnums.hpp b/Linphone/tool/LinphoneEnums.hpp index 4d35ec810..8c861fbe5 100644 --- a/Linphone/tool/LinphoneEnums.hpp +++ b/Linphone/tool/LinphoneEnums.hpp @@ -315,7 +315,6 @@ Q_DECLARE_METATYPE(LinphoneEnums::FriendCapability) Q_DECLARE_METATYPE(LinphoneEnums::MediaEncryption) Q_DECLARE_METATYPE(LinphoneEnums::ParticipantDeviceState) Q_DECLARE_METATYPE(LinphoneEnums::RecorderState) -Q_DECLARE_METATYPE(LinphoneEnums::RegistrationState) Q_DECLARE_METATYPE(LinphoneEnums::TunnelMode) Q_DECLARE_METATYPE(LinphoneEnums::TransportType) */ diff --git a/Linphone/tool/Utils.cpp b/Linphone/tool/Utils.cpp index 7cefb31ff..733fc8c31 100644 --- a/Linphone/tool/Utils.cpp +++ b/Linphone/tool/Utils.cpp @@ -98,6 +98,15 @@ VariantObject *Utils::createCall(const QString &sipAddress, return data; } + +void Utils::setFirstLaunch(bool first) { + App::getInstance()->setFirstLaunch(first); +} + +bool Utils::getFirstLaunch() { + return App::getInstance()->getFirstLaunch(); +} + void Utils::openCallsWindow(CallGui *call) { if (call) App::getInstance()->getCallsWindow(QVariant::fromValue(call))->show(); } diff --git a/Linphone/tool/Utils.hpp b/Linphone/tool/Utils.hpp index d465cd5b3..a11866b9f 100644 --- a/Linphone/tool/Utils.hpp +++ b/Linphone/tool/Utils.hpp @@ -57,6 +57,8 @@ public: Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress, const QString &prepareTransfertAddress = "", const QHash &headers = {}); + Q_INVOKABLE static void setFirstLaunch(bool first); + Q_INVOKABLE static bool getFirstLaunch(); Q_INVOKABLE static void openCallsWindow(CallGui *call); Q_INVOKABLE static QQuickWindow *getMainWindow(); Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui); diff --git a/Linphone/view/App/Main.qml b/Linphone/view/App/Main.qml index db4f8e7db..1c0e9bba3 100644 --- a/Linphone/view/App/Main.qml +++ b/Linphone/view/App/Main.qml @@ -2,7 +2,7 @@ import QtQuick 2.15 import QtQuick.Layouts 1.3 import QtQuick.Controls import Linphone -//import UI 1.0 +import UtilsCpp 1.0 Window { id: mainWindow @@ -10,6 +10,7 @@ Window { height: 982 * DefaultStyle.dp visible: true title: qsTr("Linphone") + // TODO : handle this bool when security mode is implemented property bool firstConnection: true function goToNewCall() { @@ -21,25 +22,23 @@ Window { mainWindowStackView.currentItem.transferCallSucceed() } - AccountProxy{ + AccountProxy { + // TODO : change this so it does not display the main page for one second + // when we fail trying to connect the first account (account is added and + // removed shortly after) id: accountProxy - onHaveAccountChanged: { - if(haveAccount) - mainWindowStackView.replace(mainPage, StackView.Immediate) - else - mainWindowStackView.replace(loginPage, StackView.Immediate) - } } StackView { id: mainWindowStackView anchors.fill: parent - initialItem: accountProxy.haveAccount ? mainPage : welcomePage + initialItem: accountProxy.haveAccount ? mainPage : UtilsCpp.getFirstLaunch() ? welcomePage : loginPage } Component { id: welcomePage WelcomePage { onStartButtonPressed: { mainWindowStackView.replace(loginPage)// Replacing the first item will destroy the old. + UtilsCpp.setFirstLaunch(false) } } } @@ -51,11 +50,7 @@ Window { onUseSIPButtonClicked: mainWindowStackView.push(sipLoginPage) onGoToRegister: mainWindowStackView.replace(registerPage) onConnectionSucceed: { - if (mainWindow.firstConnection) { - mainWindowStackView.replace(securityModePage) - } else { - mainWindowStackView.replace(mainPage) - } + mainWindowStackView.replace(mainPage) } } } @@ -66,11 +61,7 @@ Window { onGoToRegister: mainWindowStackView.replace(registerPage) onConnectionSucceed: { - if (mainWindow.firstConnection) { - mainWindowStackView.replace(securityModePage) - } else { - mainWindowStackView.replace(mainPage) - } + mainWindowStackView.replace(mainPage) } } } @@ -92,7 +83,9 @@ Window { Component { id: securityModePage SecurityModePage { + id: securePage onModeSelected: (index) => { + // TODO : connect to cpp part when ready var selectedMode = index == 0 ? "chiffrement" : "interoperable" console.debug("[SelectMode]User: User selected mode " + selectedMode) mainWindowStackView.replace(mainPage) @@ -103,7 +96,7 @@ Window { id: mainPage MainLayout { onAddAccountRequest: mainWindowStackView.replace(loginPage) + // StackView.onActivated: connectionSecured(0) // TODO : connect to cpp part when ready } } -} - +} \ No newline at end of file diff --git a/Linphone/view/Item/Account/Accounts.qml b/Linphone/view/Item/Account/Accounts.qml index e60bc4297..4dc177090 100644 --- a/Linphone/view/Item/Account/Accounts.qml +++ b/Linphone/view/Item/Account/Accounts.qml @@ -11,21 +11,23 @@ Item { id: mainItem width: 517 * DefaultStyle.dp readonly property int topPadding: 23 * DefaultStyle.dp - readonly property int bottomPadding: 18 * DefaultStyle.dp + readonly property int bottomPadding: 23 * DefaultStyle.dp readonly property int leftPadding: 32 * DefaultStyle.dp readonly property int rightPadding: 32 * DefaultStyle.dp readonly property int spacing: 16 * DefaultStyle.dp signal addAccountRequest() - implicitHeight: list.contentHeight + topPadding + bottomPadding + 32 * DefaultStyle.dp + 1 + newAccountArea.height ColumnLayout{ + id: childLayout anchors.top: parent.top anchors.topMargin: mainItem.topPadding anchors.left: parent.left anchors.leftMargin: mainItem.leftPadding anchors.right: parent.right anchors.rightMargin: mainItem.rightPadding + anchors.bottom: parent.bottom + anchors.bottomMargin: mainItem.bottomPadding ListView{ id: list Layout.preferredHeight: contentHeight @@ -69,8 +71,10 @@ Item { EffectImage { id: newAccount source: AppIcons.plusCircle - Layout.fillHeight: true - Layout.preferredWidth: height + width: 32 * DefaultStyle.dp + height: 32 * DefaultStyle.dp + Layout.preferredWidth: 32 * DefaultStyle.dp + Layout.preferredHeight: 32 * DefaultStyle.dp Layout.alignment: Qt.AlignHCenter fillMode: Image.PreserveAspectFit colorizationColor: DefaultStyle.main2_500main diff --git a/Linphone/view/Item/BusyIndicator.qml b/Linphone/view/Item/BusyIndicator.qml index 1861c48cd..16b1e6965 100644 --- a/Linphone/view/Item/BusyIndicator.qml +++ b/Linphone/view/Item/BusyIndicator.qml @@ -12,6 +12,7 @@ Item { Control.BusyIndicator { id: busyIndicator running: mainItem.visible + anchors.centerIn: mainItem } MultiEffect { source: busyIndicator diff --git a/Linphone/view/Item/Call/CallContactsLists.qml b/Linphone/view/Item/Call/CallContactsLists.qml index dc798e1cb..b9062a1a6 100644 --- a/Linphone/view/Item/Call/CallContactsLists.qml +++ b/Linphone/view/Item/Call/CallContactsLists.qml @@ -55,9 +55,9 @@ Item { } Repeater { id: adresses - model: [{label: "SIP", address: startCallPopup.contact ? startCallPopup.contact.core.address : ""}, - {label: "Work", address: "06000000000"}, - {label: "Personal", address: "060000000"} + model: [{label: "SIP", address: startCallPopup.contact ? startCallPopup.contact.core.address : ""} + // {label: "Work", address: "06000000000"}, + // {label: "Personal", address: "060000000"} ] //account.adresses Button { id: channel @@ -235,6 +235,10 @@ Item { Layout.fillWidth: true id: contactList searchBarText: searchBar.text + onContactSelected: (contact) => { + startCallPopup.contact = contact + startCallPopup.open() + } } } ColumnLayout { @@ -254,6 +258,10 @@ Item { sourceFlags: LinphoneEnums.MagicSearchSource.FavoriteFriends aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend } + onContactSelected: (contact) => { + startCallPopup.contact = contact + startCallPopup.open() + } } } Item { diff --git a/Linphone/view/Item/Contact/Avatar.qml b/Linphone/view/Item/Contact/Avatar.qml index 4b8bfebbe..97cca3370 100644 --- a/Linphone/view/Item/Contact/Avatar.qml +++ b/Linphone/view/Item/Contact/Avatar.qml @@ -27,8 +27,32 @@ StackView{ || (contact && contact.core.pictureUri) onHaveAvatarChanged: replace(haveAvatar ? avatar : initials, StackView.Immediate) + + property bool secured: false initialItem: haveAvatar ? avatar : initials + + Rectangle { + visible: mainItem.secured + anchors.fill: mainItem.currentItem + radius: mainItem.width / 2 + z: 1 + color: "transparent" + border { + width: 3 * DefaultStyle.dp + color: DefaultStyle.info_500_main + } + Image { + source: AppIcons.trusted + x: mainItem.width / 7 + width: mainItem.width / 4.5 + height: width + sourceSize.width: width + sourceSize.height: height + fillMode: Image.PreserveAspectFit + anchors.bottom: parent.bottom + } + } Component{ id: initials Rectangle { diff --git a/Linphone/view/Item/Contact/Contact.qml b/Linphone/view/Item/Contact/Contact.qml index 0a024499c..f8f55d525 100644 --- a/Linphone/view/Item/Contact/Contact.qml +++ b/Linphone/view/Item/Contact/Contact.qml @@ -2,6 +2,7 @@ import QtQuick import QtQuick.Effects import QtQuick.Layouts +import QtQuick.Controls as Control import Linphone @@ -31,68 +32,76 @@ Rectangle{ onClicked: mainItem.avatarClicked() } } - ContactDescription{ - id: description - Layout.fillWidth: true + Item { + Layout.preferredWidth: 200 * DefaultStyle.dp Layout.fillHeight: true Layout.leftMargin: 10 * DefaultStyle.dp - account: mainItem.account - } - Item{ - id: registrationStatusItem - Layout.preferredWidth: 97 * DefaultStyle.dp - Layout.fillHeight: true - Rectangle{ - id: registrationStatus - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - width: Math.min(text.implicitWidth + (2 * 8 * DefaultStyle.dp), registrationStatusItem.width) - height: 24 * DefaultStyle.dp - color: DefaultStyle.main2_200 - radius: 90 * DefaultStyle.dp - Text{ - id: text - anchors.fill: parent - anchors.leftMargin: 8 * DefaultStyle.dp - anchors.rightMargin: 8 * DefaultStyle.dp - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - visible: mainItem.account - readonly property int mode : !mainItem.account || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Ok - ? 0 - : mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Cleared || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.None - ? 1 - : mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Progress || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Refreshing - ? 2 - : 3 - // Test texts - //Timer{ - // running: true - // interval: 1000 - // repeat: true - // onTriggered: text.mode = (++text.mode) % 4 - //} - font.weight: 300 * DefaultStyle.dp - font.pixelSize: 12 * DefaultStyle.dp - color: mode == 0 - ? DefaultStyle.success_500main - : mode == 1 - ? DefaultStyle.warning_600 - : mode == 2 - ? DefaultStyle.main2_500main - : DefaultStyle.danger_500main - text: mode == 0 - ? 'Connecté' - : mode == 1 - ? 'Désactivé' - : mode == 2 - ? 'Connexion...' - : 'Erreur' - } + Layout.rightMargin: 10 * DefaultStyle.dp + ContactDescription{ + id: description + anchors.fill: parent + account: mainItem.account } } + Control.Control { + id: registrationStatusItem + Layout.minimumWidth: 49 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + topPadding: 4 * DefaultStyle.dp + bottomPadding: 4 * DefaultStyle.dp + leftPadding: 8 * DefaultStyle.dp + rightPadding: 8 * DefaultStyle.dp + Layout.preferredWidth: text.implicitWidth + (2 * 8 * DefaultStyle.dp) + background: Rectangle{ + id: registrationStatus + anchors.fill: parent + color: DefaultStyle.main2_200 + radius: 90 * DefaultStyle.dp + } + contentItem: Text { + id: text + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + visible: mainItem.account + property int mode : !mainItem.account || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Ok + ? 0 + : mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Cleared || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.None + ? 1 + : mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Progress || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Refreshing + ? 2 + : 3 + // Test texts + // Timer{ + // running: true + // interval: 1000 + // repeat: true + // onTriggered: text.mode = (++text.mode) % 4 + // } + font.weight: 300 * DefaultStyle.dp + font.pixelSize: 12 * DefaultStyle.dp + color: mode == 0 + ? DefaultStyle.success_500main + : mode == 1 + ? DefaultStyle.warning_600 + : mode == 2 + ? DefaultStyle.main2_500main + : DefaultStyle.danger_500main + text: mode == 0 + ? qsTr("Connecté") + : mode == 1 + ? qsTr("Désactivé") + : mode == 2 + ? qsTr("Connexion...") + : qsTr("Erreur") + } + } + Item { + Layout.fillWidth: true + } Item{ - Layout.preferredWidth: 100 * DefaultStyle.dp + Layout.preferredWidth: 22 * DefaultStyle.dp + Layout.preferredHeight: 22 * DefaultStyle.dp Layout.fillHeight: true Rectangle{ id: unreadNotifications diff --git a/Linphone/view/Item/Contact/ContactDescription.qml b/Linphone/view/Item/Contact/ContactDescription.qml index 72a22fdb8..65382f902 100644 --- a/Linphone/view/Item/Contact/ContactDescription.qml +++ b/Linphone/view/Item/Contact/ContactDescription.qml @@ -12,9 +12,9 @@ ColumnLayout{ property string topText: displayName ? displayName.value : '' property string bottomText: account ? account.core.identityAddress : '' spacing: 0 - Text{ + width: topTextItem.implicitWidth + Text { id: topTextItem - Layout.fillWidth: true Layout.fillHeight: true verticalAlignment: (bottomTextItem.visible?Text.AlignBottom:Text.AlignVCenter) visible: text != '' @@ -22,10 +22,13 @@ ColumnLayout{ font.pixelSize: 14 * DefaultStyle.dp color: DefaultStyle.main2_700 text: mainItem.topText + width: mainItem.width + Layout.preferredWidth: mainItem.width + wrapMode: Text.WrapAnywhere + maximumLineCount: 1 } - Text{ + Text { id: bottomTextItem - Layout.fillWidth: true Layout.fillHeight: true verticalAlignment: (topTextItem.visible?Text.AlignTop:Text.AlignVCenter) visible: text != '' @@ -33,5 +36,8 @@ ColumnLayout{ font.pixelSize: 12 * DefaultStyle.dp color: DefaultStyle.main2_400 text: mainItem.bottomText + Layout.preferredWidth: mainItem.width + maximumLineCount: 1 + wrapMode: Text.WrapAnywhere } } diff --git a/Linphone/view/Item/ContactsList.qml b/Linphone/view/Item/ContactsList.qml index f515b7732..35ea66cd8 100644 --- a/Linphone/view/Item/ContactsList.qml +++ b/Linphone/view/Item/ContactsList.qml @@ -16,6 +16,8 @@ ListView { property bool contactMenuVisible: true property bool initialHeadersVisible: true + signal contactSelected(var contact) + model: MagicSearchProxy { searchText: searchBarText.length === 0 ? "*" : searchBarText } @@ -40,6 +42,7 @@ ListView { } Item { width: mainItem.width + Layout.preferredWidth: mainItem.width height: 56 * DefaultStyle.dp RowLayout { anchors.fill: parent @@ -129,9 +132,7 @@ ListView { visible: contactArea.containsMouse || friendPopup.hovered } onClicked: { - startCallPopup.contact = modelData - startCallPopup.open() - // mainItem.callButtonPressed(modelData.core.address) + mainItem.contactSelected(modelData) } } } diff --git a/Linphone/view/Item/ErrorText.qml b/Linphone/view/Item/ErrorText.qml index 35944060d..1bcb0861b 100644 --- a/Linphone/view/Item/ErrorText.qml +++ b/Linphone/view/Item/ErrorText.qml @@ -8,6 +8,12 @@ Text { id: mainItem color: DefaultStyle.danger_500main opacity: 0 + function displayText() { + mainItem.state = "Visible" + } + function hideText() { + mainItem.state = "Invisible" + } font { pixelSize: 13 * DefaultStyle.dp weight: 600 * DefaultStyle.dp @@ -30,10 +36,6 @@ Text { property: "opacity" duration: 1000 } - // NumberAnimation { - // property: "visible" - // duration: 1100 - // } } ] Timer { @@ -48,7 +50,7 @@ Text { target: mainItem onTextChanged: { if (mainItem.text.length > 0) { - errorText.state = "Visible" + mainItem.state = "Visible" } } } diff --git a/Linphone/view/Item/Form/LoginForm.qml b/Linphone/view/Item/Form/LoginForm.qml index 73c205de0..8a506308d 100644 --- a/Linphone/view/Item/Form/LoginForm.qml +++ b/Linphone/view/Item/Form/LoginForm.qml @@ -1,5 +1,5 @@ import QtQuick 2.15 -import QtQuick.Layouts 1.0 +import QtQuick.Layouts import QtQuick.Controls as Control import Linphone @@ -24,32 +24,38 @@ ColumnLayout { value: DefaultStyle.danger_500main } } - TextInput { - id: password - label: "Password" - mandatory: true - hidden: true - enableErrorText: true - Binding on background.border.color { - when: errorText.opacity != 0 - value: DefaultStyle.danger_500main - } - Binding on textField.color { - when: errorText.opacity != 0 - value: DefaultStyle.danger_500main - } - } + Item { + Layout.preferredHeight: password.implicitHeight + TextInput { + id: password + label: "Password" + mandatory: true + hidden: true + enableErrorText: true - ErrorText { - id: errorText - Connections { - target: LoginPageCpp - onRegistrationStateChanged: { - if (LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Failed) { - errorText.text = qsTr("Le couple identifiant mot de passe ne correspont pas") - } else if (LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Ok) { - mainItem.connectionSucceed() + Binding on background.border.color { + when: errorText.opacity != 0 + value: DefaultStyle.danger_500main + } + Binding on textField.color { + when: errorText.opacity != 0 + value: DefaultStyle.danger_500main + } + } + + ErrorText { + anchors.bottom: password.bottom + id: errorText + Connections { + target: LoginPageCpp + onErrorMessageChanged: { + errorText.text = LoginPageCpp.errorMessage + } + onRegistrationStateChanged: { + if (LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Ok) { + mainItem.connectionSucceed() + } } } } @@ -58,11 +64,43 @@ ColumnLayout { RowLayout { id: lastFormLineLayout Button { - text: qsTr("Connexion") + contentItem: StackLayout { + id: connectionButton + currentIndex: 0 + Text { + text: qsTr("Connexion") + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + font { + pixelSize: 18 * DefaultStyle.dp + weight: 600 * DefaultStyle.dp + } + color: DefaultStyle.grey_0 + } + BusyIndicator { + width: parent.height + height: parent.height + Layout.alignment: Qt.AlignCenter + indicatorColor: DefaultStyle.grey_0 + } + Connections { + target: LoginPageCpp + onRegistrationStateChanged: { + if (LoginPageCpp.registrationState != LinphoneEnums.RegistrationState.Progress) { + connectionButton.currentIndex = 0 + } + } + onErrorMessageChanged: { + connectionButton.currentIndex = 0 + } + } + } Layout.rightMargin: 20 * DefaultStyle.dp onClicked: { username.errorMessage = "" password.errorMessage = "" + errorText.text = "" if (username.text.length == 0 || password.text.length == 0) { if (username.text.length == 0) @@ -72,6 +110,7 @@ ColumnLayout { return } LoginPageCpp.login(username.text, password.text) + connectionButton.currentIndex = 1 } } Button { diff --git a/Linphone/view/Item/TextInput.qml b/Linphone/view/Item/TextInput.qml index 42e886fe9..00217a530 100644 --- a/Linphone/view/Item/TextInput.qml +++ b/Linphone/view/Item/TextInput.qml @@ -18,6 +18,7 @@ ColumnLayout { property string initialText property bool enableErrorText: false + property bool errorTextVisible: errorText.opacity > 0 property alias textField: textField property alias background: input @@ -61,11 +62,11 @@ ColumnLayout { radius: 79 * DefaultStyle.dp color: mainItem.enableBackgroundColors ? DefaultStyle.grey_100 : "transparent" border.color: mainItem.enableBackgroundColors - ? errorText.opacity === 0 - ? textField.activeFocus + ? mainItem.errorTextVisible + ? DefaultStyle.danger_500main + : textField.activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.grey_200 - : DefaultStyle.danger_500main : "transparent" Control.TextField { @@ -82,7 +83,7 @@ ColumnLayout { pixelSize: 14 * DefaultStyle.dp weight: 400 * DefaultStyle.dp } - color: errorText.opacity === 0 ? DefaultStyle.main2_600 : DefaultStyle.danger_500main + color: mainItem.errorTextVisible ? DefaultStyle.danger_500main : DefaultStyle.main2_600 selectByMouse: true validator: mainItem.validator background: Item { @@ -117,6 +118,6 @@ ColumnLayout { id: errorText visible: mainItem.enableErrorText text: mainItem.errorMessage - Layout.preferredWidth: mainItem.textInputWidth + Layout.preferredWidth: implicitWidth } } diff --git a/Linphone/view/Page/Login/RegisterCheckingPage.qml b/Linphone/view/Page/Login/RegisterCheckingPage.qml index 64a01a92e..af7b126be 100644 --- a/Linphone/view/Page/Login/RegisterCheckingPage.qml +++ b/Linphone/view/Page/Login/RegisterCheckingPage.qml @@ -76,7 +76,6 @@ LoginLayout { required property int index Layout.preferredWidth: width Layout.preferredHeight: height - Component.onCompleted: console.log("completed", width, Layout.preferredWidth) onTextEdited: { console.log("textfield text", text, index) if (text.length > 0 ) { diff --git a/Linphone/view/Page/Login/WelcomePage.qml b/Linphone/view/Page/Login/WelcomePage.qml index 78114e68a..0d02ed25d 100644 --- a/Linphone/view/Page/Login/WelcomePage.qml +++ b/Linphone/view/Page/Login/WelcomePage.qml @@ -54,7 +54,7 @@ LoginLayout { } } } - centerContent: ColumnLayout { + centerContent: Item { id: centerLayout Layout.bottomMargin: 20 * DefaultStyle.dp Layout.fillWidth: false @@ -62,6 +62,7 @@ LoginLayout { Layout.leftMargin: 250 * DefaultStyle.dp Layout.topMargin: 165 * DefaultStyle.dp RowLayout { + id: carouselLayout Image { id: carouselImg Layout.rightMargin: 40 * DefaultStyle.dp @@ -104,10 +105,11 @@ LoginLayout { } Button { - Layout.topMargin: 20 * DefaultStyle.dp - Layout.bottomMargin: 20 * DefaultStyle.dp - Layout.leftMargin: (centerLayout.width - width) * DefaultStyle.dp - Layout.alignment: Qt.AlignBottom | Qt.AlignRight + anchors.top: carouselLayout.bottom + anchors.right: carouselLayout.right + anchors.topMargin: 20 * DefaultStyle.dp + anchors.bottomMargin: 20 * DefaultStyle.dp + anchors.leftMargin: (centerLayout.width - width) * DefaultStyle.dp y: centerLayout.implicitWidth - width text: carousel.currentIndex < (carousel.itemsCount - 1) ? qsTr("Suivant") : qsTr("Commencer") onClicked: {