mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-07-01 22:25:26 +02:00
account: implement import-from-device using new API
- Implements new APIs - Implements import-from-device mechanism (creation wizard) - Minor refactoring of accountmodel and accountadapter Gitlab: #1695 Change-Id: Ib3c6301b82b19a25320dd703f2f7e941f8048a8e
This commit is contained in:
parent
82c876c0fa
commit
33da15daba
25 changed files with 820 additions and 347 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,6 +7,7 @@ doc/Doxyfile
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
### VisualStudioCode Patch ###
|
### VisualStudioCode Patch ###
|
||||||
# Ignore all local history of files
|
# Ignore all local history of files
|
||||||
|
|
2
daemon
2
daemon
|
@ -1 +1 @@
|
||||||
Subproject commit 597cde8d30814b5078e2ac8c8a0953dd471ec716
|
Subproject commit 86d3bb664489077107e68b838e419f4cd6459859
|
|
@ -22,8 +22,11 @@
|
||||||
#include "systemtray.h"
|
#include "systemtray.h"
|
||||||
#include "lrcinstance.h"
|
#include "lrcinstance.h"
|
||||||
#include "accountlistmodel.h"
|
#include "accountlistmodel.h"
|
||||||
|
#include "wizardviewstepmodel.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "api/account.h"
|
||||||
|
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QThreadPool>
|
||||||
|
|
||||||
AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
|
AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
|
||||||
SystemTray* systemTray,
|
SystemTray* systemTray,
|
||||||
|
@ -111,7 +114,10 @@ AccountAdapter::createJamiAccount(const QVariantMap& settings)
|
||||||
&lrcInstance_->accountModel(),
|
&lrcInstance_->accountModel(),
|
||||||
&lrc::api::AccountModel::accountAdded,
|
&lrc::api::AccountModel::accountAdded,
|
||||||
[this, registeredName, settings](const QString& accountId) {
|
[this, registeredName, settings](const QString& accountId) {
|
||||||
lrcInstance_->accountModel().setAvatar(accountId, settings["avatar"].toString(), true,1);
|
lrcInstance_->accountModel().setAvatar(accountId,
|
||||||
|
settings["avatar"].toString(),
|
||||||
|
true,
|
||||||
|
1);
|
||||||
Utils::oneShotConnect(&lrcInstance_->accountModel(),
|
Utils::oneShotConnect(&lrcInstance_->accountModel(),
|
||||||
&lrc::api::AccountModel::accountDetailsChanged,
|
&lrc::api::AccountModel::accountDetailsChanged,
|
||||||
[this](const QString& accountId) {
|
[this](const QString& accountId) {
|
||||||
|
@ -159,8 +165,9 @@ AccountAdapter::createJamiAccount(const QVariantMap& settings)
|
||||||
|
|
||||||
connectFailure();
|
connectFailure();
|
||||||
|
|
||||||
auto futureResult = QtConcurrent::run([this, settings] {
|
QThreadPool::globalInstance()->start([this, settings] {
|
||||||
lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::JAMI,
|
lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::JAMI,
|
||||||
|
{},
|
||||||
settings["alias"].toString(),
|
settings["alias"].toString(),
|
||||||
settings["archivePath"].toString(),
|
settings["archivePath"].toString(),
|
||||||
settings["password"].toString(),
|
settings["password"].toString(),
|
||||||
|
@ -206,14 +213,14 @@ AccountAdapter::createSIPAccount(const QVariantMap& settings)
|
||||||
|
|
||||||
connectFailure();
|
connectFailure();
|
||||||
|
|
||||||
auto futureResult = QtConcurrent::run([this, settings] {
|
QThreadPool::globalInstance()->start([this, settings] {
|
||||||
lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::SIP,
|
lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::SIP,
|
||||||
|
{},
|
||||||
settings["alias"].toString(),
|
settings["alias"].toString(),
|
||||||
settings["archivePath"].toString(),
|
settings["archivePath"].toString(),
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
settings["username"].toString(),
|
settings["username"].toString());
|
||||||
{});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +257,7 @@ AccountAdapter::createJAMSAccount(const QVariantMap& settings)
|
||||||
|
|
||||||
connectFailure();
|
connectFailure();
|
||||||
|
|
||||||
auto futureResult = QtConcurrent::run([this, settings] {
|
QThreadPool::globalInstance()->start([this, settings] {
|
||||||
lrcInstance_->accountModel().connectToAccountManager(settings["username"].toString(),
|
lrcInstance_->accountModel().connectToAccountManager(settings["username"].toString(),
|
||||||
settings["password"].toString(),
|
settings["password"].toString(),
|
||||||
settings["manager"].toString());
|
settings["manager"].toString());
|
||||||
|
@ -293,7 +300,7 @@ AccountAdapter::setCurrAccDisplayName(const QString& text)
|
||||||
void
|
void
|
||||||
AccountAdapter::setCurrentAccountAvatarFile(const QString& source)
|
AccountAdapter::setCurrentAccountAvatarFile(const QString& source)
|
||||||
{
|
{
|
||||||
auto futureResult = QtConcurrent::run([this, source]() {
|
QThreadPool::globalInstance()->start([this, source]() {
|
||||||
QPixmap image;
|
QPixmap image;
|
||||||
if (!image.load(source)) {
|
if (!image.load(source)) {
|
||||||
qWarning() << "Not a valid image file";
|
qWarning() << "Not a valid image file";
|
||||||
|
@ -308,7 +315,7 @@ AccountAdapter::setCurrentAccountAvatarFile(const QString& source)
|
||||||
void
|
void
|
||||||
AccountAdapter::setCurrentAccountAvatarBase64(const QString& data)
|
AccountAdapter::setCurrentAccountAvatarBase64(const QString& data)
|
||||||
{
|
{
|
||||||
auto futureResult = QtConcurrent::run([this, data]() {
|
QThreadPool::globalInstance()->start([this, data]() {
|
||||||
auto accountId = lrcInstance_->get_currentAccountId();
|
auto accountId = lrcInstance_->get_currentAccountId();
|
||||||
lrcInstance_->accountModel().setAvatar(accountId, data, true, 1);
|
lrcInstance_->accountModel().setAvatar(accountId, data, true, 1);
|
||||||
});
|
});
|
||||||
|
@ -339,9 +346,73 @@ AccountAdapter::exportToFile(const QString& accountId,
|
||||||
void
|
void
|
||||||
AccountAdapter::setArchivePasswordAsync(const QString& accountID, const QString& password)
|
AccountAdapter::setArchivePasswordAsync(const QString& accountID, const QString& password)
|
||||||
{
|
{
|
||||||
auto futureResult = QtConcurrent::run([this, accountID, password] {
|
QThreadPool::globalInstance()->start([this, accountID, password] {
|
||||||
auto config = lrcInstance_->accountModel().getAccountConfig(accountID);
|
auto config = lrcInstance_->accountModel().getAccountConfig(accountID);
|
||||||
config.archivePassword = password;
|
config.archivePassword = password;
|
||||||
lrcInstance_->accountModel().setAccountConfig(accountID, config);
|
lrcInstance_->accountModel().setAccountConfig(accountID, config);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AccountAdapter::startImportAccount()
|
||||||
|
{
|
||||||
|
auto wizardModel = qApp->property("WizardViewStepModel").value<WizardViewStepModel*>();
|
||||||
|
wizardModel->set_deviceAuthState(lrc::api::account::DeviceAuthState::INIT);
|
||||||
|
wizardModel->set_deviceLinkDetails({});
|
||||||
|
|
||||||
|
// This will create an account with the ARCHIVE_URL configured to start the import process.
|
||||||
|
importAccountId_ = lrcInstance_->accountModel().createDeviceImportAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AccountAdapter::provideAccountAuthentication(const QString& password)
|
||||||
|
{
|
||||||
|
if (importAccountId_.isEmpty()) {
|
||||||
|
qWarning() << "No import account to provide password to";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto wizardModel = qApp->property("WizardViewStepModel").value<WizardViewStepModel*>();
|
||||||
|
wizardModel->set_deviceAuthState(lrc::api::account::DeviceAuthState::IN_PROGRESS);
|
||||||
|
|
||||||
|
Utils::oneShotConnect(
|
||||||
|
&lrcInstance_->accountModel(),
|
||||||
|
&lrc::api::AccountModel::accountAdded,
|
||||||
|
[this](const QString& accountId) {
|
||||||
|
Q_EMIT lrcInstance_->accountListChanged();
|
||||||
|
Q_EMIT accountAdded(accountId,
|
||||||
|
lrcInstance_->accountModel().getAccountList().indexOf(accountId));
|
||||||
|
},
|
||||||
|
this,
|
||||||
|
&AccountAdapter::accountCreationFailed);
|
||||||
|
|
||||||
|
connectFailure();
|
||||||
|
|
||||||
|
QThreadPool::globalInstance()->start([this, password] {
|
||||||
|
lrcInstance_->accountModel().provideAccountAuthentication(importAccountId_, password);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
AccountAdapter::getImportErrorMessage(QVariantMap details)
|
||||||
|
{
|
||||||
|
QString errorString = details.value("error").toString();
|
||||||
|
if (!errorString.isEmpty() && errorString != "none") {
|
||||||
|
auto error = lrc::api::account::mapLinkDeviceError(errorString.toStdString());
|
||||||
|
return lrc::api::account::getLinkDeviceString(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AccountAdapter::cancelImportAccount()
|
||||||
|
{
|
||||||
|
auto wizardModel = qApp->property("WizardViewStepModel").value<WizardViewStepModel*>();
|
||||||
|
wizardModel->set_deviceAuthState(lrc::api::account::DeviceAuthState::INIT);
|
||||||
|
wizardModel->set_deviceLinkDetails({});
|
||||||
|
|
||||||
|
// Remove the account if it was created
|
||||||
|
lrcInstance_->accountModel().removeAccount(importAccountId_);
|
||||||
|
importAccountId_.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -81,6 +81,13 @@ public:
|
||||||
const bool& state);
|
const bool& state);
|
||||||
Q_INVOKABLE QStringList getDefaultModerators(const QString& accountId);
|
Q_INVOKABLE QStringList getDefaultModerators(const QString& accountId);
|
||||||
|
|
||||||
|
// New import account / link device functions
|
||||||
|
// import: (note: Listen for: DeviceAuthStateChanged)
|
||||||
|
Q_INVOKABLE void startImportAccount();
|
||||||
|
Q_INVOKABLE void provideAccountAuthentication(const QString& password = {});
|
||||||
|
Q_INVOKABLE QString getImportErrorMessage(QVariantMap details);
|
||||||
|
Q_INVOKABLE void cancelImportAccount();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
// Trigger other components to reconnect account related signals.
|
// Trigger other components to reconnect account related signals.
|
||||||
void accountStatusChanged(QString accountId);
|
void accountStatusChanged(QString accountId);
|
||||||
|
@ -98,6 +105,9 @@ private:
|
||||||
|
|
||||||
QMetaObject::Connection registeredNameSavedConnection_;
|
QMetaObject::Connection registeredNameSavedConnection_;
|
||||||
|
|
||||||
|
// The account ID of the last used import account.
|
||||||
|
QString importAccountId_;
|
||||||
|
|
||||||
AppSettingsManager* settingsManager_;
|
AppSettingsManager* settingsManager_;
|
||||||
SystemTray* systemTray_;
|
SystemTray* systemTray_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "lrcinstance.h"
|
#include "lrcinstance.h"
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
class AsyncAvatarImageResponseRunnable : public AsyncImageResponseRunnable
|
class AsyncAvatarImageResponseRunnable : public AsyncImageResponseRunnable
|
||||||
{
|
{
|
||||||
|
@ -69,6 +70,16 @@ public:
|
||||||
image = Utils::accountPhoto(lrcInstance_, imageId, requestedSize_);
|
image = Utils::accountPhoto(lrcInstance_, imageId, requestedSize_);
|
||||||
} else if (type == "contact") {
|
} else if (type == "contact") {
|
||||||
image = Utils::contactPhoto(lrcInstance_, imageId, requestedSize_);
|
image = Utils::contactPhoto(lrcInstance_, imageId, requestedSize_);
|
||||||
|
} else if (type == "temporaryAccount") {
|
||||||
|
// Check if imageId is a SHA-1 hash (jamiId or registered name)
|
||||||
|
static const QRegularExpression sha1Pattern("^[0-9a-fA-F]{40}$");
|
||||||
|
if (sha1Pattern.match(imageId).hasMatch()) {
|
||||||
|
// If we only have a jamiId use default avatar
|
||||||
|
image = Utils::fallbackAvatar("jami:" + imageId, QString(), requestedSize_);
|
||||||
|
} else {
|
||||||
|
// For registered usernames, use fallbackAvatar avatar with the name
|
||||||
|
image = Utils::fallbackAvatar(QString(), imageId, requestedSize_);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qWarning() << Q_FUNC_INFO << "Missing valid prefix in the image url";
|
qWarning() << Q_FUNC_INFO << "Missing valid prefix in the image url";
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -28,7 +28,8 @@ Item {
|
||||||
enum Mode {
|
enum Mode {
|
||||||
Account,
|
Account,
|
||||||
Contact,
|
Contact,
|
||||||
Conversation
|
Conversation,
|
||||||
|
TemporaryAccount
|
||||||
}
|
}
|
||||||
property int mode: Avatar.Mode.Account
|
property int mode: Avatar.Mode.Account
|
||||||
property alias sourceSize: image.sourceSize
|
property alias sourceSize: image.sourceSize
|
||||||
|
@ -45,6 +46,8 @@ Item {
|
||||||
return 'contact';
|
return 'contact';
|
||||||
case Avatar.Mode.Conversation:
|
case Avatar.Mode.Conversation:
|
||||||
return 'conversation';
|
return 'conversation';
|
||||||
|
case Avatar.Mode.TemporaryAccount:
|
||||||
|
return 'temporaryAccount';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,21 @@ Item {
|
||||||
property string transferThisCall: qsTr("Transfer this call")
|
property string transferThisCall: qsTr("Transfer this call")
|
||||||
property string transferTo: qsTr("Transfer to")
|
property string transferTo: qsTr("Transfer to")
|
||||||
|
|
||||||
|
// Device import/linking
|
||||||
|
property string scanToImportAccount: qsTr("Scan this QR code on your other device to proceed with importing your account.")
|
||||||
|
property string waitingForToken: qsTr("Please wait…")
|
||||||
|
property string scanQRCode: qsTr("Scan QR code")
|
||||||
|
property string connectingToDevice: qsTr("Action required.\nPlease confirm account on your old device.")
|
||||||
|
property string confirmAccountImport: qsTr("Authenticating device")
|
||||||
|
property string transferringAccount: qsTr("Transferring account…")
|
||||||
|
property string cantScanQRCode: qsTr("If you are unable to scan the QR code, enter this token on your other device to proceed.")
|
||||||
|
property string optionConfirm: qsTr("Confirm")
|
||||||
|
property string optionTryAgain: qsTr("Try again")
|
||||||
|
property string importFailed: qsTr("Import failed")
|
||||||
|
property string importFromAnotherAccount: qsTr("Import from another account")
|
||||||
|
property string connectToAccount: qsTr("Connect to account")
|
||||||
|
property string authenticationError: qsTr("An authentication error occurred. Please check credentials and try again.")
|
||||||
|
|
||||||
// AccountMigrationDialog
|
// AccountMigrationDialog
|
||||||
property string authenticationRequired: qsTr("Authentication required")
|
property string authenticationRequired: qsTr("Authentication required")
|
||||||
property string migrationReason: qsTr("Your session has expired or been revoked on this device. Please enter your password.")
|
property string migrationReason: qsTr("Your session has expired or been revoked on this device. Please enter your password.")
|
||||||
|
@ -579,19 +594,8 @@ Item {
|
||||||
// ImportFromDevicePage
|
// ImportFromDevicePage
|
||||||
property string importButton: qsTr("Import")
|
property string importButton: qsTr("Import")
|
||||||
property string pin: qsTr("Enter the PIN code")
|
property string pin: qsTr("Enter the PIN code")
|
||||||
property string importFromDeviceDescription: qsTr("A PIN code is required to use an existing Jami account on this device.")
|
|
||||||
property string importStep1: qsTr("Step 1")
|
|
||||||
property string importStep2: qsTr("Step 2")
|
|
||||||
property string importStep3: qsTr("Step 3")
|
|
||||||
property string importStep4: qsTr("Step 4")
|
|
||||||
property string importStep1Desc: qsTr("Open the manage account tab in the settings of the previous device.")
|
|
||||||
property string importStep2Desc: qsTr("Select the account to link.")
|
|
||||||
property string importStep3Desc: qsTr("Select “Link new device.”")
|
|
||||||
property string importStep4Desc: qsTr("The PIN code will expire in 10 minutes.")
|
|
||||||
property string importPasswordDesc: qsTr("Fill if the account is password-encrypted.")
|
|
||||||
|
|
||||||
// LinkDevicesDialog
|
// LinkDevicesDialog
|
||||||
property string pinTimerInfos: qsTr("The PIN code and the account password should be entered in the device within 10 minutes.")
|
|
||||||
property string close: qsTr("Close")
|
property string close: qsTr("Close")
|
||||||
property string enterAccountPassword: qsTr("Enter account password")
|
property string enterAccountPassword: qsTr("Enter account password")
|
||||||
property string enterPasswordPinCode: qsTr("This account is password encrypted, enter the password to generate a PIN code.")
|
property string enterPasswordPinCode: qsTr("This account is password encrypted, enter the password to generate a PIN code.")
|
||||||
|
|
|
@ -179,6 +179,12 @@ registerTypes(QQmlEngine* engine,
|
||||||
QQmlEngine::setObjectOwnership(pluginStoreListModel, QQmlEngine::CppOwnership);
|
QQmlEngine::setObjectOwnership(pluginStoreListModel, QQmlEngine::CppOwnership);
|
||||||
REG_QML_SINGLETON<PluginStoreListModel>(REG_MODEL, "PluginStoreListModel", CREATE(pluginStoreListModel));
|
REG_QML_SINGLETON<PluginStoreListModel>(REG_MODEL, "PluginStoreListModel", CREATE(pluginStoreListModel));
|
||||||
|
|
||||||
|
// WizardViewStepModel
|
||||||
|
auto wizardViewStepModel = new WizardViewStepModel(lrcInstance, settingsManager, app);
|
||||||
|
qApp->setProperty("WizardViewStepModel", QVariant::fromValue(wizardViewStepModel));
|
||||||
|
QQmlEngine::setObjectOwnership(wizardViewStepModel, QQmlEngine::CppOwnership);
|
||||||
|
REG_QML_SINGLETON<WizardViewStepModel>(REG_MODEL, "WizardViewStepModel", CREATE(wizardViewStepModel));
|
||||||
|
|
||||||
// Register app-level objects that are used by QML created objects.
|
// Register app-level objects that are used by QML created objects.
|
||||||
// These MUST be set prior to loading the initial QML file, in order to
|
// These MUST be set prior to loading the initial QML file, in order to
|
||||||
// be available to the QML adapter class factory creation methods.
|
// be available to the QML adapter class factory creation methods.
|
||||||
|
@ -205,7 +211,6 @@ registerTypes(QQmlEngine* engine,
|
||||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, TipsModel);
|
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, TipsModel);
|
||||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, VideoDevices);
|
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, VideoDevices);
|
||||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CurrentAccountToMigrate);
|
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CurrentAccountToMigrate);
|
||||||
QML_REGISTERSINGLETON_TYPE(NS_MODELS, WizardViewStepModel);
|
|
||||||
QML_REGISTERSINGLETON_TYPE(NS_HELPERS, ImageDownloader);
|
QML_REGISTERSINGLETON_TYPE(NS_HELPERS, ImageDownloader);
|
||||||
|
|
||||||
// TODO: remove these
|
// TODO: remove these
|
||||||
|
@ -263,12 +268,12 @@ registerTypes(QQmlEngine* engine,
|
||||||
// Enums
|
// Enums
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, Settings)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, Settings)
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, NetworkManager)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, NetworkManager)
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, WizardViewStepModel)
|
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, DeviceItemListModel)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, DeviceItemListModel)
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, ModeratorListModel)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, ModeratorListModel)
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoInputDeviceModel)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoInputDeviceModel)
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatResolutionModel)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatResolutionModel)
|
||||||
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatFpsModel)
|
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatFpsModel)
|
||||||
|
QML_REGISTERUNCREATABLE(NS_ENUMS, DeviceAuthStateEnum)
|
||||||
|
|
||||||
engine->addImageProvider(QLatin1String("qrImage"), new QrImageProvider(lrcInstance));
|
engine->addImageProvider(QLatin1String("qrImage"), new QrImageProvider(lrcInstance));
|
||||||
engine->addImageProvider(QLatin1String("avatarimage"), new AvatarImageProvider(lrcInstance));
|
engine->addImageProvider(QLatin1String("avatarimage"), new AvatarImageProvider(lrcInstance));
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "quickimageproviderbase.h"
|
#include "quickimageproviderbase.h"
|
||||||
#include "accountlistmodel.h"
|
|
||||||
|
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
|
@ -42,7 +42,6 @@ BaseModalDialog {
|
||||||
}
|
}
|
||||||
stackedWidget.currentIndex = exportingSpinnerPage.pageIndex;
|
stackedWidget.currentIndex = exportingSpinnerPage.pageIndex;
|
||||||
spinnerMovie.playing = true;
|
spinnerMovie.playing = true;
|
||||||
timerForExport.restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setExportPage(status, pin) {
|
function setExportPage(status, pin) {
|
||||||
|
@ -69,25 +68,6 @@ BaseModalDialog {
|
||||||
stackedWidget.height = exportingLayout.implicitHeight;
|
stackedWidget.height = exportingLayout.implicitHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: timerForExport
|
|
||||||
|
|
||||||
repeat: false
|
|
||||||
interval: 200
|
|
||||||
|
|
||||||
onTriggered: {
|
|
||||||
AccountAdapter.model.exportOnRing(LRCInstance.currentAccountId, passwordEdit.dynamicText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: NameDirectory
|
|
||||||
|
|
||||||
function onExportOnRingEnded(status, pin) {
|
|
||||||
stackedWidget.setExportPage(status, pin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
if (CurrentAccount.hasArchivePassword) {
|
if (CurrentAccount.hasArchivePassword) {
|
||||||
|
|
|
@ -165,8 +165,7 @@ Utils::CreateStartupLink(const std::wstring& wstrAppName)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (desktopPath.isEmpty() || !(QFile::exists(desktopPath))) {
|
if (desktopPath.isEmpty() || !(QFile::exists(desktopPath))) {
|
||||||
qDebug() << "Error while attempting to locate .desktop file at"
|
qDebug() << "Error while attempting to locate .desktop file at" << desktopPath;
|
||||||
<< desktopPath;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +192,7 @@ Utils::CreateStartupLink(const std::wstring& wstrAppName)
|
||||||
if (QDir().mkdir(autoStartDir)) {
|
if (QDir().mkdir(autoStartDir)) {
|
||||||
qDebug() << "Created autostart directory:" << autoStartDir;
|
qDebug() << "Created autostart directory:" << autoStartDir;
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Error while creating autostart directory:"
|
qWarning() << "Error while creating autostart directory:" << autoStartDir;
|
||||||
<< autoStartDir;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +281,8 @@ Utils::CheckStartupLink(const std::wstring& wstrAppName)
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(wstrAppName)
|
Q_UNUSED(wstrAppName)
|
||||||
return (
|
return (
|
||||||
!QStandardPaths::locate(QStandardPaths::ConfigLocation, "autostart/net.jami.Jami.desktop").isEmpty());
|
!QStandardPaths::locate(QStandardPaths::ConfigLocation, "autostart/net.jami.Jami.desktop")
|
||||||
|
.isEmpty());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,14 +615,16 @@ Utils::getProjectCredits()
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
QTextStream in(&projectCreditsFile);
|
QTextStream in(&projectCreditsFile);
|
||||||
return in.readAll().arg(
|
return in.readAll().arg(QObject::tr("We would like to thank our contributors, whose efforts "
|
||||||
QObject::tr("We would like to thank our contributors, whose efforts over many years have made this software what it is."),
|
"over many years have made this software what it is."),
|
||||||
QObject::tr("Developers"),
|
QObject::tr("Developers"),
|
||||||
QObject::tr("Media"),
|
QObject::tr("Media"),
|
||||||
QObject::tr("Community Management"),
|
QObject::tr("Community Management"),
|
||||||
QObject::tr("Special thanks to"),
|
QObject::tr("Special thanks to"),
|
||||||
QObject::tr("This is a list of people who have made a significant investment of time, with useful results, into Jami. Any such contributors who want to be added to the list should contact us.")
|
QObject::tr(
|
||||||
);
|
"This is a list of people who have made a significant investment "
|
||||||
|
"of time, with useful results, into Jami. Any such contributors "
|
||||||
|
"who want to be added to the list should contact us."));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QString
|
inline QString
|
||||||
|
@ -951,3 +952,13 @@ Utils::getTempSwarmAvatarPath()
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QDir::separator()
|
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QDir::separator()
|
||||||
+ "tmpSwarmImage";
|
+ "tmpSwarmImage";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap
|
||||||
|
Utils::mapStringStringToVariantMap(const MapStringString& map)
|
||||||
|
{
|
||||||
|
QVariantMap variantMap;
|
||||||
|
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
|
||||||
|
variantMap.insert(it.key(), it.value());
|
||||||
|
}
|
||||||
|
return variantMap;
|
||||||
|
}
|
||||||
|
|
|
@ -120,4 +120,7 @@ QString generateUid();
|
||||||
QString humanFileSize(qint64 fileSize);
|
QString humanFileSize(qint64 fileSize);
|
||||||
QString getDebugFilePath();
|
QString getDebugFilePath();
|
||||||
|
|
||||||
|
// Convert a MapStringString to a QVariantMap
|
||||||
|
QVariantMap mapStringStringToVariantMap(const MapStringString& map);
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
|
|
@ -56,9 +56,11 @@ BaseView {
|
||||||
case WizardViewStepModel.AccountCreationOption.CreateJamiAccount:
|
case WizardViewStepModel.AccountCreationOption.CreateJamiAccount:
|
||||||
case WizardViewStepModel.AccountCreationOption.CreateRendezVous:
|
case WizardViewStepModel.AccountCreationOption.CreateRendezVous:
|
||||||
case WizardViewStepModel.AccountCreationOption.ImportFromBackup:
|
case WizardViewStepModel.AccountCreationOption.ImportFromBackup:
|
||||||
case WizardViewStepModel.AccountCreationOption.ImportFromDevice:
|
|
||||||
AccountAdapter.createJamiAccount(WizardViewStepModel.accountCreationInfo);
|
AccountAdapter.createJamiAccount(WizardViewStepModel.accountCreationInfo);
|
||||||
break;
|
break;
|
||||||
|
case WizardViewStepModel.AccountCreationOption.ImportFromDevice:
|
||||||
|
AccountAdapter.startImportAccount();
|
||||||
|
break;
|
||||||
case WizardViewStepModel.AccountCreationOption.ConnectToAccountManager:
|
case WizardViewStepModel.AccountCreationOption.ConnectToAccountManager:
|
||||||
AccountAdapter.createJAMSAccount(WizardViewStepModel.accountCreationInfo);
|
AccountAdapter.createJAMSAccount(WizardViewStepModel.accountCreationInfo);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,9 +17,13 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Dialogs
|
||||||
|
import net.jami.Adapters 1.1
|
||||||
import net.jami.Models 1.1
|
import net.jami.Models 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
import net.jami.Enums 1.1
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
import "../../mainview/components"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
@ -27,30 +31,99 @@ Rectangle {
|
||||||
property string errorText: ""
|
property string errorText: ""
|
||||||
property int preferredHeight: importFromDevicePageColumnLayout.implicitHeight + 2 * JamiTheme.preferredMarginSize
|
property int preferredHeight: importFromDevicePageColumnLayout.implicitHeight + 2 * JamiTheme.preferredMarginSize
|
||||||
|
|
||||||
signal showThisPage
|
// The token is used to generate the QR code and is also provided to the user as a backup if the QR
|
||||||
|
// code cannot be scanned. It is a URI using the scheme "jami-auth".
|
||||||
|
readonly property string tokenUri: WizardViewStepModel.deviceLinkDetails["token"] || ""
|
||||||
|
|
||||||
function initializeOnShowUp() {
|
property string jamiId: ""
|
||||||
clearAllTextFields();
|
|
||||||
|
function isPasswordWrong() {
|
||||||
|
return WizardViewStepModel.deviceLinkDetails["auth_error"] !== undefined &&
|
||||||
|
WizardViewStepModel.deviceLinkDetails["auth_error"] !== "" &&
|
||||||
|
WizardViewStepModel.deviceLinkDetails["auth_error"] !== "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function requiresPassword() {
|
||||||
|
return WizardViewStepModel.deviceLinkDetails["auth_scheme"] === "password"
|
||||||
|
}
|
||||||
|
|
||||||
|
function requiresConfirmationBeforeClosing() {
|
||||||
|
const state = WizardViewStepModel.deviceAuthState
|
||||||
|
return state !== DeviceAuthStateEnum.INIT &&
|
||||||
|
state !== DeviceAuthStateEnum.DONE
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLoadingState() {
|
||||||
|
const state = WizardViewStepModel.deviceAuthState
|
||||||
|
return state === DeviceAuthStateEnum.INIT ||
|
||||||
|
state === DeviceAuthStateEnum.CONNECTING ||
|
||||||
|
state === DeviceAuthStateEnum.IN_PROGRESS
|
||||||
|
}
|
||||||
|
|
||||||
|
signal showThisPage
|
||||||
|
|
||||||
function clearAllTextFields() {
|
function clearAllTextFields() {
|
||||||
connectBtn.spinnerTriggered = false;
|
errorText = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorOccurred(errorMessage) {
|
function errorOccurred(errorMessage) {
|
||||||
errorText = errorMessage;
|
errorText = errorMessage;
|
||||||
connectBtn.spinnerTriggered = false;
|
}
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: confirmCloseDialog
|
||||||
|
|
||||||
|
text: JamiStrings.linkDeviceCloseWarningTitle
|
||||||
|
informativeText: JamiStrings.linkDeviceCloseWarningMessage
|
||||||
|
buttons: MessageDialog.Ok | MessageDialog.Cancel
|
||||||
|
|
||||||
|
onButtonClicked: function(button) {
|
||||||
|
if (button === MessageDialog.Ok) {
|
||||||
|
AccountAdapter.cancelImportAccount();
|
||||||
|
WizardViewStepModel.previousStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: WizardViewStepModel
|
target: WizardViewStepModel
|
||||||
|
|
||||||
function onMainStepChanged() {
|
function onMainStepChanged() {
|
||||||
if (WizardViewStepModel.mainStep === WizardViewStepModel.MainSteps.AccountCreation && WizardViewStepModel.accountCreationOption === WizardViewStepModel.AccountCreationOption.ImportFromDevice) {
|
if (WizardViewStepModel.mainStep === WizardViewStepModel.MainSteps.DeviceAuthorization) {
|
||||||
clearAllTextFields();
|
clearAllTextFields();
|
||||||
root.showThisPage();
|
root.showThisPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDeviceAuthStateChanged() {
|
||||||
|
switch (WizardViewStepModel.deviceAuthState) {
|
||||||
|
case DeviceAuthStateEnum.TOKEN_AVAILABLE:
|
||||||
|
// Token is available and displayed as QR code
|
||||||
|
clearAllTextFields();
|
||||||
|
break;
|
||||||
|
case DeviceAuthStateEnum.CONNECTING:
|
||||||
|
// P2P connection being established
|
||||||
|
clearAllTextFields();
|
||||||
|
break;
|
||||||
|
case DeviceAuthStateEnum.AUTHENTICATING:
|
||||||
|
jamiId = WizardViewStepModel.deviceLinkDetails["peer_id"] || "";
|
||||||
|
if (jamiId.length > 0) {
|
||||||
|
NameDirectory.lookupAddress(CurrentAccount.id, jamiId)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DeviceAuthStateEnum.IN_PROGRESS:
|
||||||
|
// Account archive is being transferred
|
||||||
|
clearAllTextFields();
|
||||||
|
break;
|
||||||
|
case DeviceAuthStateEnum.DONE:
|
||||||
|
// Final state - check for specific errors
|
||||||
|
const error = AccountAdapter.getImportErrorMessage(WizardViewStepModel.deviceLinkDetails);
|
||||||
|
if (error.length > 0) {
|
||||||
|
errorOccurred(error)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
color: JamiTheme.secondaryBackgroundColor
|
color: JamiTheme.secondaryBackgroundColor
|
||||||
|
@ -65,184 +138,276 @@ Rectangle {
|
||||||
width: Math.max(508, root.width - 100)
|
width: Math.max(508, root.width - 100)
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
text: JamiStrings.importFromAnotherAccount
|
||||||
text: JamiStrings.importAccountFromAnotherDevice
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
Layout.topMargin: JamiTheme.preferredMarginSize
|
Layout.topMargin: JamiTheme.preferredMarginSize
|
||||||
Layout.preferredWidth: Math.min(360, root.width - JamiTheme.preferredMarginSize * 2)
|
Layout.preferredWidth: Math.min(360, root.width - JamiTheme.preferredMarginSize * 2)
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
color: JamiTheme.textColor
|
|
||||||
|
|
||||||
|
color: JamiTheme.textColor
|
||||||
font.pixelSize: JamiTheme.wizardViewTitleFontPixelSize
|
font.pixelSize: JamiTheme.wizardViewTitleFontPixelSize
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
|
||||||
text: JamiStrings.importFromDeviceDescription
|
|
||||||
Layout.preferredWidth: Math.min(360, root.width - JamiTheme.preferredMarginSize * 2)
|
|
||||||
Layout.topMargin: JamiTheme.wizardViewDescriptionMarginSize
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
|
||||||
font.pixelSize: JamiTheme.wizardViewDescriptionFontPixelSize
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: JamiTheme.textColor
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
lineHeight: JamiTheme.wizardViewTextLineHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
Flow {
|
|
||||||
spacing: 30
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.topMargin: JamiTheme.wizardViewBlocMarginSize
|
Layout.maximumWidth: parent.width
|
||||||
Layout.preferredWidth: Math.min(step1.width * 2 + spacing, root.width - JamiTheme.preferredMarginSize * 2)
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: JamiTheme.wizardViewDescriptionFontPixelSize
|
||||||
InfoBox {
|
lineHeight: JamiTheme.wizardViewTextLineHeight
|
||||||
id: step1
|
text: {
|
||||||
icoSource: JamiResources.settings_24dp_svg
|
switch (WizardViewStepModel.deviceAuthState) {
|
||||||
title: JamiStrings.importStep1
|
case DeviceAuthStateEnum.INIT:
|
||||||
description: JamiStrings.importStep1Desc
|
return JamiStrings.waitingForToken;
|
||||||
icoColor: JamiTheme.buttonTintedBlue
|
case DeviceAuthStateEnum.TOKEN_AVAILABLE:
|
||||||
|
return JamiStrings.scanToImportAccount;
|
||||||
|
case DeviceAuthStateEnum.CONNECTING:
|
||||||
|
return JamiStrings.connectingToDevice;
|
||||||
|
case DeviceAuthStateEnum.AUTHENTICATING:
|
||||||
|
return JamiStrings.confirmAccountImport;
|
||||||
|
case DeviceAuthStateEnum.IN_PROGRESS:
|
||||||
|
return JamiStrings.transferringAccount;
|
||||||
|
case DeviceAuthStateEnum.DONE:
|
||||||
|
return errorText.length > 0 ? JamiStrings.importFailed : "";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
color: JamiTheme.textColor
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoBox {
|
// Confirmation form
|
||||||
id: step2
|
ColumnLayout {
|
||||||
icoSource: JamiResources.person_24dp_svg
|
Layout.alignment: Qt.AlignHCenter
|
||||||
title: JamiStrings.importStep2
|
Layout.maximumWidth: Math.min(parent.width - 40, 400)
|
||||||
description: JamiStrings.importStep2Desc
|
visible: WizardViewStepModel.deviceAuthState === DeviceAuthStateEnum.AUTHENTICATING
|
||||||
icoColor: JamiTheme.buttonTintedBlue
|
spacing: JamiTheme.wizardViewPageLayoutSpacing
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: JamiTheme.wizardViewDescriptionFontPixelSize
|
||||||
|
lineHeight: JamiTheme.wizardViewTextLineHeight
|
||||||
|
text: JamiStrings.connectToAccount
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoBox {
|
// Account Widget (avatar + username + ID)
|
||||||
id: step3
|
Rectangle {
|
||||||
icoSource: JamiResources.finger_select_svg
|
id: accountContainer
|
||||||
title: JamiStrings.importStep3
|
Layout.alignment: Qt.AlignHCenter
|
||||||
description: JamiStrings.importStep3Desc
|
implicitWidth: accountLayout.implicitWidth + 40
|
||||||
icoColor: JamiTheme.buttonTintedBlue
|
implicitHeight: accountLayout.implicitHeight + 40
|
||||||
|
radius: 8
|
||||||
|
color: JamiTheme.primaryBackgroundColor
|
||||||
|
border.width: 1
|
||||||
|
border.color: JamiTheme.tabbarBorderColor
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: accountLayout
|
||||||
|
anchors {
|
||||||
|
centerIn: parent
|
||||||
|
}
|
||||||
|
spacing: 20
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
id: accountAvatar
|
||||||
|
showPresenceIndicator: false
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.preferredWidth: 48
|
||||||
|
Layout.preferredHeight: 48
|
||||||
|
mode: Avatar.Mode.TemporaryAccount
|
||||||
|
imageId: name.text || jamiId
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoBox {
|
ColumnLayout {
|
||||||
id: step4
|
Layout.fillWidth: true
|
||||||
icoSource: JamiResources.time_clock_svg
|
Layout.fillHeight: true
|
||||||
title: JamiStrings.importStep4
|
Layout.alignment: Qt.AlignVCenter
|
||||||
description: JamiStrings.importStep4Desc
|
spacing: 4
|
||||||
icoColor: JamiTheme.buttonTintedBlue
|
|
||||||
|
Text {
|
||||||
|
id: name
|
||||||
|
visible: text !== undefined && text !== ""
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
id: registeredNameFoundConnection
|
||||||
|
target: NameDirectory
|
||||||
|
enabled: jamiId.length > 0
|
||||||
|
|
||||||
|
function onRegisteredNameFound(status, address, registeredName, requestedName) {
|
||||||
|
if (address === jamiId && status === NameDirectory.LookupStatus.SUCCESS) {
|
||||||
|
name.text = registeredName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: userId
|
||||||
|
text: jamiId
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModalTextEdit {
|
// Password
|
||||||
id: pinFromDevice
|
PasswordTextEdit {
|
||||||
|
id: passwordField
|
||||||
|
|
||||||
objectName: "pinFromDevice"
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
Layout.rightMargin: 10
|
||||||
|
Layout.topMargin: 10
|
||||||
|
Layout.bottomMargin: 10
|
||||||
|
visible: requiresPassword()
|
||||||
|
placeholderText: JamiStrings.enterPassword
|
||||||
|
echoMode: TextInput.Password
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
onAccepted: confirmButton.clicked()
|
||||||
Layout.preferredWidth: Math.min(410, root.width - JamiTheme.preferredMarginSize * 2)
|
|
||||||
Layout.topMargin: JamiTheme.wizardViewBlocMarginSize
|
|
||||||
|
|
||||||
focus: visible
|
|
||||||
|
|
||||||
placeholderText: JamiStrings.pin
|
|
||||||
staticText: ""
|
|
||||||
|
|
||||||
KeyNavigation.up: backButton
|
|
||||||
KeyNavigation.down: passwordFromDevice
|
|
||||||
KeyNavigation.tab: KeyNavigation.down
|
|
||||||
|
|
||||||
onAccepted: passwordFromDevice.forceActiveFocus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
id: passwordErrorField
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.topMargin: JamiTheme.wizardViewBlocMarginSize
|
Layout.maximumWidth: parent.width - 40
|
||||||
|
visible: isPasswordWrong()
|
||||||
color: JamiTheme.textColor
|
text: JamiStrings.authenticationError
|
||||||
wrapMode: Text.WordWrap
|
font.pointSize: JamiTheme.tinyFontSize
|
||||||
text: JamiStrings.importPasswordDesc
|
|
||||||
font.pixelSize: JamiTheme.wizardViewDescriptionFontPixelSize
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
PasswordTextEdit {
|
|
||||||
id: passwordFromDevice
|
|
||||||
|
|
||||||
objectName: "passwordFromDevice"
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
|
||||||
Layout.preferredWidth: Math.min(410, root.width - JamiTheme.preferredMarginSize * 2)
|
|
||||||
Layout.topMargin: JamiTheme.wizardViewMarginSize
|
|
||||||
|
|
||||||
placeholderText: JamiStrings.enterPassword
|
|
||||||
|
|
||||||
KeyNavigation.up: pinFromDevice
|
|
||||||
KeyNavigation.down: {
|
|
||||||
if (connectBtn.enabled)
|
|
||||||
return connectBtn;
|
|
||||||
else if (connectBtn.spinnerTriggered)
|
|
||||||
return passwordFromDevice;
|
|
||||||
return backButton;
|
|
||||||
}
|
|
||||||
KeyNavigation.tab: KeyNavigation.down
|
|
||||||
|
|
||||||
onAccepted: pinFromDevice.forceActiveFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
SpinnerButton {
|
|
||||||
id: connectBtn
|
|
||||||
|
|
||||||
TextMetrics {
|
|
||||||
id: textSize
|
|
||||||
font.weight: Font.Bold
|
|
||||||
font.pixelSize: JamiTheme.wizardViewButtonFontPixelSize
|
|
||||||
text: connectBtn.normalText
|
|
||||||
}
|
|
||||||
|
|
||||||
objectName: "importFromDevicePageConnectBtn"
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
|
||||||
Layout.topMargin: JamiTheme.wizardViewBlocMarginSize
|
|
||||||
Layout.bottomMargin: errorLabel.visible ? 0 : JamiTheme.wizardViewPageBackButtonMargins
|
|
||||||
|
|
||||||
preferredWidth: textSize.width + 2 * JamiTheme.buttontextWizzardPadding + 1
|
|
||||||
primary: true
|
|
||||||
|
|
||||||
spinnerTriggeredtext: JamiStrings.generatingAccount
|
|
||||||
normalText: JamiStrings.importButton
|
|
||||||
|
|
||||||
enabled: pinFromDevice.dynamicText.length !== 0 && !spinnerTriggered
|
|
||||||
|
|
||||||
KeyNavigation.tab: backButton
|
|
||||||
KeyNavigation.up: passwordFromDevice
|
|
||||||
KeyNavigation.down: backButton
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
spinnerTriggered = true;
|
|
||||||
WizardViewStepModel.accountCreationInfo = JamiQmlUtils.setUpAccountCreationInputPara({
|
|
||||||
"archivePin": pinFromDevice.dynamicText,
|
|
||||||
"password": passwordFromDevice.dynamicText
|
|
||||||
});
|
|
||||||
WizardViewStepModel.nextStep();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: errorLabel
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
|
||||||
Layout.bottomMargin: JamiTheme.wizardViewPageBackButtonMargins
|
|
||||||
|
|
||||||
visible: errorText.length !== 0
|
|
||||||
|
|
||||||
text: errorText
|
|
||||||
|
|
||||||
font.pixelSize: JamiTheme.textEditError
|
|
||||||
color: JamiTheme.redColor
|
color: JamiTheme.redColor
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
spacing: 16
|
||||||
|
Layout.margins: 10
|
||||||
|
|
||||||
|
MaterialButton {
|
||||||
|
id: confirmButton
|
||||||
|
text: JamiStrings.optionConfirm
|
||||||
|
primary: true
|
||||||
|
enabled: !passwordField.visible || passwordField.dynamicText.length > 0
|
||||||
|
onClicked: {
|
||||||
|
AccountAdapter.provideAccountAuthentication(passwordField.visible ? passwordField.dynamicText : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BackButton {
|
// Show busy indicator when waiting for token
|
||||||
|
BusyIndicator {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
visible: isLoadingState()
|
||||||
|
Layout.preferredWidth: 50
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
running: visible
|
||||||
|
}
|
||||||
|
|
||||||
|
// QR Code container with frame
|
||||||
|
Rectangle {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.preferredWidth: qrLoader.Layout.preferredWidth + 40
|
||||||
|
Layout.preferredHeight: qrLoader.Layout.preferredHeight + 40
|
||||||
|
visible: WizardViewStepModel.deviceAuthState === DeviceAuthStateEnum.TOKEN_AVAILABLE
|
||||||
|
color: JamiTheme.primaryBackgroundColor
|
||||||
|
radius: 8
|
||||||
|
border.width: 1
|
||||||
|
border.color: JamiTheme.tabbarBorderColor
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: qrLoader
|
||||||
|
anchors.centerIn: parent
|
||||||
|
active: WizardViewStepModel.deviceAuthState === DeviceAuthStateEnum.TOKEN_AVAILABLE
|
||||||
|
Layout.preferredWidth: Math.min(parent.parent.width - 60, 250)
|
||||||
|
Layout.preferredHeight: Layout.preferredWidth
|
||||||
|
|
||||||
|
sourceComponent: Image {
|
||||||
|
width: qrLoader.Layout.preferredWidth
|
||||||
|
height: qrLoader.Layout.preferredHeight
|
||||||
|
smooth: false
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: "image://qrImage/raw_" + tokenUri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token URI backup text
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
visible: tokenUri !== ""
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: parent.parent.width - 40
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: JamiStrings.cantScanQRCode
|
||||||
|
font.pixelSize: JamiTheme.wizardViewDescriptionFontPixelSize
|
||||||
|
lineHeight: JamiTheme.wizardViewTextLineHeight
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: tokenUriTextArea
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: parent.parent.width - 40
|
||||||
|
text: tokenUri
|
||||||
|
font.pointSize: JamiTheme.wizardViewDescriptionFontPixelSize
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
readOnly: true
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
selectByMouse: true
|
||||||
|
background: Rectangle {
|
||||||
|
color: JamiTheme.primaryBackgroundColor
|
||||||
|
radius: 5
|
||||||
|
border.width: 1
|
||||||
|
border.color: JamiTheme.tabbarBorderColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error view
|
||||||
|
ColumnLayout {
|
||||||
|
id: errorColumn
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: parent.width - 40
|
||||||
|
visible: errorText !== ""
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
text: errorText
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
font.pointSize: JamiTheme.mediumFontSize
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialButton {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: JamiStrings.optionTryAgain
|
||||||
|
toolTipText: JamiStrings.optionTryAgain
|
||||||
|
primary: true
|
||||||
|
onClicked: {
|
||||||
|
AccountAdapter.cancelImportAccount();
|
||||||
|
WizardViewStepModel.previousStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back button
|
||||||
|
JamiPushButton {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
QWKSetParentHitTestVisible {
|
||||||
|
}
|
||||||
|
|
||||||
objectName: "importFromDevicePageBackButton"
|
objectName: "importFromDevicePageBackButton"
|
||||||
|
|
||||||
|
@ -250,12 +415,18 @@ Rectangle {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.margins: JamiTheme.wizardViewPageBackButtonMargins
|
anchors.margins: JamiTheme.wizardViewPageBackButtonMargins
|
||||||
|
|
||||||
visible: !connectBtn.spinnerTriggered
|
preferredSize: 36
|
||||||
|
imageContainerWidth: 20
|
||||||
|
source: JamiResources.ic_arrow_back_24dp_svg
|
||||||
|
|
||||||
KeyNavigation.tab: pinFromDevice
|
visible: WizardViewStepModel.deviceAuthState !== DeviceAuthStateEnum.IN_PROGRESS
|
||||||
KeyNavigation.up: connectBtn.enabled ? connectBtn : passwordFromDevice
|
|
||||||
KeyNavigation.down: pinFromDevice
|
|
||||||
|
|
||||||
onClicked: WizardViewStepModel.previousStep()
|
onClicked: {
|
||||||
|
if (requiresConfirmationBeforeClosing()) {
|
||||||
|
confirmCloseDialog.open();
|
||||||
|
} else {
|
||||||
|
WizardViewStepModel.previousStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "appsettingsmanager.h"
|
#include "appsettingsmanager.h"
|
||||||
#include "lrcinstance.h"
|
#include "lrcinstance.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
#include "api/accountmodel.h"
|
#include "api/accountmodel.h"
|
||||||
|
|
||||||
|
@ -46,17 +47,31 @@ WizardViewStepModel::WizardViewStepModel(LRCInstance* lrcInstance,
|
||||||
|
|
||||||
Q_EMIT accountIsReady(accountId);
|
Q_EMIT accountIsReady(accountId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Connect to account model signals to track import progress
|
||||||
|
connect(&lrcInstance_->accountModel(),
|
||||||
|
&AccountModel::deviceAuthStateChanged,
|
||||||
|
this,
|
||||||
|
[this](const QString& accountID, int state, const MapStringString& details) {
|
||||||
|
set_deviceLinkDetails(Utils::mapStringStringToVariantMap(details));
|
||||||
|
set_deviceAuthState(static_cast<lrc::api::account::DeviceAuthState>(state));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WizardViewStepModel::startAccountCreationFlow(AccountCreationOption accountCreationOption)
|
WizardViewStepModel::startAccountCreationFlow(AccountCreationOption accountCreationOption)
|
||||||
{
|
{
|
||||||
|
using namespace lrc::api::account;
|
||||||
set_accountCreationOption(accountCreationOption);
|
set_accountCreationOption(accountCreationOption);
|
||||||
if (accountCreationOption == AccountCreationOption::CreateJamiAccount
|
if (accountCreationOption == AccountCreationOption::ImportFromDevice) {
|
||||||
|| accountCreationOption == AccountCreationOption::CreateRendezVous)
|
set_mainStep(MainSteps::DeviceAuthorization);
|
||||||
|
Q_EMIT createAccountRequested(accountCreationOption);
|
||||||
|
} else if (accountCreationOption == AccountCreationOption::CreateJamiAccount
|
||||||
|
|| accountCreationOption == AccountCreationOption::CreateRendezVous) {
|
||||||
set_mainStep(MainSteps::NameRegistration);
|
set_mainStep(MainSteps::NameRegistration);
|
||||||
else
|
} else {
|
||||||
set_mainStep(MainSteps::AccountCreation);
|
set_mainStep(MainSteps::AccountCreation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -80,6 +95,10 @@ WizardViewStepModel::previousStep()
|
||||||
reset();
|
reset();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MainSteps::DeviceAuthorization: {
|
||||||
|
reset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,4 +107,6 @@ WizardViewStepModel::reset()
|
||||||
{
|
{
|
||||||
set_accountCreationOption(AccountCreationOption::None);
|
set_accountCreationOption(AccountCreationOption::None);
|
||||||
set_mainStep(MainSteps::Initial);
|
set_mainStep(MainSteps::Initial);
|
||||||
|
set_deviceAuthState(lrc::api::account::DeviceAuthState::INIT);
|
||||||
|
set_deviceLinkDetails({});
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
|
#include "api/account.h" // Include for DeviceAuthState
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
@ -29,6 +30,21 @@ class AccountAdapter;
|
||||||
class LRCInstance;
|
class LRCInstance;
|
||||||
class AppSettingsManager;
|
class AppSettingsManager;
|
||||||
|
|
||||||
|
class DeviceAuthStateEnum : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
INIT = static_cast<int>(lrc::api::account::DeviceAuthState::INIT),
|
||||||
|
TOKEN_AVAILABLE = static_cast<int>(lrc::api::account::DeviceAuthState::TOKEN_AVAILABLE),
|
||||||
|
CONNECTING = static_cast<int>(lrc::api::account::DeviceAuthState::CONNECTING),
|
||||||
|
AUTHENTICATING = static_cast<int>(lrc::api::account::DeviceAuthState::AUTHENTICATING),
|
||||||
|
IN_PROGRESS = static_cast<int>(lrc::api::account::DeviceAuthState::IN_PROGRESS),
|
||||||
|
DONE = static_cast<int>(lrc::api::account::DeviceAuthState::DONE)
|
||||||
|
};
|
||||||
|
Q_ENUM(State)
|
||||||
|
};
|
||||||
|
|
||||||
class WizardViewStepModel : public QObject
|
class WizardViewStepModel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -40,6 +56,7 @@ public:
|
||||||
Initial, // Initial welcome step.
|
Initial, // Initial welcome step.
|
||||||
AccountCreation, // General account creation step.
|
AccountCreation, // General account creation step.
|
||||||
NameRegistration, // Name registration step : CreateJamiAccount, CreateRendezVous
|
NameRegistration, // Name registration step : CreateJamiAccount, CreateRendezVous
|
||||||
|
DeviceAuthorization // Add new step for device authorization.
|
||||||
};
|
};
|
||||||
Q_ENUM(MainSteps)
|
Q_ENUM(MainSteps)
|
||||||
|
|
||||||
|
@ -57,6 +74,8 @@ public:
|
||||||
QML_PROPERTY(MainSteps, mainStep)
|
QML_PROPERTY(MainSteps, mainStep)
|
||||||
QML_PROPERTY(AccountCreationOption, accountCreationOption)
|
QML_PROPERTY(AccountCreationOption, accountCreationOption)
|
||||||
QML_PROPERTY(QVariantMap, accountCreationInfo)
|
QML_PROPERTY(QVariantMap, accountCreationInfo)
|
||||||
|
QML_PROPERTY(lrc::api::account::DeviceAuthState, deviceAuthState)
|
||||||
|
QML_PROPERTY(QVariantMap, deviceLinkDetails)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static WizardViewStepModel* create(QQmlEngine*, QJSEngine*)
|
static WizardViewStepModel* create(QQmlEngine*, QJSEngine*)
|
||||||
|
|
|
@ -117,12 +117,14 @@ public Q_SLOTS:
|
||||||
void slotAccountStatusChanged(const QString& accountID, const api::account::Status status);
|
void slotAccountStatusChanged(const QString& accountID, const api::account::Status status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit exportOnRingEnded.
|
* Emit deviceAuthStateChanged.
|
||||||
* @param accountId
|
* @param accountId
|
||||||
* @param status
|
* @param state
|
||||||
* @param pin
|
* @param details map
|
||||||
*/
|
*/
|
||||||
void slotExportOnRingEnded(const QString& accountID, int status, const QString& pin);
|
void slotDeviceAuthStateChanged(const QString& accountID,
|
||||||
|
int state,
|
||||||
|
const MapStringString& details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param accountId
|
* @param accountId
|
||||||
|
@ -282,11 +284,12 @@ AccountModel::setAlias(const QString& accountId, const QString& alias, bool save
|
||||||
accountInfo.profileInfo.alias = alias;
|
accountInfo.profileInfo.alias = alias;
|
||||||
|
|
||||||
if (save)
|
if (save)
|
||||||
ConfigurationManager::instance().updateProfile(accountId,
|
ConfigurationManager::instance()
|
||||||
|
.updateProfile(accountId,
|
||||||
alias,
|
alias,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
5);// flag out of range to avoid updating avatar
|
5); // flag out of range to avoid updating avatar
|
||||||
Q_EMIT profileUpdated(accountId);
|
Q_EMIT profileUpdated(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,9 +326,30 @@ AccountModel::exportToFile(const QString& accountId,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AccountModel::exportOnRing(const QString& accountId, const QString& password) const
|
AccountModel::provideAccountAuthentication(const QString& accountId,
|
||||||
|
const QString& credentialsFromUser) const
|
||||||
{
|
{
|
||||||
return ConfigurationManager::instance().exportOnRing(accountId, password);
|
return ConfigurationManager::instance().provideAccountAuthentication(accountId,
|
||||||
|
credentialsFromUser,
|
||||||
|
"password");
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
AccountModel::addDevice(const QString& accountId, const QString& token) const
|
||||||
|
{
|
||||||
|
return ConfigurationManager::instance().addDevice(accountId, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AccountModel::confirmAddDevice(const QString& accountId, uint32_t operationId) const
|
||||||
|
{
|
||||||
|
return ConfigurationManager::instance().confirmAddDevice(accountId, operationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AccountModel::cancelAddDevice(const QString& accountId, uint32_t operationId) const
|
||||||
|
{
|
||||||
|
return ConfigurationManager::instance().cancelAddDevice(accountId, operationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -403,9 +427,9 @@ AccountModelPimpl::AccountModelPimpl(AccountModel& linked,
|
||||||
this,
|
this,
|
||||||
&AccountModelPimpl::slotVolatileAccountDetailsChanged);
|
&AccountModelPimpl::slotVolatileAccountDetailsChanged);
|
||||||
connect(&callbacksHandler,
|
connect(&callbacksHandler,
|
||||||
&CallbacksHandler::exportOnRingEnded,
|
&CallbacksHandler::deviceAuthStateChanged,
|
||||||
this,
|
&linked,
|
||||||
&AccountModelPimpl::slotExportOnRingEnded);
|
&AccountModel::deviceAuthStateChanged);
|
||||||
connect(&callbacksHandler,
|
connect(&callbacksHandler,
|
||||||
&CallbacksHandler::nameRegistrationEnded,
|
&CallbacksHandler::nameRegistrationEnded,
|
||||||
this,
|
this,
|
||||||
|
@ -594,23 +618,13 @@ AccountModelPimpl::slotVolatileAccountDetailsChanged(const QString& accountId,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AccountModelPimpl::slotExportOnRingEnded(const QString& accountID, int status, const QString& pin)
|
AccountModelPimpl::slotDeviceAuthStateChanged(const QString& accountId,
|
||||||
|
int state,
|
||||||
|
const MapStringString& details)
|
||||||
{
|
{
|
||||||
account::ExportOnRingStatus convertedStatus = account::ExportOnRingStatus::INVALID;
|
// implement business logic here
|
||||||
switch (status) {
|
// can be bypassed with a signal to signal
|
||||||
case 0:
|
Q_EMIT linked.deviceAuthStateChanged(accountId, state, details);
|
||||||
convertedStatus = account::ExportOnRingStatus::SUCCESS;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
convertedStatus = account::ExportOnRingStatus::WRONG_PASSWORD;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
convertedStatus = account::ExportOnRingStatus::NETWORK_ERROR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Q_EMIT linked.exportOnRingEnded(accountID, convertedStatus, pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -673,7 +687,11 @@ AccountModelPimpl::slotRegisteredNameFound(const QString& accountId,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Q_EMIT linked.registeredNameFound(accountId, requestedName, convertedStatus, address, registeredName);
|
Q_EMIT linked.registeredNameFound(accountId,
|
||||||
|
requestedName,
|
||||||
|
convertedStatus,
|
||||||
|
address,
|
||||||
|
registeredName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1041,17 +1059,32 @@ account::ConfProperties_t::toDetails() const
|
||||||
|
|
||||||
QString
|
QString
|
||||||
AccountModel::createNewAccount(profile::Type type,
|
AccountModel::createNewAccount(profile::Type type,
|
||||||
|
const MapStringString& config,
|
||||||
const QString& displayName,
|
const QString& displayName,
|
||||||
const QString& archivePath,
|
const QString& archivePath,
|
||||||
const QString& password,
|
const QString& password,
|
||||||
const QString& pin,
|
const QString& pin,
|
||||||
const QString& uri,
|
const QString& uri)
|
||||||
const MapStringString& config)
|
|
||||||
{
|
{
|
||||||
|
// Get the template for the account type to prefill the details
|
||||||
MapStringString details = type == profile::Type::SIP
|
MapStringString details = type == profile::Type::SIP
|
||||||
? ConfigurationManager::instance().getAccountTemplate("SIP")
|
? ConfigurationManager::instance().getAccountTemplate("SIP")
|
||||||
: ConfigurationManager::instance().getAccountTemplate("RING");
|
: ConfigurationManager::instance().getAccountTemplate("RING");
|
||||||
|
|
||||||
|
// Add the supplied config to the details
|
||||||
|
if (!config.isEmpty()) {
|
||||||
|
for (MapStringString::const_iterator it = config.begin(); it != config.end(); it++) {
|
||||||
|
details[it.key()] = it.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using namespace libjami::Account;
|
using namespace libjami::Account;
|
||||||
|
|
||||||
|
// Add the rest of the details if we are not creating an ephemeral account for linking
|
||||||
|
// in which case the ARCHIVE_URL was set to "jami-auth" or the MANAGER_URI was set to
|
||||||
|
// the account manager URI in the case of a remote account manager connection
|
||||||
|
if (details[ConfProperties::ARCHIVE_URL].isEmpty()
|
||||||
|
&& details[ConfProperties::MANAGER_URI].isEmpty()) {
|
||||||
details[ConfProperties::TYPE] = type == profile::Type::SIP ? "SIP" : "RING";
|
details[ConfProperties::TYPE] = type == profile::Type::SIP ? "SIP" : "RING";
|
||||||
details[ConfProperties::DISPLAYNAME] = displayName;
|
details[ConfProperties::DISPLAYNAME] = displayName;
|
||||||
details[ConfProperties::ALIAS] = displayName;
|
details[ConfProperties::ALIAS] = displayName;
|
||||||
|
@ -1059,14 +1092,14 @@ AccountModel::createNewAccount(profile::Type type,
|
||||||
details[ConfProperties::ARCHIVE_PASSWORD] = password;
|
details[ConfProperties::ARCHIVE_PASSWORD] = password;
|
||||||
details[ConfProperties::ARCHIVE_PIN] = pin;
|
details[ConfProperties::ARCHIVE_PIN] = pin;
|
||||||
details[ConfProperties::ARCHIVE_PATH] = archivePath;
|
details[ConfProperties::ARCHIVE_PATH] = archivePath;
|
||||||
if (type == profile::Type::SIP)
|
|
||||||
|
// Override the username with the provided URI if it's a SIP account
|
||||||
|
if (type == profile::Type::SIP) {
|
||||||
details[ConfProperties::USERNAME] = uri;
|
details[ConfProperties::USERNAME] = uri;
|
||||||
if (!config.isEmpty()) {
|
|
||||||
for (MapStringString::const_iterator it = config.begin(); it != config.end(); it++) {
|
|
||||||
details[it.key()] = it.value();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actually add the account and return the account ID
|
||||||
QString accountId = ConfigurationManager::instance().addAccount(details);
|
QString accountId = ConfigurationManager::instance().addAccount(details);
|
||||||
return accountId;
|
return accountId;
|
||||||
}
|
}
|
||||||
|
@ -1077,20 +1110,24 @@ AccountModel::connectToAccountManager(const QString& username,
|
||||||
const QString& serverUri,
|
const QString& serverUri,
|
||||||
const MapStringString& config)
|
const MapStringString& config)
|
||||||
{
|
{
|
||||||
MapStringString details = ConfigurationManager::instance().getAccountTemplate("RING");
|
MapStringString details = config;
|
||||||
using namespace libjami::Account;
|
using namespace libjami::Account;
|
||||||
details[ConfProperties::TYPE] = "RING";
|
details[ConfProperties::TYPE] = "RING";
|
||||||
details[ConfProperties::MANAGER_URI] = serverUri;
|
details[ConfProperties::MANAGER_URI] = serverUri;
|
||||||
details[ConfProperties::MANAGER_USERNAME] = username;
|
details[ConfProperties::MANAGER_USERNAME] = username;
|
||||||
details[ConfProperties::ARCHIVE_PASSWORD] = password;
|
details[ConfProperties::ARCHIVE_PASSWORD] = password;
|
||||||
if (!config.isEmpty()) {
|
return createNewAccount(profile::Type::JAMI, details);
|
||||||
for (MapStringString::const_iterator it = config.begin(); it != config.end(); it++) {
|
}
|
||||||
details[it.key()] = it.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString accountId = ConfigurationManager::instance().addAccount(details);
|
QString
|
||||||
return accountId;
|
AccountModel::createDeviceImportAccount()
|
||||||
|
{
|
||||||
|
// auto details = ConfigurationManager::instance().getAccountTemplate("RING");
|
||||||
|
MapStringString details;
|
||||||
|
using namespace libjami::Account;
|
||||||
|
details[ConfProperties::TYPE] = "RING";
|
||||||
|
details[ConfProperties::ARCHIVE_URL] = "jami-auth";
|
||||||
|
return createNewAccount(profile::Type::JAMI, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -188,9 +188,65 @@ struct ConfProperties_t
|
||||||
MapStringString toDetails() const;
|
MapStringString toDetails() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Possible account export status
|
// The following statuses are used to track the status of
|
||||||
enum class ExportOnRingStatus { SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2, INVALID };
|
// device-linking and account-import
|
||||||
Q_ENUM_NS(ExportOnRingStatus)
|
enum class DeviceAuthState {
|
||||||
|
INIT = 0,
|
||||||
|
TOKEN_AVAILABLE = 1,
|
||||||
|
CONNECTING = 2,
|
||||||
|
AUTHENTICATING = 3,
|
||||||
|
IN_PROGRESS = 4,
|
||||||
|
DONE = 5
|
||||||
|
};
|
||||||
|
Q_ENUM_NS(DeviceAuthState)
|
||||||
|
|
||||||
|
enum class DeviceLinkError {
|
||||||
|
WRONG_PASSWORD, // auth_error, invalid_credentials
|
||||||
|
NETWORK, // network
|
||||||
|
TIMEOUT, // timeout
|
||||||
|
STATE, // state
|
||||||
|
CANCELED, // canceled
|
||||||
|
UNKNOWN // fallback
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_ENUM_NS(DeviceLinkError)
|
||||||
|
|
||||||
|
inline DeviceLinkError
|
||||||
|
mapLinkDeviceError(const std::string& error)
|
||||||
|
{
|
||||||
|
if (error == "auth_error" || error == "invalid_credentials")
|
||||||
|
return DeviceLinkError::WRONG_PASSWORD;
|
||||||
|
if (error == "network")
|
||||||
|
return DeviceLinkError::NETWORK;
|
||||||
|
if (error == "timeout")
|
||||||
|
return DeviceLinkError::TIMEOUT;
|
||||||
|
if (error == "state")
|
||||||
|
return DeviceLinkError::STATE;
|
||||||
|
if (error == "canceled")
|
||||||
|
return DeviceLinkError::CANCELED;
|
||||||
|
return DeviceLinkError::UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString
|
||||||
|
getLinkDeviceString(DeviceLinkError error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case DeviceLinkError::WRONG_PASSWORD:
|
||||||
|
return QObject::tr(
|
||||||
|
"An authentication error occurred.\nPlease check credentials and try again.");
|
||||||
|
case DeviceLinkError::NETWORK:
|
||||||
|
return QObject::tr("A network error occurred.\nPlease verify your connection.");
|
||||||
|
case DeviceLinkError::TIMEOUT:
|
||||||
|
return QObject::tr("The operation has timed out.\nPlease try again.");
|
||||||
|
case DeviceLinkError::STATE:
|
||||||
|
return QObject::tr("An error occurred while exporting the account.\nPlease try again.");
|
||||||
|
case DeviceLinkError::CANCELED:
|
||||||
|
return QObject::tr("Operation was canceled.");
|
||||||
|
case DeviceLinkError::UNKNOWN:
|
||||||
|
default:
|
||||||
|
return QObject::tr("An unexpected error occurred.\nPlease try again.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class RegisterNameStatus {
|
enum class RegisterNameStatus {
|
||||||
SUCCESS = 0,
|
SUCCESS = 0,
|
||||||
|
|
|
@ -112,13 +112,37 @@ public:
|
||||||
Q_INVOKABLE bool exportToFile(const QString& accountId,
|
Q_INVOKABLE bool exportToFile(const QString& accountId,
|
||||||
const QString& path,
|
const QString& path,
|
||||||
const QString& password = {}) const;
|
const QString& password = {}) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call exportOnRing from the daemon
|
* Provide authentication for an account
|
||||||
* @param accountId
|
* @param accountId
|
||||||
* @param password
|
* @param credentialsFromUser
|
||||||
|
* @return if the authentication is successful
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE bool provideAccountAuthentication(const QString& accountId,
|
||||||
|
const QString& credentialsFromUser) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param accountId
|
||||||
|
* @param uri
|
||||||
* @return if the export is initialized
|
* @return if the export is initialized
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool exportOnRing(const QString& accountId, const QString& password) const;
|
Q_INVOKABLE int32_t addDevice(const QString& accountId, const QString& token) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm the addition of a device
|
||||||
|
* @param accountId
|
||||||
|
* @param operationId
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE bool confirmAddDevice(const QString& accountId, uint32_t operationId) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel the addition of a device
|
||||||
|
* @param accountId
|
||||||
|
* @param operationId
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE bool cancelAddDevice(const QString& accountId, uint32_t operationId) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call removeAccount from the daemon
|
* Call removeAccount from the daemon
|
||||||
* @param accountId to remove
|
* @param accountId to remove
|
||||||
|
@ -141,7 +165,7 @@ public:
|
||||||
* @param avatar
|
* @param avatar
|
||||||
* @throws out_of_range exception if account is not found
|
* @throws out_of_range exception if account is not found
|
||||||
*/
|
*/
|
||||||
void setAvatar(const QString& accountId, const QString& avatar, bool save = true, int flag =0);
|
void setAvatar(const QString& accountId, const QString& avatar, bool save = true, int flag = 0);
|
||||||
/**
|
/**
|
||||||
* Change the alias of an account
|
* Change the alias of an account
|
||||||
* @param accountId
|
* @param accountId
|
||||||
|
@ -159,18 +183,7 @@ public:
|
||||||
Q_INVOKABLE bool registerName(const QString& accountId,
|
Q_INVOKABLE bool registerName(const QString& accountId,
|
||||||
const QString& password,
|
const QString& password,
|
||||||
const QString& username);
|
const QString& username);
|
||||||
/**
|
|
||||||
* Connect to JAMS to retrieve the account
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param serverUri
|
|
||||||
* @param config
|
|
||||||
* @return the account id
|
|
||||||
*/
|
|
||||||
static QString connectToAccountManager(const QString& username,
|
|
||||||
const QString& password,
|
|
||||||
const QString& serverUri,
|
|
||||||
const MapStringString& config = MapStringString());
|
|
||||||
/**
|
/**
|
||||||
* Create a new Ring or SIP account
|
* Create a new Ring or SIP account
|
||||||
* @param type determine if the new account will be a Ring account or a SIP one
|
* @param type determine if the new account will be a Ring account or a SIP one
|
||||||
|
@ -184,12 +197,32 @@ public:
|
||||||
* @return the created account
|
* @return the created account
|
||||||
*/
|
*/
|
||||||
static QString createNewAccount(profile::Type type,
|
static QString createNewAccount(profile::Type type,
|
||||||
|
const MapStringString& config = MapStringString(),
|
||||||
const QString& displayName = "",
|
const QString& displayName = "",
|
||||||
const QString& archivePath = "",
|
const QString& archivePath = "",
|
||||||
const QString& password = "",
|
const QString& password = "",
|
||||||
const QString& pin = "",
|
const QString& pin = "",
|
||||||
const QString& uri = "",
|
const QString& uri = "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to JAMS to retrieve the account
|
||||||
|
* @param username
|
||||||
|
* @param password
|
||||||
|
* @param serverUri
|
||||||
|
* @param config
|
||||||
|
* @return the account id
|
||||||
|
*/
|
||||||
|
static QString connectToAccountManager(const QString& username,
|
||||||
|
const QString& password,
|
||||||
|
const QString& serverUri,
|
||||||
const MapStringString& config = MapStringString());
|
const MapStringString& config = MapStringString());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a simple ephemeral account from a device import
|
||||||
|
* @return the account id of the created account
|
||||||
|
*/
|
||||||
|
static QString createDeviceImportAccount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an account to the first position
|
* Set an account to the first position
|
||||||
*/
|
*/
|
||||||
|
@ -296,14 +329,24 @@ Q_SIGNALS:
|
||||||
void profileUpdated(const QString& accountID);
|
void profileUpdated(const QString& accountID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect this signal to know when an account is exported on the DHT
|
* Device authentication state has changed
|
||||||
* @param accountID
|
* @param accountID
|
||||||
* @param status
|
* @param state
|
||||||
* @param pin
|
* @param details map
|
||||||
*/
|
*/
|
||||||
void exportOnRingEnded(const QString& accountID,
|
void deviceAuthStateChanged(const QString& accountID, int state, const MapStringString& details);
|
||||||
account::ExportOnRingStatus status,
|
|
||||||
const QString& pin);
|
/**
|
||||||
|
* Add device state has changed
|
||||||
|
* @param accountID
|
||||||
|
* @param operationId
|
||||||
|
* @param state
|
||||||
|
* @param details map
|
||||||
|
*/
|
||||||
|
void addDeviceStateChanged(const QString& accountID,
|
||||||
|
uint32_t operationId,
|
||||||
|
int state,
|
||||||
|
const MapStringString& details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name registration has ended
|
* Name registration has ended
|
||||||
|
|
|
@ -242,9 +242,9 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent)
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(&ConfigurationManager::instance(),
|
connect(&ConfigurationManager::instance(),
|
||||||
&ConfigurationManagerInterface::exportOnRingEnded,
|
&ConfigurationManagerInterface::deviceAuthStateChanged,
|
||||||
this,
|
this,
|
||||||
&CallbacksHandler::slotExportOnRingEnded,
|
&CallbacksHandler::slotDeviceAuthStateChanged,
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(&ConfigurationManager::instance(),
|
connect(&ConfigurationManager::instance(),
|
||||||
|
@ -546,7 +546,9 @@ CallbacksHandler::slotIncomingMessage(const QString& accountId,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallbacksHandler::slotConferenceCreated(const QString& accountId, const QString& convId, const QString& callId)
|
CallbacksHandler::slotConferenceCreated(const QString& accountId,
|
||||||
|
const QString& convId,
|
||||||
|
const QString& callId)
|
||||||
{
|
{
|
||||||
Q_EMIT conferenceCreated(accountId, convId, callId);
|
Q_EMIT conferenceCreated(accountId, convId, callId);
|
||||||
}
|
}
|
||||||
|
@ -678,9 +680,11 @@ CallbacksHandler::slotDeviceRevokationEnded(const QString& accountId,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallbacksHandler::slotExportOnRingEnded(const QString& accountId, int status, const QString& pin)
|
CallbacksHandler::slotDeviceAuthStateChanged(const QString& accountId,
|
||||||
|
int state,
|
||||||
|
const MapStringString& details)
|
||||||
{
|
{
|
||||||
Q_EMIT exportOnRingEnded(accountId, status, pin);
|
Q_EMIT deviceAuthStateChanged(accountId, state, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -171,7 +171,9 @@ Q_SIGNALS:
|
||||||
* Connect this signal to know when a new conference is created
|
* Connect this signal to know when a new conference is created
|
||||||
* @param callId of the conference
|
* @param callId of the conference
|
||||||
*/
|
*/
|
||||||
void conferenceCreated(const QString& accountId, const QString& conversationId, const QString& callId);
|
void conferenceCreated(const QString& accountId,
|
||||||
|
const QString& conversationId,
|
||||||
|
const QString& callId);
|
||||||
void conferenceChanged(const QString& accountId, const QString& confId, const QString& state);
|
void conferenceChanged(const QString& accountId, const QString& confId, const QString& state);
|
||||||
/**
|
/**
|
||||||
* Connect this signal to know when a conference is removed
|
* Connect this signal to know when a conference is removed
|
||||||
|
@ -235,12 +237,12 @@ Q_SIGNALS:
|
||||||
const QString& userPhoto);
|
const QString& userPhoto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit exportOnRingEnded
|
* Device authentication state has changed
|
||||||
* @param accountId
|
* @param accountId
|
||||||
* @param status SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2
|
* @param state
|
||||||
* @param pin
|
* @param details map
|
||||||
*/
|
*/
|
||||||
void exportOnRingEnded(const QString& accountId, int status, const QString& pin);
|
void deviceAuthStateChanged(const QString& accountId, int state, const MapStringString& details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name registration has ended
|
* Name registration has ended
|
||||||
|
@ -504,7 +506,9 @@ private Q_SLOTS:
|
||||||
* @param callId of the conference
|
* @param callId of the conference
|
||||||
* @param conversationId of the conference
|
* @param conversationId of the conference
|
||||||
*/
|
*/
|
||||||
void slotConferenceCreated(const QString& accountId, const QString& conversationId, const QString& callId);
|
void slotConferenceCreated(const QString& accountId,
|
||||||
|
const QString& conversationId,
|
||||||
|
const QString& callId);
|
||||||
/**
|
/**
|
||||||
* Emit conferenceRemove
|
* Emit conferenceRemove
|
||||||
* @param accountId
|
* @param accountId
|
||||||
|
@ -574,12 +578,14 @@ private Q_SLOTS:
|
||||||
const QString& userPhoto);
|
const QString& userPhoto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit exportOnRingEnded
|
* Device authentication state has changed
|
||||||
* @param accountId
|
* @param accountId
|
||||||
* @param status SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2
|
* @param state
|
||||||
* @param pin
|
* @param details map
|
||||||
*/
|
*/
|
||||||
void slotExportOnRingEnded(const QString& accountId, int status, const QString& pin);
|
void slotDeviceAuthStateChanged(const QString& accountId,
|
||||||
|
int state,
|
||||||
|
const MapStringString& details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit nameRegistrationEnded
|
* Emit nameRegistrationEnded
|
||||||
|
|
|
@ -36,11 +36,6 @@ NameDirectoryPrivate::NameDirectoryPrivate(NameDirectory* q)
|
||||||
this,
|
this,
|
||||||
&NameDirectoryPrivate::slotRegisteredNameFound,
|
&NameDirectoryPrivate::slotRegisteredNameFound,
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
connect(&configurationManager,
|
|
||||||
&ConfigurationManagerInterface::exportOnRingEnded,
|
|
||||||
this,
|
|
||||||
&NameDirectoryPrivate::slotExportOnRingEnded,
|
|
||||||
Qt::QueuedConnection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NameDirectory::NameDirectory()
|
NameDirectory::NameDirectory()
|
||||||
|
@ -100,16 +95,6 @@ NameDirectoryPrivate::slotRegisteredNameFound(const QString& accountId,
|
||||||
requestedName);
|
requestedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export account has ended with pin generated
|
|
||||||
void
|
|
||||||
NameDirectoryPrivate::slotExportOnRingEnded(const QString& accountId, int status, const QString& pin)
|
|
||||||
{
|
|
||||||
LC_DBG << "Export on ring ended for account: " << accountId << "status: " << status
|
|
||||||
<< "PIN: " << pin;
|
|
||||||
|
|
||||||
Q_EMIT q_ptr->exportOnRingEnded(static_cast<NameDirectory::ExportOnRingStatus>(status), pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup a name
|
// Lookup a name
|
||||||
bool
|
bool
|
||||||
NameDirectory::lookupName(const QString& accountId,
|
NameDirectory::lookupName(const QString& accountId,
|
||||||
|
|
|
@ -40,15 +40,16 @@ public:
|
||||||
enum class LookupStatus { SUCCESS = 0, INVALID_NAME = 1, NOT_FOUND = 2, ERROR = 3 };
|
enum class LookupStatus { SUCCESS = 0, INVALID_NAME = 1, NOT_FOUND = 2, ERROR = 3 };
|
||||||
Q_ENUM(LookupStatus)
|
Q_ENUM(LookupStatus)
|
||||||
|
|
||||||
enum class ExportOnRingStatus { SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2, INVALID };
|
|
||||||
Q_ENUM(ExportOnRingStatus)
|
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
static NameDirectory& instance();
|
static NameDirectory& instance();
|
||||||
|
|
||||||
// Lookup
|
// Lookup
|
||||||
Q_INVOKABLE bool lookupName(const QString& accountId, const QString& name, const QString& nameServiceURL = "") const;
|
Q_INVOKABLE bool lookupName(const QString& accountId,
|
||||||
Q_INVOKABLE bool lookupAddress(const QString& accountId, const QString& address, const QString& nameServiceURL = "") const;
|
const QString& name,
|
||||||
|
const QString& nameServiceURL = "") const;
|
||||||
|
Q_INVOKABLE bool lookupAddress(const QString& accountId,
|
||||||
|
const QString& address,
|
||||||
|
const QString& nameServiceURL = "") const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constructors & Destructors
|
// Constructors & Destructors
|
||||||
|
@ -70,8 +71,5 @@ Q_SIGNALS:
|
||||||
const QString& address,
|
const QString& address,
|
||||||
const QString& registeredName,
|
const QString& registeredName,
|
||||||
const QString& requestedName);
|
const QString& requestedName);
|
||||||
|
|
||||||
// Export account has ended with pin generated
|
|
||||||
void exportOnRingEnded(NameDirectory::ExportOnRingStatus status, const QString& pin);
|
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(NameDirectory*)
|
Q_DECLARE_METATYPE(NameDirectory*)
|
||||||
|
|
|
@ -37,5 +37,4 @@ public Q_SLOTS:
|
||||||
int status,
|
int status,
|
||||||
const QString& address,
|
const QString& address,
|
||||||
const QString& registeredName);
|
const QString& registeredName);
|
||||||
void slotExportOnRingEnded(const QString& accountId, int status, const QString& pin);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -150,11 +150,23 @@ public:
|
||||||
QString(displayName.c_str()),
|
QString(displayName.c_str()),
|
||||||
QString(userPhoto.c_str()));
|
QString(userPhoto.c_str()));
|
||||||
}),
|
}),
|
||||||
exportable_callback<ConfigurationSignal::ExportOnRingEnded>(
|
exportable_callback<ConfigurationSignal::AddDeviceStateChanged>(
|
||||||
[this](const std::string& accountId, int status, const std::string& pin) {
|
[this](const std::string& accountId,
|
||||||
Q_EMIT this->exportOnRingEnded(QString(accountId.c_str()),
|
uint32_t operationId,
|
||||||
status,
|
int state,
|
||||||
QString(pin.c_str()));
|
const std::map<std::string, std::string>& details) {
|
||||||
|
Q_EMIT this->addDeviceStateChanged(QString(accountId.c_str()),
|
||||||
|
operationId,
|
||||||
|
state,
|
||||||
|
convertMap(details));
|
||||||
|
}),
|
||||||
|
exportable_callback<ConfigurationSignal::DeviceAuthStateChanged>(
|
||||||
|
[this](const std::string& accountId,
|
||||||
|
int state,
|
||||||
|
const std::map<std::string, std::string>& details) {
|
||||||
|
Q_EMIT this->deviceAuthStateChanged(QString(accountId.c_str()),
|
||||||
|
state,
|
||||||
|
convertMap(details));
|
||||||
}),
|
}),
|
||||||
exportable_callback<ConfigurationSignal::NameRegistrationEnded>(
|
exportable_callback<ConfigurationSignal::NameRegistrationEnded>(
|
||||||
[this](const std::string& accountId, int status, const std::string& name) {
|
[this](const std::string& accountId, int status, const std::string& name) {
|
||||||
|
@ -431,9 +443,28 @@ public Q_SLOTS: // METHODS
|
||||||
path.toStdString());
|
path.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exportOnRing(const QString& accountId, const QString& password)
|
bool provideAccountAuthentication(const QString& accountId,
|
||||||
|
const QString& credentialsFromUser,
|
||||||
|
const QString scheme = "password")
|
||||||
{
|
{
|
||||||
return libjami::exportOnRing(accountId.toStdString(), password.toStdString());
|
return libjami::provideAccountAuthentication(accountId.toStdString(),
|
||||||
|
credentialsFromUser.toStdString(),
|
||||||
|
scheme.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t addDevice(const QString& accountId, const QString& token)
|
||||||
|
{
|
||||||
|
return libjami::addDevice(accountId.toStdString(), token.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool confirmAddDevice(const QString& accountId, uint32_t operationId)
|
||||||
|
{
|
||||||
|
return libjami::confirmAddDevice(accountId.toStdString(), operationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cancelAddDevice(const QString& accountId, uint32_t operationId)
|
||||||
|
{
|
||||||
|
return libjami::cancelAddDevice(accountId.toStdString(), operationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exportToFile(const QString& accountId,
|
bool exportToFile(const QString& accountId,
|
||||||
|
@ -498,8 +529,7 @@ public Q_SLOTS: // METHODS
|
||||||
displayName.toStdString(),
|
displayName.toStdString(),
|
||||||
avatarPath.toStdString(),
|
avatarPath.toStdString(),
|
||||||
fileType.toStdString(),
|
fileType.toStdString(),
|
||||||
flag
|
flag);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList getAccountList()
|
QStringList getAccountList()
|
||||||
|
@ -1197,7 +1227,11 @@ Q_SIGNALS: // SIGNALS
|
||||||
const QString& certId,
|
const QString& certId,
|
||||||
const QString& status);
|
const QString& status);
|
||||||
void knownDevicesChanged(const QString& accountId, const MapStringString& devices);
|
void knownDevicesChanged(const QString& accountId, const MapStringString& devices);
|
||||||
void exportOnRingEnded(const QString& accountId, int status, const QString& pin);
|
void addDeviceStateChanged(const QString& accountId,
|
||||||
|
uint32_t operationId,
|
||||||
|
int state,
|
||||||
|
const MapStringString& details);
|
||||||
|
void deviceAuthStateChanged(const QString& accountId, int state, const MapStringString& details);
|
||||||
void incomingAccountMessage(const QString& accountId,
|
void incomingAccountMessage(const QString& accountId,
|
||||||
const QString& from,
|
const QString& from,
|
||||||
const QString msgId,
|
const QString msgId,
|
||||||
|
|
Loading…
Add table
Reference in a new issue