diff --git a/src/controller.cpp b/src/controller.cpp index eb334d291..2af1a92f8 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -307,6 +307,14 @@ NeochatChangePasswordJob::NeochatChangePasswordJob(const QString &newPassword, b setRequestData(_data); } +NeoChatDeactivateAccountJob::NeoChatDeactivateAccountJob(const Quotient::Omittable &auth) + : BaseJob(HttpVerb::Post, QStringLiteral("DisableDeviceJob"), "_matrix/client/v3/account/deactivate") +{ + QJsonObject data; + addParam(data, QStringLiteral("auth"), auth); + setRequestData(data); +} + int Controller::accountCount() const { return m_accountRegistry.count(); diff --git a/src/controller.h b/src/controller.h index 1d0f3ebe3..72bb232c1 100644 --- a/src/controller.h +++ b/src/controller.h @@ -249,3 +249,9 @@ class NeochatDeleteDeviceJob : public Quotient::BaseJob public: explicit NeochatDeleteDeviceJob(const QString &deviceId, const Quotient::Omittable &auth = Quotient::none); }; + +class NeoChatDeactivateAccountJob : public Quotient::BaseJob +{ +public: + explicit NeoChatDeactivateAccountJob(const Quotient::Omittable &auth = Quotient::none); +}; diff --git a/src/neochatconnection.cpp b/src/neochatconnection.cpp index 41f11e9c6..ec3d9faa4 100644 --- a/src/neochatconnection.cpp +++ b/src/neochatconnection.cpp @@ -132,3 +132,24 @@ QString NeoChatConnection::label() const { return accountDataJson("org.kde.neochat.account_label"_ls)["account_label"_ls].toString(); } + +void NeoChatConnection::deactivateAccount(const QString &password) +{ + auto job = callApi(); + connect(job, &BaseJob::result, this, [this, job, password] { + if (job->error() == 103) { + QJsonObject replyData = job->jsonData(); + QJsonObject authData; + authData["session"_ls] = replyData["session"_ls]; + authData["password"_ls] = password; + authData["type"_ls] = "m.login.password"_ls; + authData["user"_ls] = user()->id(); + QJsonObject identifier = {{"type"_ls, "m.id.user"_ls}, {"user"_ls, user()->id()}}; + authData["identifier"_ls] = identifier; + auto innerJob = callApi(authData); + connect(innerJob, &BaseJob::success, this, [this]() { + logout(false); + }); + } + }); +} diff --git a/src/neochatconnection.h b/src/neochatconnection.h index 207ec1a7e..c4c1bf344 100644 --- a/src/neochatconnection.h +++ b/src/neochatconnection.h @@ -46,6 +46,8 @@ public: [[nodiscard]] QString label() const; void setLabel(const QString &label); + Q_INVOKABLE void deactivateAccount(const QString &password); + Q_SIGNALS: void labelChanged(); }; diff --git a/src/qml/Dialog/ConfirmDeactivateAccountDialog.qml b/src/qml/Dialog/ConfirmDeactivateAccountDialog.qml new file mode 100644 index 000000000..5de4a225e --- /dev/null +++ b/src/qml/Dialog/ConfirmDeactivateAccountDialog.qml @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2023 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 + +import QtQuick.Layouts 1.15 + +import org.kde.kirigami 2.20 as Kirigami +import org.kde.kirigamiaddons.formcard 1.0 as FormCard + +import org.kde.neochat 1.0 + +FormCard.FormCardPage { + id: root + + property var connection + + title: i18nc("@title", "Deactivate Account") + + FormCard.FormHeader { + title: i18nc("@title", "Deactivate Account") + } + FormCard.FormCard { + FormCard.FormTextDelegate { + text: i18nc("@title", "Warning") + description: i18n("Your account will be permanently disabled.\nThis cannot be undone.\nYour Matrix ID will not be available for new accounts.\nYour messages will stay available.") + } + + FormCard.FormTextFieldDelegate { + id: passwordField + label: i18n("Password") + echoMode: TextInput.Password + } + + FormCard.FormButtonDelegate { + text: i18n("Deactivate account") + icon.name: "emblem-warning" + enabled: passwordField.text.length > 0 + onClicked: { + root.connection.deactivateAccount(passwordField.text) + root.closeDialog() + } + } + } +} diff --git a/src/qml/Settings/AccountEditorPage.qml b/src/qml/Settings/AccountEditorPage.qml index 519d7e473..0a2ccb293 100644 --- a/src/qml/Settings/AccountEditorPage.qml +++ b/src/qml/Settings/AccountEditorPage.qml @@ -249,6 +249,21 @@ Kirigami.ScrollablePage { }*/ } } + MobileForm.FormHeader { + Layout.fillWidth: true + title: i18nc("@title", "Account Management") + } + MobileForm.FormCard { + Layout.fillWidth: true + contentItem: ColumnLayout { + spacing: 0 + MobileForm.FormButtonDelegate { + id: deactivateAccountButton + text: i18n("Deactivate Account") + onClicked: pageStack.pushDialogLayer("qrc:/ConfirmDeactivateAccountDialog.qml", {connection: root.connection}, {title: i18nc("@title", "Confirm Deactivating Account")}) + } + } + } } Component { id: openFileDialog diff --git a/src/res.qrc b/src/res.qrc index dcb06a8d1..3cce484f5 100644 --- a/src/res.qrc +++ b/src/res.qrc @@ -88,6 +88,7 @@ qml/Dialog/KeyVerification/EmojiItem.qml qml/Dialog/KeyVerification/EmojiRow.qml qml/Dialog/KeyVerification/EmojiSas.qml + qml/Dialog/ConfirmDeactivateAccountDialog.qml qml/Dialog/KeyVerification/VerificationCanceled.qml qml/Menu/GlobalMenu.qml qml/Menu/EditMenu.qml