diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c9736da21735b78504c2469fc2257e8c881e0da..ceb7ffa5d6a0a58be13c88286e0e17f15755020e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ set(COMMON_SOURCES ${SRC_DIR}/pluginhandleritemlistmodel.cpp ${SRC_DIR}/preferenceitemlistmodel.cpp ${SRC_DIR}/mediacodeclistmodel.cpp - ${SRC_DIR}/accountstomigratelistmodel.cpp + ${SRC_DIR}/currentaccounttomigrate.cpp ${SRC_DIR}/audiodevicemodel.cpp ${SRC_DIR}/pluginlistpreferencemodel.cpp ${SRC_DIR}/audiomanagerlistmodel.cpp @@ -125,7 +125,7 @@ set(COMMON_HEADERS ${SRC_DIR}/pluginhandleritemlistmodel.h ${SRC_DIR}/preferenceitemlistmodel.h ${SRC_DIR}/mediacodeclistmodel.h - ${SRC_DIR}/accountstomigratelistmodel.h + ${SRC_DIR}/currentaccounttomigrate.h ${SRC_DIR}/audiodevicemodel.h ${SRC_DIR}/pluginlistpreferencemodel.h ${SRC_DIR}/audiomanagerlistmodel.h diff --git a/qml.qrc b/qml.qrc index 65342816fdd1fdaa2c246ddf76df794a7b9b03b4..b096a67f75b3b0afb0a4cef84a7ce5e88bd2bbec 100644 --- a/qml.qrc +++ b/qml.qrc @@ -15,7 +15,6 @@ <file>src/commoncomponents/CustomBorder.qml</file> <file>src/commoncomponents/PushButton.qml</file> <file>src/commoncomponents/JamiFileDialog.qml</file> - <file>src/commoncomponents/AccountMigrationDialog.qml</file> <file>src/commoncomponents/MaterialButton.qml</file> <file>src/commoncomponents/ElidedTextLabel.qml</file> <file>src/commoncomponents/SpinnerButton.qml</file> @@ -173,5 +172,6 @@ <file>src/commoncomponents/JamiScrollBar.qml</file> <file>qtquickcontrols2.conf</file> <file>src/commoncomponents/JamiFlickable.qml</file> + <file>src/AccountMigrationView.qml</file> </qresource> </RCC> diff --git a/src/commoncomponents/AccountMigrationDialog.qml b/src/AccountMigrationView.qml similarity index 57% rename from src/commoncomponents/AccountMigrationDialog.qml rename to src/AccountMigrationView.qml index ae5b14a04d1257871f5dbea99be60cdaa3f4b265..d0cef649bc3526e7f7ae56e2b4abc7bb70c271bd 100644 --- a/src/commoncomponents/AccountMigrationDialog.qml +++ b/src/AccountMigrationView.qml @@ -25,110 +25,36 @@ import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 -import "../wizardview/components" +import "commoncomponents" // Account Migration Dialog for migrating account +Rectangle { + id: root -Window { - id: accountMigrationDialog - - AccountsToMigrateListModel { - id: accountsToMigrateListModel - - lrcInstance: LRCInstance + enum AccountMigrationStep { + PasswordEnter, + Synching } - property string accountID: "" - property string password: "" - - property bool nonOperationClosing: true - property bool successState : true - - signal accountMigrationFinished - - function startAccountMigrationOfTopStack() { - passwordInputLineEdit.clear() - accountsToMigrateListModel.reset() - - if (accountsToMigrateListModel.rowCount() <= 0) { - closeWithoutOperation() + property bool successState: true - return false - } - - var managerUsername = accountsToMigrateListModel.data(accountsToMigrateListModel.index( - 0, 0), AccountsToMigrateListModel.ManagerUsername) - var managerUri = accountsToMigrateListModel.data(accountsToMigrateListModel.index( - 0, 0), AccountsToMigrateListModel.ManagerUri) - var username = accountsToMigrateListModel.data(accountsToMigrateListModel.index( - 0, 0), AccountsToMigrateListModel.Username) - var alias = accountsToMigrateListModel.data(accountsToMigrateListModel.index( - 0, 0), AccountsToMigrateListModel.Alias) - - if (managerUri.length !== 0) { - managerUriInputLabel.text = managerUri - } else { - managerUriInputLabel.text = "N/A" - } - - if (username.length !== 0) { - usernameInputLabel.text = username - } else if (managerUsername.length !== 0) { - usernameInputLabel.text = managerUsername - } else { - usernameInputLabel.text = "N/A" - } + // signal to redirect the page to main view + signal loaderSourceChangeRequested(int sourceToLoad) - if (alias.length !== 0) { - aliasInputLabel.text = alias - } else { - aliasInputLabel.text = "N/A" - } - - accountID = accountsToMigrateListModel.data(accountsToMigrateListModel.index( - 0, 0), AccountsToMigrateListModel.Account_ID) - - connectionMigrationEnded.enabled = false - migrationPushButton.enabled = false - stackedWidget.currentIndex = 0 - - successState = true - nonOperationClosing = true - - accountMigrationDialog.show() - return true - } + function slotMigrationButtonClicked() { + stackedWidget.currentIndex = AccountMigrationView.AccountMigrationStep.Synching - function checkIfAccountMigrationFinishedAndClose() { - accountsToMigrateListModel.reset() - if (accountsToMigrateListModel.rowCount() > 0) { - startAccountMigrationOfTopStack() - } else { - accountMigrationFinished() - if (!nonOperationClosing) { - nonOperationClosing = true - accountMigrationDialog.close() - } - } + AccountAdapter.setArchivePasswordAsync( + CurrentAccountToMigrate.accountId, passwordInputLineEdit.text) } - function acceptMigration() { - nonOperationClosing = false - accountsToMigrateListModel.dataChanged(accountsToMigrateListModel.index(0, 0), - accountsToMigrateListModel.index( - accountsToMigrateListModel.rowCount() - 1, 0)) - checkIfAccountMigrationFinishedAndClose() - } + function slotDeleteButtonClicked() { + stackedWidget.currentIndex = AccountMigrationView.AccountMigrationStep.Synching - function refuseMigrationAndDeleteAccount() { - AccountAdapter.model.removeAccount(accountID) - acceptMigration() + CurrentAccountToMigrate.removeCurrentAccountToMigrate() } - function closeWithoutOperation() { - nonOperationClosing = false - accountMigrationDialog.close() - } + color: JamiTheme.backgroundColor Timer { id: timerFailureReturn @@ -137,73 +63,46 @@ Window { repeat: false onTriggered: { - stackedWidget.currentIndex = 0 + stackedWidget.currentIndex = + AccountMigrationView.AccountMigrationStep.PasswordEnter successState = true } } Connections { id: connectionMigrationEnded - enabled: false - target: AccountAdapter.model - - function onMigrationEnded(accountIdIn, ok) { - nonOperationClosing = true - connectionMigrationEnded.enabled = false - if (accountID !== accountIdIn) { - return - } + + target: CurrentAccountToMigrate + + function onMigrationEnded(ok) { + successState = ok + if (ok) { - acceptMigration() + passwordInputLineEdit.clear() + + stackedWidget.currentIndex = + AccountMigrationView.AccountMigrationStep.PasswordEnter } else { - successState = false timerFailureReturn.restart() } } - } - function slotMigrationButtonClicked() { - successState = true - stackedWidget.currentIndex = 1 - - connectionMigrationEnded.enabled = true - AccountAdapter.setArchivePasswordAsync(accountID,password) - } - - function slotDeleteButtonClicked() { - nonOperationClosing = false - refuseMigrationAndDeleteAccount() - } + function onCurrentAccountToMigrateRemoved() { + successState = true + passwordInputLineEdit.clear() - onClosing: { - connectionMigrationEnded.enabled = false - stackedWidget.currentIndex = 0 - accountID = "" - password = "" - passwordInputLineEdit.clear() - managerUriInputLabel.text = "" - usernameInputLabel.text = "" - aliasInputLabel.text = "" - - if (nonOperationClosing) { - checkIfAccountMigrationFinishedAndClose() + stackedWidget.currentIndex = + AccountMigrationView.AccountMigrationStep.PasswordEnter } - nonOperationClosing = true - } - visible: false - - title: JamiStrings.authenticate - flags: Qt.WindowStaysOnTopHint - - width: 600 - height: 600 - minimumWidth: 600 - minimumHeight: 600 - - Component.onCompleted: { - setX(Screen.width / 2 - width / 2) - setY(Screen.height / 2 - height / 2) + function onAllMigrationsFinished() { + if (UtilsAdapter.getAccountListSize() === 0) + root.loaderSourceChangeRequested( + MainApplicationWindow.LoadedSource.WizardView) + else + root.loaderSourceChangeRequested( + MainApplicationWindow.LoadedSource.MainView) + } } ColumnLayout { @@ -217,22 +116,14 @@ Window { Layout.fillHeight: true Layout.alignment: Qt.AlignHCenter - currentIndex: 0 - // Index = 0 Rectangle { id: accountMigrationPage - Layout.fillWidth: true - Layout.fillHeight: true - Layout.alignment: Qt.AlignHCenter - ColumnLayout { spacing: 8 - width: stackedWidget.width - height: stackedWidget.height - Layout.alignment: Qt.AlignHCenter + anchors.fill: accountMigrationPage Label { id: accountMigrationLabel @@ -266,7 +157,7 @@ Window { verticalAlignment: Text.AlignVCenter } - Label { + Avatar { id: avatarLabel Layout.preferredWidth: 200 @@ -274,19 +165,9 @@ Window { Layout.alignment: Qt.AlignHCenter - background: Rectangle { - id: avatarLabelBackground - - anchors.fill: parent - color: "transparent" - - Avatar { - anchors.fill: parent - showPresenceIndicator: false - mode: Avatar.Mode.Account - imageId: accountID - } - } + showPresenceIndicator: false + mode: Avatar.Mode.Account + imageId: CurrentAccountToMigrate.accountId } GridLayout { @@ -321,6 +202,13 @@ Window { Layout.preferredWidth: JamiTheme.preferredFieldWidth Layout.preferredHeight: JamiTheme.preferredFieldHeight + text: { + if (CurrentAccountToMigrate.alias.length !== 0) { + return CurrentAccountToMigrate.alias + } else { + return JamiStrings.notAvailable + } + } font.pointSize: JamiTheme.textFontSize font.kerning: true @@ -349,6 +237,15 @@ Window { Layout.preferredWidth: JamiTheme.preferredFieldWidth Layout.preferredHeight: JamiTheme.preferredFieldHeight + text: { + if (CurrentAccountToMigrate.username.length !== 0) { + return CurrentAccountToMigrate.username + } else if (CurrentAccountToMigrate.managerUsername.length !== 0) { + return CurrentAccountToMigrate.managerUsername + } else { + return JamiStrings.notAvailable + } + } font.pointSize: JamiTheme.textFontSize font.kerning: true @@ -377,6 +274,13 @@ Window { Layout.preferredWidth: JamiTheme.preferredFieldWidth Layout.preferredHeight: JamiTheme.preferredFieldHeight + text: { + if (CurrentAccountToMigrate.managerUri.length !== 0) { + return CurrentAccountToMigrate.managerUri + } else { + return JamiStrings.notAvailable + } + } font.pointSize: JamiTheme.textFontSize font.kerning: true @@ -410,22 +314,15 @@ Window { Layout.preferredHeight: 48 echoMode: TextInput.Password - placeholderText: JamiStrings.password - onTextChanged: { - migrationPushButton.enabled = text.length > 0 - password = text - } - - onEditingFinished: { - password = text - } + onAccepted: slotMigrationButtonClicked() } } RowLayout { spacing: 80 + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter Layout.bottomMargin: JamiTheme.preferredMarginSize @@ -441,12 +338,11 @@ Window { hoveredColor: JamiTheme.buttonTintedBlackHovered pressedColor: JamiTheme.buttonTintedBlackPressed outlined: true + enabled: passwordInputLineEdit.text.length > 0 text: JamiStrings.authenticate - onClicked: { - slotMigrationButtonClicked() - } + onClicked: slotMigrationButtonClicked() } MaterialButton { @@ -462,9 +358,7 @@ Window { outlined: true text: JamiStrings.deleteAccount - onClicked: { - slotDeleteButtonClicked() - } + onClicked: slotDeleteButtonClicked() } } } @@ -491,7 +385,24 @@ Window { Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true - Label { + ResponsiveImage { + id: errorLabel + + Layout.alignment: Qt.AlignHCenter + + Layout.preferredWidth: 200 + Layout.preferredHeight: 200 + + containerHeight: Layout.preferredHeight + containerWidth: Layout.preferredWidth + + visible: !successState + + source: JamiResources.round_remove_circle_24dp_svg + color: JamiTheme.redColor + } + + AnimatedImage { id: spinnerLabel Layout.alignment: Qt.AlignHCenter @@ -499,29 +410,13 @@ Window { Layout.preferredWidth: 200 Layout.preferredHeight: 200 - property string spinnerDisplyState: successState ? "spinnerLabel_Regular" : "spinnerLabel_Failure" - onSpinnerDisplyStateChanged: { - switch (spinnerDisplyState) { - case "spinnerLabel_Regular": - background = Qt.createQmlObject("import QtQuick; - import \"qrc:/src/constant/\"; - AnimatedImage { - source: JamiResources.jami_eclipse_spinner_gif - playing: true - paused: false - fillMode: Image.PreserveAspectFit - mipmap: true}", spinnerLabel) - break - case "spinnerLabel_Failure": - background = Qt.createQmlObject("import QtQuick; - import \"qrc:/src/constant/\"; - Image { - anchors.fill: parent; - source: JamiResources.error_outline_black_24dp_svg; - mipmap: true;}", spinnerLabel) - break - } - } + visible: successState + + source: JamiResources.jami_eclipse_spinner_gif + + playing: successState + fillMode: Image.PreserveAspectFit + mipmap: true } } @@ -532,9 +427,10 @@ Window { Layout.fillWidth: true Layout.bottomMargin: 80 - color: successState? "black" : "red" - text: successState? JamiStrings.inProgress : JamiStrings.authenticationFailed - font.pointSize: JamiTheme.textFontSize + color: successState ? JamiTheme.textColor : JamiTheme.redColor + text: successState ? JamiStrings.inProgress : + JamiStrings.authenticationFailed + font.pointSize: JamiTheme.textFontSize + 5 font.kerning: true horizontalAlignment: Text.AlignHCenter diff --git a/src/MainApplicationWindow.qml b/src/MainApplicationWindow.qml index 792e9ef8da3e41dd8052dff2819e37c95f3384b3..5efde1979c107b7726d4229fd924cc5d5bb7f6d5 100644 --- a/src/MainApplicationWindow.qml +++ b/src/MainApplicationWindow.qml @@ -42,6 +42,7 @@ ApplicationWindow { enum LoadedSource { WizardView = 0, MainView, + AccountMigrationView, None } @@ -63,11 +64,7 @@ ApplicationWindow { return MainApplicationWindow.LoadedSource.None } - function startAccountMigration(){ - return accountMigrationDialog.startAccountMigrationOfTopStack() - } - - function startClient(){ + function startClient() { if (UtilsAdapter.getAccountListSize() !== 0) { mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath) } else { @@ -75,6 +72,10 @@ ApplicationWindow { } } + function startAccountMigration() { + mainApplicationLoader.setSource(JamiQmlUtils.accountMigrationViewLoadPath) + } + function close(force = false) { // If we're in the onboarding wizard or 'MinimizeOnClose' // is set, then we can quit @@ -123,14 +124,6 @@ ApplicationWindow { anchors.fill: parent } - AccountMigrationDialog { - id: accountMigrationDialog - - visible: false - - onAccountMigrationFinished: startClient() - } - DaemonReconnectPopup { id: daemonReconnectPopup } @@ -225,9 +218,11 @@ ApplicationWindow { onScreenChanged: JamiQmlUtils.mainApplicationScreen = root.screen Component.onCompleted: { - if(!startAccountMigration()){ + if (CurrentAccountToMigrate.accountToMigrateListSize <= 0) startClient() - } + else + startAccountMigration() + JamiQmlUtils.mainApplicationScreen = root.screen if (Qt.platform.os !== "windows") diff --git a/src/accountstomigratelistmodel.cpp b/src/accountstomigratelistmodel.cpp deleted file mode 100644 index b05bd614623f5e981ce05de7913ebb8ef7c2d5f8..0000000000000000000000000000000000000000 --- a/src/accountstomigratelistmodel.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2019-2020 by Savoir-faire Linux - * Author: Yang Wang <yang.wang@savoirfairelinux.com> - * - * 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 3 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, see <http://www.gnu.org/licenses/>. - */ - -#include "accountstomigratelistmodel.h" - -#include "lrcinstance.h" - -#include "api/account.h" -#include "api/contact.h" -#include "api/conversation.h" -#include "api/newdevicemodel.h" - -AccountsToMigrateListModel::AccountsToMigrateListModel(QObject* parent) - : AbstractListModelBase(parent) -{} - -AccountsToMigrateListModel::~AccountsToMigrateListModel() {} - -int -AccountsToMigrateListModel::rowCount(const QModelIndex& parent) const -{ - if (!parent.isValid() && lrcInstance_) { - /* - * Count. - */ - auto accountList = lrcInstance_->accountModel().getAccountList(); - - int countAccountToMigrate = 0; - - for (const QString& i : accountList) { - auto accountStatus = lrcInstance_->accountModel().getAccountInfo(i).status; - if (accountStatus == lrc::api::account::Status::ERROR_NEED_MIGRATION) { - countAccountToMigrate++; - } - } - - return countAccountToMigrate; - } - /* - * A valid QModelIndex returns 0 as no entry has sub-elements. - */ - return 0; -} - -int -AccountsToMigrateListModel::columnCount(const QModelIndex& parent) const -{ - Q_UNUSED(parent); - /* - * Only need one column. - */ - return 1; -} - -QVariant -AccountsToMigrateListModel::data(const QModelIndex& index, int role) const -{ - auto accountList = lrcInstance_->accountModel().getAccountList(); - if (!index.isValid() || accountList.size() <= index.row()) { - return QVariant(); - } - - QList<QString> accountToMigrateList; - - for (QString i : accountList) { - auto accountStatus = lrcInstance_->accountModel().getAccountInfo(i).status; - if (accountStatus == lrc::api::account::Status::ERROR_NEED_MIGRATION) { - accountToMigrateList.append(i); - } - } - - QString accountId = accountToMigrateList.at(index.row()); - - auto& avatarInfo = lrcInstance_->accountModel().getAccountInfo(accountId); - - switch (role) { - case Role::Account_ID: - return QVariant(accountId); - case Role::ManagerUsername: - return QVariant(avatarInfo.confProperties.managerUsername); - case Role::ManagerUri: - return QVariant(avatarInfo.confProperties.managerUri); - case Role::Username: - return QVariant(avatarInfo.confProperties.username); - case Role::Alias: - return QVariant(lrcInstance_->accountModel().getAccountInfo(accountId).profileInfo.alias); - } - return QVariant(); -} - -QHash<int, QByteArray> -AccountsToMigrateListModel::roleNames() const -{ - QHash<int, QByteArray> roles; - roles[Account_ID] = "Account_ID"; - roles[ManagerUsername] = "ManagerUsername"; - roles[ManagerUri] = "ManagerUri"; - roles[Username] = "Username"; - roles[Alias] = "Alias"; - return roles; -} - -QModelIndex -AccountsToMigrateListModel::index(int row, int column, const QModelIndex& parent) const -{ - Q_UNUSED(parent); - if (column != 0) { - return QModelIndex(); - } - - if (row >= 0 && row < rowCount()) { - return createIndex(row, column); - } - return QModelIndex(); -} - -QModelIndex -AccountsToMigrateListModel::parent(const QModelIndex& child) const -{ - Q_UNUSED(child); - return QModelIndex(); -} - -Qt::ItemFlags -AccountsToMigrateListModel::flags(const QModelIndex& index) const -{ - auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; - if (!index.isValid()) { - return QAbstractItemModel::flags(index); - } - return flags; -} - -void -AccountsToMigrateListModel::reset() -{ - beginResetModel(); - endResetModel(); -} diff --git a/src/accountstomigratelistmodel.h b/src/accountstomigratelistmodel.h deleted file mode 100644 index 9b4d2ebfcc6fcc9e7c5a49ccd5cc38e32af40280..0000000000000000000000000000000000000000 --- a/src/accountstomigratelistmodel.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019-2020 by Savoir-faire Linux - * Author: Yang Wang <yang.wang@savoirfairelinux.com> - * - * 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 3 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, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "abstractlistmodelbase.h" - -class AccountsToMigrateListModel : public AbstractListModelBase -{ - Q_OBJECT -public: - enum Role { Account_ID = Qt::UserRole + 1, ManagerUsername, ManagerUri, Username, Alias }; - Q_ENUM(Role) - - explicit AccountsToMigrateListModel(QObject* parent = nullptr); - ~AccountsToMigrateListModel(); - - /* - * QAbstractListModel override. - */ - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& parent) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - /* - * Override role name as access point in qml. - */ - QHash<int, QByteArray> roleNames() const override; - QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex& child) const; - Qt::ItemFlags flags(const QModelIndex& index) const; - - /* - * This function is to reset the model when there's new account added. - */ - Q_INVOKABLE void reset(); -}; diff --git a/src/constant/JamiQmlUtils.qml b/src/constant/JamiQmlUtils.qml index a1e9c2a32a6310e8334fda8725f7fc5f51f6fddc..b2f545ed2e6eab3d89a820f45b48c06ba88fae06 100644 --- a/src/constant/JamiQmlUtils.qml +++ b/src/constant/JamiQmlUtils.qml @@ -28,6 +28,7 @@ Item { readonly property string mainViewLoadPath: "qrc:/src/mainview/MainView.qml" readonly property string wizardViewLoadPath: "qrc:/src/wizardview/WizardView.qml" + readonly property string accountMigrationViewLoadPath: "qrc:/src/AccountMigrationView.qml" readonly property string base64StringTitle: "data:image/png;base64," property var mainApplicationScreen: "" diff --git a/src/currentaccounttomigrate.cpp b/src/currentaccounttomigrate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db3e86b3dc01a16fbd896a93a7286bab0a53d7dd --- /dev/null +++ b/src/currentaccounttomigrate.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang <yang.wang@savoirfairelinux.com> + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#include "currentaccounttomigrate.h" + +#include "lrcinstance.h" + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +CurrentAccountToMigrate::CurrentAccountToMigrate(LRCInstance* instance, QObject* parent) + : QObject(parent) + , lrcInstance_(instance) +{ + auto accountList = lrcInstance_->accountModel().getAccountList(); + + for (const QString& i : accountList) { + auto accountStatus = lrcInstance_->accountModel().getAccountInfo(i).status; + if (accountStatus == lrc::api::account::Status::ERROR_NEED_MIGRATION) { + accountToMigrateList_.append(i); + } + } + + if (accountToMigrateList_.size()) { + migrationEndedConnection_ = connect( + &lrcInstance_->accountModel(), + &lrc::api::NewAccountModel::migrationEnded, + this, + [this](const QString& accountId, bool ok) { + if (ok && accountToMigrateList_.removeOne(accountId)) { + updateData(); + } + + if (accountToMigrateList_.isEmpty()) { + disconnect(migrationEndedConnection_); + Q_EMIT allMigrationsFinished(); + + return; + } + + Q_EMIT migrationEnded(ok); + }, + Qt::ConnectionType::QueuedConnection); + + updateData(); + } +} + +CurrentAccountToMigrate::~CurrentAccountToMigrate() {} + +void +CurrentAccountToMigrate::removeCurrentAccountToMigrate() +{ + if (accountToMigrateList_.removeOne(get_accountId())) { + updateData(); + } + + Utils::oneShotConnect(&lrcInstance_->accountModel(), + &lrc::api::NewAccountModel::accountRemoved, + [this] { + if (accountToMigrateList_.isEmpty()) + Q_EMIT allMigrationsFinished(); + else + Q_EMIT currentAccountToMigrateRemoved(); + }); + + lrcInstance_->accountModel().removeAccount(get_accountId()); +} + +void +CurrentAccountToMigrate::updateData() +{ + set_accountToMigrateListSize(accountToMigrateList_.size()); + if (get_accountToMigrateListSize() == 0) + return; + + QString accountId = accountToMigrateList_.at(0); + + auto& avatarInfo = lrcInstance_->accountModel().getAccountInfo(accountId); + + set_accountId(accountId); + set_managerUsername(avatarInfo.confProperties.managerUsername); + set_managerUri(avatarInfo.confProperties.managerUri); + set_username(avatarInfo.confProperties.username); + set_alias(lrcInstance_->accountModel().getAccountInfo(accountId).profileInfo.alias); +} diff --git a/src/currentaccounttomigrate.h b/src/currentaccounttomigrate.h new file mode 100644 index 0000000000000000000000000000000000000000..d39f4ff6c90f323bb62c8143e1e426a0bf500110 --- /dev/null +++ b/src/currentaccounttomigrate.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang <yang.wang@savoirfairelinux.com> + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <QObject> + +#include "qtutils.h" + +class LRCInstance; + +class CurrentAccountToMigrate : public QObject +{ + Q_OBJECT + QML_RO_PROPERTY(int, accountToMigrateListSize) + QML_RO_PROPERTY(QString, accountId) + QML_RO_PROPERTY(QString, managerUsername) + QML_RO_PROPERTY(QString, managerUri) + QML_RO_PROPERTY(QString, username) + QML_RO_PROPERTY(QString, alias) + +public: + explicit CurrentAccountToMigrate(LRCInstance* lrcInstance, QObject* parent = nullptr); + ~CurrentAccountToMigrate(); + + Q_INVOKABLE void removeCurrentAccountToMigrate(); + +Q_SIGNALS: + void migrationEnded(bool success); + void allMigrationsFinished(); + void currentAccountToMigrateRemoved(); + +private: + void updateData(); + + LRCInstance* lrcInstance_; + + // It will only be updated when starting to launch the client. + QList<QString> accountToMigrateList_; + + QMetaObject::Connection migrationEndedConnection_; +}; diff --git a/src/qmlregister.cpp b/src/qmlregister.cpp index 759b0043c37ecb9c43d671b2ed1d97faa487646f..72182e29055cb28225346ec7c683ce2e6531dd5a 100644 --- a/src/qmlregister.cpp +++ b/src/qmlregister.cpp @@ -30,9 +30,9 @@ #include "currentconversation.h" #include "currentaccount.h" #include "videodevices.h" +#include "currentaccounttomigrate.h" #include "accountlistmodel.h" -#include "accountstomigratelistmodel.h" #include "mediacodeclistmodel.h" #include "audiodevicemodel.h" #include "audiomanagerlistmodel.h" @@ -117,6 +117,7 @@ registerTypes(QQmlEngine* engine, auto currentConversation = new CurrentConversation(lrcInstance, parent); auto currentAccount = new CurrentAccount(lrcInstance, settingsManager, parent); auto videoDevices = new VideoDevices(lrcInstance, parent); + auto currentAccountToMigrate = new CurrentAccountToMigrate(lrcInstance, parent); // qml adapter registration QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, callAdapter, "CallAdapter"); @@ -130,6 +131,7 @@ registerTypes(QQmlEngine* engine, QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentConversation, "CurrentConversation"); QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentAccount, "CurrentAccount"); QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, videoDevices, "VideoDevices"); + QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentAccountToMigrate, "CurrentAccountToMigrate") // TODO: remove these QML_REGISTERSINGLETONTYPE_CUSTOM(NS_MODELS, AVModel, &lrcInstance->avModel()) @@ -151,7 +153,6 @@ registerTypes(QQmlEngine* engine, QML_REGISTERTYPE(NS_MODELS, BannedListModel); QML_REGISTERTYPE(NS_MODELS, ModeratorListModel); QML_REGISTERTYPE(NS_MODELS, MediaCodecListModel); - QML_REGISTERTYPE(NS_MODELS, AccountsToMigrateListModel); QML_REGISTERTYPE(NS_MODELS, AudioDeviceModel); QML_REGISTERTYPE(NS_MODELS, AudioManagerListModel); QML_REGISTERTYPE(NS_MODELS, PluginListPreferenceModel);