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 e63c03bc..adae50d0 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 1f7b6226..04f73a0a 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 a3ef4438..e9eaa7fa 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 edda6c8c..0eb118dd 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 06c5d8d4..a71bf4e8 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 4b9f02a4..3b337e59 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 b12d8756..d93b0f96 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 4d35ec81..8c861fbe 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 7cefb31f..733fc8c3 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 d465cd5b..a11866b9 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 db4f8e7d..1c0e9bba 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 e60bc429..4dc17709 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 1861c48c..16b1e696 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 dc798e1c..b9062a1a 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 4b8bfebb..97cca337 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 0a024499..f8f55d52 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 72a22fdb..65382f90 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 f515b773..35ea66cd 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 35944060..1bcb0861 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 73c205de..8a506308 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 42e886fe..00217a53 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 64a01a92..af7b126b 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 78114e68..0d02ed25 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: {