Commit 9954c943 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(ui/views/App/Main/Assistant): supports login with username/password

parent 0526a6cd
......@@ -86,6 +86,7 @@ set(SOURCES
src/app/providers/AvatarProvider.cpp
src/app/providers/ThumbnailProvider.cpp
src/app/translator/DefaultTranslator.cpp
src/components/assistant/AssistantModel.cpp
src/components/call/CallModel.cpp
src/components/calls/CallsListModel.cpp
src/components/camera/Camera.cpp
......@@ -123,15 +124,17 @@ set(HEADERS
src/app/providers/AvatarProvider.hpp
src/app/providers/ThumbnailProvider.hpp
src/app/translator/DefaultTranslator.hpp
src/components/assistant/AssistantModel.hpp
src/components/camera/Camera.hpp
src/components/camera/MSFunctions.hpp
src/components/call/CallModel.hpp
src/components/calls/CallsListModel.hpp
src/components/camera/MSFunctions.hpp
src/components/chat/ChatModel.hpp
src/components/chat/ChatProxyModel.hpp
src/components/codecs/AbstractCodecsModel.hpp
src/components/codecs/AudioCodecsModel.hpp
src/components/codecs/VideoCodecsModel.hpp
src/components/Components.hpp
src/components/contact/ContactModel.hpp
src/components/contact/VcardModel.hpp
src/components/contacts/ContactsListModel.hpp
......
......@@ -124,6 +124,49 @@
<translation>CREATE A LINPHONE ACCOUNT</translation>
</message>
</context>
<context>
<name>AssistantModel</name>
<message>
<source>loginWithUsernameFailed</source>
<translation>Login failed. Please check your username/password.</translation>
</message>
<message>
<source>usernameStatusTooShort</source>
<translation>Too short! (%1 characters min.)</translation>
</message>
<message>
<source>usernameStatusTooLong</source>
<translation>Too long! (%1 characters max.)</translation>
</message>
<message>
<source>usernameStatusInvalidCharacters</source>
<translation>Invalid characters detected. (regex: `%1`.)</translation>
</message>
<message>
<source>usernameStatusInvalid</source>
<translation>Invalid username.</translation>
</message>
<message>
<source>passwordStatusTooShort</source>
<translation>Too short! (%1 characters min.)</translation>
</message>
<message>
<source>passwordStatusTooLong</source>
<translation>Too long! (%1 characters max.)</translation>
</message>
<message>
<source>passwordStatusInvalidCharacters</source>
<translation>Invalid characters detected. (regex: `%1`.)</translation>
</message>
<message>
<source>passwordStatusMissingCharacters</source>
<translation>Missing characters: `%1`.</translation>
</message>
<message>
<source>requestFailed</source>
<translation>Unable to send the request.</translation>
</message>
</context>
<context>
<name>AssistantUseLinphoneSipAccount</name>
<message>
......
......@@ -124,6 +124,49 @@
<translation>CRÉER UN COMPTE LINPHONE</translation>
</message>
</context>
<context>
<name>AssistantModel</name>
<message>
<source>usernameStatusTooShort</source>
<translation>Trop court ! (%1 caractères min.)</translation>
</message>
<message>
<source>usernameStatusTooLong</source>
<translation>Trop long ! (%1 caractères max.)</translation>
</message>
<message>
<source>usernameStatusInvalidCharacters</source>
<translation>Caractères invalides détectés. (regex: `%1`.)</translation>
</message>
<message>
<source>usernameStatusInvalid</source>
<translation>Nom d&apos;utilisateur invalide.</translation>
</message>
<message>
<source>passwordStatusTooShort</source>
<translation>Trop court ! (%1 caractères min.)</translation>
</message>
<message>
<source>passwordStatusTooLong</source>
<translation>Trop long ! (%1 caractères max.)&gt;</translation>
</message>
<message>
<source>passwordStatusInvalidCharacters</source>
<translation>Caractères invalides détectés. (regex: `%1`.)</translation>
</message>
<message>
<source>passwordStatusMissingCharacters</source>
<translation>Caractères manquants : `%1`.</translation>
</message>
<message>
<source>requestFailed</source>
<translation>Impossible d&apos;envoyer la requête.</translation>
</message>
<message>
<source>loginWithUsernameFailed</source>
<translation>La connection a échouée. Merci de vérifier le nom d&apos;utilisateur/mot de passe.</translation>
</message>
</context>
<context>
<name>AssistantUseLinphoneSipAccount</name>
<message>
......
......@@ -263,10 +263,11 @@
<file>ui/modules/Common/Window/Window.js</file>
<file>ui/modules/Common/Window/Window.qml</file>
<file>ui/modules/Linphone/Account/AccountStatus.qml</file>
<file>ui/modules/Linphone/Blocks/CardBlock.qml</file>
<file>ui/modules/Linphone/Blocks/RequestBlock.qml</file>
<file>ui/modules/Linphone/Calls/CallControls.qml</file>
<file>ui/modules/Linphone/Calls/Calls.js</file>
<file>ui/modules/Linphone/Calls/Calls.qml</file>
<file>ui/modules/Linphone/CardBlock.qml</file>
<file>ui/modules/Linphone/Chat/Chat.js</file>
<file>ui/modules/Linphone/Chat/Chat.qml</file>
<file>ui/modules/Linphone/Chat/Event.qml</file>
......@@ -291,9 +292,10 @@
<file>ui/modules/Linphone/qmldir</file>
<file>ui/modules/Linphone/SmartSearchBar.qml</file>
<file>ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml</file>
<file>ui/modules/Linphone/Styles/Blocks/CardBlockStyle.qml</file>
<file>ui/modules/Linphone/Styles/Blocks/RequestBlockStyle.qml</file>
<file>ui/modules/Linphone/Styles/Calls/CallControlsStyle.qml</file>
<file>ui/modules/Linphone/Styles/Calls/CallsStyle.qml</file>
<file>ui/modules/Linphone/Styles/CardBlockStyle.qml</file>
<file>ui/modules/Linphone/Styles/ChatStyle.qml</file>
<file>ui/modules/Linphone/Styles/Codecs/CodecsViewerStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/AvatarStyle.qml</file>
......
......@@ -20,17 +20,7 @@
* Author: Ronan Abhamon
*/
#include "../components/calls/CallsListModel.hpp"
#include "../components/camera/Camera.hpp"
#include "../components/chat/ChatProxyModel.hpp"
#include "../components/codecs/AudioCodecsModel.hpp"
#include "../components/codecs/VideoCodecsModel.hpp"
#include "../components/contacts/ContactsListProxyModel.hpp"
#include "../components/core/CoreManager.hpp"
#include "../components/presence/OwnPresenceModel.hpp"
#include "../components/settings/AccountSettingsModel.hpp"
#include "../components/smart-search-bar/SmartSearchBarModel.hpp"
#include "../components/timeline/TimelineModel.hpp"
#include "../components/Components.hpp"
#include "../utils.hpp"
#include "logger/Logger.hpp"
......@@ -269,6 +259,7 @@ void registerSingletonType (const char *name) {
void App::registerTypes () {
qInfo() << "Registering types...";
qmlRegisterType<AssistantModel>("Linphone", 1, 0, "AssistantModel");
qmlRegisterType<Camera>("Linphone", 1, 0, "Camera");
qmlRegisterType<ContactsListProxyModel>("Linphone", 1, 0, "ContactsListProxyModel");
qmlRegisterType<ChatModel>("Linphone", 1, 0, "ChatModel");
......@@ -291,10 +282,10 @@ void App::registerTypes () {
);
registerSingletonType<AccountSettingsModel>("AccountSettingsModel");
registerSingletonType<AudioCodecsModel>("AudioCodecsModel");
registerSingletonType<OwnPresenceModel>("OwnPresenceModel");
registerSingletonType<Presence>("Presence");
registerSingletonType<TimelineModel>("TimelineModel");
registerSingletonType<AudioCodecsModel>("AudioCodecsModel");
registerSingletonType<VideoCodecsModel>("VideoCodecsModel");
registerSharedSingletonType(App, "App", App::getInstance);
......
/*
* Components.hpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: April 6, 2017
* Author: Ronan Abhamon
*/
#include "assistant/AssistantModel.hpp"
#include "calls/CallsListModel.hpp"
#include "camera/Camera.hpp"
#include "chat/ChatProxyModel.hpp"
#include "codecs/AudioCodecsModel.hpp"
#include "codecs/VideoCodecsModel.hpp"
#include "contacts/ContactsListProxyModel.hpp"
#include "core/CoreManager.hpp"
#include "presence/OwnPresenceModel.hpp"
#include "settings/AccountSettingsModel.hpp"
#include "smart-search-bar/SmartSearchBarModel.hpp"
#include "timeline/TimelineModel.hpp"
/*
* AssistantModel.cpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: April 6, 2017
* Author: Ronan Abhamon
*/
#include "../../utils.hpp"
#include "../core/CoreManager.hpp"
#include "AssistantModel.hpp"
#define DEFAULT_XMLRPC_URL "https://subscribe.linphone.org:444/wizard.php"
using namespace std;
// =============================================================================
class AssistantModel::Handlers : public linphone::AccountCreatorListener {
public:
Handlers (AssistantModel *assistant) {
m_assistant = assistant;
}
void onCreateAccount (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onIsAccountExist (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &
) override {
if (status == linphone::AccountCreatorStatusAccountExist || status == linphone::AccountCreatorStatusAccountExistWithAlias) {
CoreManager::getInstance()->getCore()->addProxyConfig(creator->configure());
emit m_assistant->loginStatusChanged("");
} else {
if (status == linphone::AccountCreatorStatusRequestFailed)
emit m_assistant->loginStatusChanged(tr("requestFailed"));
else
emit m_assistant->loginStatusChanged(tr("loginWithUsernameFailed"));
}
}
void onActivateAccount (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onIsAccountActivated (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onLinkAccount (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onActivateAlias (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onIsAliasUsed (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onIsAccountLinked (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onRecoverAccount (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
void onUpdateAccount (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
const string &resp
) override {}
private:
AssistantModel *m_assistant;
};
// -----------------------------------------------------------------------------
AssistantModel::AssistantModel (QObject *parent) : QObject(parent) {
m_handlers = make_shared<AssistantModel::Handlers>(this);
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
m_account_creator = core->createAccountCreator(
core->getConfig()->getString("assistant", "xmlrpc_url", DEFAULT_XMLRPC_URL)
);
m_account_creator->setListener(m_handlers);
}
// -----------------------------------------------------------------------------
void AssistantModel::setUsername (const QString &username) {
shared_ptr<linphone::Config> config = CoreManager::getInstance()->getCore()->getConfig();
QString error;
switch (m_account_creator->setUsername(::Utils::qStringToLinphoneString(username))) {
case linphone::AccountCreatorUsernameStatusOk:
break;
case linphone::AccountCreatorUsernameStatusTooShort:
error = tr("usernameStatusTooShort").arg(config->getInt("assistant", "username_min_length", 1));
break;
case linphone::AccountCreatorUsernameStatusTooLong:
error = tr("usernameStatusTooLong").arg(config->getInt("assistant", "username_max_length", -1));
break;
case linphone::AccountCreatorUsernameStatusInvalidCharacters:
error = tr("usernameStatusInvalidCharacters")
.arg(::Utils::linphoneStringToQString(config->getString("assistant", "username_regex", "")));
break;
case linphone::AccountCreatorUsernameStatusInvalid:
error = tr("usernameStatusInvalid");
break;
}
emit usernameChanged(username, error);
}
void AssistantModel::setPassword (const QString &password) {
shared_ptr<linphone::Config> config = CoreManager::getInstance()->getCore()->getConfig();
QString error;
switch (m_account_creator->setPassword(::Utils::qStringToLinphoneString(password))) {
case linphone::AccountCreatorPasswordStatusOk:
break;
case linphone::AccountCreatorPasswordStatusTooShort:
error = tr("passwordStatusTooShort").arg(config->getInt("assistant", "password_min_length", 1));
break;
case linphone::AccountCreatorPasswordStatusTooLong:
error = tr("passwordStatusTooLong").arg(config->getInt("assistant", "password_max_length", -1));
break;
case linphone::AccountCreatorPasswordStatusInvalidCharacters:
error = tr("passwordStatusInvalidCharacters")
.arg(::Utils::linphoneStringToQString(config->getString("assistant", "password_regex", "")));
break;
case linphone::AccountCreatorPasswordStatusMissingCharacters:
error = tr("passwordStatusMissingCharacters")
.arg(::Utils::linphoneStringToQString(config->getString("assistant", "missing_characters", "")));
break;
}
emit passwordChanged(password, error);
}
// -----------------------------------------------------------------------------
void AssistantModel::login () {
m_account_creator->isAccountExist();
}
/*
* AssistantModel.hpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: April 6, 2017
* Author: Ronan Abhamon
*/
#ifndef ASSISTANT_MODEL_H_
#define ASSISTANT_MODEL_H_
#include <linphone++/linphone.hh>
#include <QObject>
// =============================================================================
class AssistantModel : public QObject {
class Handlers;
Q_OBJECT;
public:
AssistantModel (QObject *parent = Q_NULLPTR);
Q_INVOKABLE void setUsername (const QString &username);
Q_INVOKABLE void setPassword (const QString &password);
Q_INVOKABLE void login ();
signals:
void usernameChanged (const QString &username, const QString &error);
void passwordChanged (const QString &password, const QString &error);
void loginStatusChanged (const QString &error);
private:
std::shared_ptr<linphone::AccountCreator> m_account_creator;
std::shared_ptr<Handlers> m_handlers;
};
#endif // ASSISTANT_MODEL_H_
......@@ -38,4 +38,6 @@ QtObject {
property color x: '#96A5B1'
property color y: '#D0D8DE'
property color z: '#17A81A'
property color error: '#FF0000'
}
......@@ -12,11 +12,14 @@ Controls.TextField {
id: textField
property alias icon: icon.icon
property string error: ''
property var tools
background: Rectangle {
border {
color: TextFieldStyle.background.border.color
color: textField.error.length > 0
? TextFieldStyle.background.border.color.error
: TextFieldStyle.background.border.color.normal
width: TextFieldStyle.background.border.width
}
......@@ -39,7 +42,9 @@ Controls.TextField {
id: toolsContainer
border {
color: TextFieldStyle.background.border.color
color: textField.error.length > 0
? TextFieldStyle.background.border.color.error
: TextFieldStyle.background.border.color.normal
width: TextFieldStyle.background.border.width
}
......
......@@ -7,6 +7,7 @@ import Common.Styles 1.0
Column {
property alias title: title.text
property bool dealWithErrors: false
property int orientation: Qt.Horizontal
// ---------------------------------------------------------------------------
......
......@@ -9,6 +9,7 @@ Loader {
property string label
readonly property int orientation: parent.orientation
readonly property bool dealWithErrors: parent.dealWithErrors
default property var _content: null
......
......@@ -15,6 +15,7 @@ Row {
return curWidth < maxWidth ? curWidth : maxWidth
}
readonly property int orientation: parent.orientation
readonly property bool dealWithErrors: parent.dealWithErrors
// ---------------------------------------------------------------------------
......
......@@ -54,4 +54,20 @@ ColumnLayout {
}
}
}
Text {
Layout.fillWidth: true
Layout.preferredHeight: FormVGroupStyle.error.height
color: FormVGroupStyle.error.color
elide: Text.ElideRight
font {
italic: true
pointSize: FormVGroupStyle.error.fontSize
}
text: _content && _content.error && _content.error.length ? _content.error : ''
visible: parent.parent.dealWithErrors
}
}
......@@ -13,7 +13,11 @@ QtObject {
property int radius: 4
property QtObject border: QtObject {
property color color: Colors.c
property QtObject color: QtObject {
property color error: Colors.error
property color normal: Colors.c
}
property int width: 1
}
......
......@@ -12,6 +12,12 @@ QtObject {
property int maxWidth: 400
}
property QtObject error: QtObject {
property color color: Colors.error
property int fontSize: 10
property int height: 16
}
property QtObject legend: QtObject {
property color color: Colors.j
property int fontSize: 10
......
import QtQuick 2.7
import Common 1.0
import Linphone.Styles 1.0
// =============================================================================
Item {
id: block
property var action
readonly property alias loading: block._loading
property bool _loading: false
// ----------------------------------------------------------------------------
function execute () {
block._loading = true
action()
}
function stop (error) {
errorBlock.text = error
block._loading = false
}
// ----------------------------------------------------------------------------
height: RequestBlockStyle.height
Text {
id: errorBlock
color: RequestBlockStyle.error.color
elide: Text.ElideRight
font {
italic: true
pointSize: RequestBlockStyle.error.fontSize
}
height: parent.height
width: parent.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
visible: !block.loading
}
BusyIndicator {
anchors.centerIn: parent
height: RequestBlockStyle.loadingIndicator.height
width: RequestBlockStyle.loadingIndicator.width
running: block.loading
}
}
pragma Singleton
import QtQuick 2.7
import Common 1.0
// =============================================================================
QtObject {
property int height: 60
property QtObject error: QtObject {
property color color: Colors.error
property int fontSize: 11
}
property QtObject loadingIndicator: QtObject {
property int height: 20
property int width: 20
}
}
......@@ -6,7 +6,8 @@ module Linphone.Styles
singleton AccountStatusStyle 1.0 Account/AccountStatusStyle.qml
singleton CardBlockStyle 1.0 CardBlockStyle.qml
singleton CardBlockStyle 1.0 Blocks/CardBlockStyle.qml
singleton RequestBlockStyle 1.0 Blocks/RequestBlockStyle.qml
singleton ChatStyle 1.0 ChatStyle.qml
......
......@@ -8,7 +8,8 @@ module Linphone
AccountStatus 1.0 Account/AccountStatus.qml
CardBlock 1.0 CardBlock.qml
CardBlock 1.0 Blocks/CardBlock.qml
RequestBlock 1.0 Blocks/RequestBlock.qml
Calls 1.0 Calls/Calls.qml
......
import QtQuick 2.7
import Common 1.0
import Linphone 1.0
import App.Styles 1.0
// =============================================================================
AssistantAbstractView {
mainAction: (function () {
console.log('TODO')
})
mainAction: requestBlock.execute
mainActionEnabled: {
var item = loader.item
return item && item.mainActionEnabled
return item && item.mainActionEnabled && !requestBlock.loading
}
mainActionLabel: qsTr('confirmAction')
......@@ -30,6 +28,7 @@ AssistantAbstractView {
Form {
property bool mainActionEnabled: country.currentIndex !== -1 && phoneNumber.text
dealWithErrors: true
orientation: Qt.Vertical
FormLine {
......@@ -62,8 +61,15 @@ AssistantAbstractView {
id: emailAddressForm
Form {
property bool mainActionEnabled: username.length && password.text
property bool mainActionEnabled: username.length &&
password.text &&
!usernameError.length &&
!passwordError.length
property alias usernameError: username.error
property alias passwordError: password.error
dealWithErrors: true
orientation: Qt.Vertical
FormLine {
......@@ -72,6 +78,8 @@ AssistantAbstractView {
TextField {
id: username
onTextChanged: assistantModel.setUsername(text)
}
}
}
......@@ -82,6 +90,8 @@ AssistantAbstractView {
TextField {
id: password
onTextChanged: assistantModel.setPassword(text)
}
}
}
......@@ -92,7 +102,6 @@ AssistantAbstractView {
Column {
anchors.fill: parent
spacing: AssistantUseLinphoneSipAccountStyle.spacing
Loader {
id: loader
......@@ -107,5 +116,28 @@ AssistantAbstractView {
text: qsTr('useUsernameToLogin')
width: AssistantUseLinphoneSipAccountStyle.checkBox.width
}
RequestBlock {
id: requestBlock
action: assistantModel.login
width: parent.width
}
}
// ---------------------------------------------------------------------------
AssistantModel {
id: assistantModel
onUsernameChanged: loader.item.usernameError = error
onPasswordChanged: loader.item.passwordError = error
onLoginStatusChanged: {
requestBlock.stop(error)
if (!error.length) {
window.setView('Home')
}
}
}
}
......@@ -4,8 +4,6 @@ import QtQuick 2.7
// =============================================================================
QtObject {
property int spacing: 20
property QtObject checkBox: QtObject {
property int width: 300
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment