Work
This commit is contained in:
@@ -406,3 +406,12 @@ void Controller::removeConnection(const QString &userId)
|
||||
SettingsGroup("Accounts"_ls).remove(userId);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::saveFileContent(const QString &path, const QByteArray &data) const
|
||||
{
|
||||
QUrl url(path);
|
||||
QFile file(url.toLocalFile());
|
||||
file.open(QFile::WriteOnly);
|
||||
file.write(data);
|
||||
file.close();
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
static void listenForNotifications();
|
||||
|
||||
Q_INVOKABLE QString loadFileContent(const QString &path) const;
|
||||
Q_INVOKABLE void saveFileContent(const QString &path, const QByteArray &data) const;
|
||||
|
||||
Quotient::AccountRegistry &accounts();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <Quotient/accountregistry.h>
|
||||
#include <Quotient/e2ee/sssshandler.h>
|
||||
#include <Quotient/keyimport.h>
|
||||
#include <Quotient/keyverificationsession.h>
|
||||
|
||||
#include "controller.h"
|
||||
@@ -50,3 +51,10 @@ struct ForeignSSSSHandler {
|
||||
QML_FOREIGN(Quotient::SSSSHandler)
|
||||
QML_NAMED_ELEMENT(SSSSHandler)
|
||||
};
|
||||
|
||||
struct ForeignKeyImport {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(Quotient::KeyImport)
|
||||
QML_NAMED_ELEMENT(KeyImport)
|
||||
QML_SINGLETON
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <Quotient/connection.h>
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
#include <Quotient/keyimport.h>
|
||||
#include <Quotient/quotient_common.h>
|
||||
#include <qt6keychain/keychain.h>
|
||||
|
||||
@@ -500,4 +501,15 @@ LinkPreviewer *NeoChatConnection::previewerForLink(const QUrl &link)
|
||||
return previewer;
|
||||
}
|
||||
|
||||
void NeoChatConnection::exportMegolmSessions(const QString &passphrase, const QString &path)
|
||||
{
|
||||
KeyImport keyImport;
|
||||
auto result = keyImport.exportKeys(passphrase, this);
|
||||
if (!result.has_value()) {
|
||||
qWarning() << "error TODO";
|
||||
return;
|
||||
}
|
||||
Controller::instance().saveFileContent(path, result.value());
|
||||
}
|
||||
|
||||
#include "moc_neochatconnection.cpp"
|
||||
|
||||
@@ -160,6 +160,8 @@ public:
|
||||
|
||||
LinkPreviewer *previewerForLink(const QUrl &link);
|
||||
|
||||
Q_INVOKABLE void exportMegolmSessions(const QString &passphrase, const QString &path);
|
||||
|
||||
Q_SIGNALS:
|
||||
void labelChanged();
|
||||
void directChatNotificationsChanged();
|
||||
|
||||
@@ -35,4 +35,6 @@ qt_add_qml_module(settings
|
||||
PasswordSheet.qml
|
||||
ThemeRadioButton.qml
|
||||
ThreePIdCard.qml
|
||||
ImportKeysDialog.qml
|
||||
ExportKeysDialog.qml
|
||||
)
|
||||
|
||||
48
src/settings/ExportKeysDialog.qml
Normal file
48
src/settings/ExportKeysDialog.qml
Normal file
@@ -0,0 +1,48 @@
|
||||
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
title: i18nc("@title", "Export Keys")
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
FormCard.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: passphraseField
|
||||
label: i18nc("@label:textbox", "Passphrase:")
|
||||
echoMode: TextInput.Password
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
enabled: passphraseField.text.length > 0
|
||||
text: i18nc("@action:button", "Export keys")
|
||||
onClicked: {
|
||||
let dialog = saveDialog.createObject(root);
|
||||
dialog.accepted.connect(() => {
|
||||
root.connection.exportMegolmSessions(passphraseField.text, dialog.selectedFile);
|
||||
});
|
||||
dialog.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: saveDialog
|
||||
FileDialog {
|
||||
fileMode: FileDialog.SaveFile
|
||||
currentFolder: Config.lastSaveDirectory.length > 0 ? Config.lastSaveDirectory : StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
73
src/settings/ImportKeysDialog.qml
Normal file
73
src/settings/ImportKeysDialog.qml
Normal file
@@ -0,0 +1,73 @@
|
||||
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
title: i18nc("@title", "Import Keys")
|
||||
|
||||
header: KirigamiComponents.Banner {
|
||||
id: banner
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
}
|
||||
|
||||
FormCard.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
FormCard.FormButtonDelegate {
|
||||
id: fileButton
|
||||
text: i18nc("@action:button", "Choose backup file")
|
||||
description: ""
|
||||
icon.name: "cloud-upload"
|
||||
onClicked: {
|
||||
let dialog = Qt.createComponent("org.kde.neochat", "OpenFileDialog").createObject(root);
|
||||
dialog.chosen.connect(path => {
|
||||
fileButton.description = path.substring(7);
|
||||
});
|
||||
dialog.open();
|
||||
}
|
||||
}
|
||||
FormCard.FormDelegateSeparator {}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: passphraseField
|
||||
label: i18nc("@label:textbox", "Passphrase:")
|
||||
echoMode: TextInput.Password
|
||||
}
|
||||
FormCard.FormDelegateSeparator {}
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Import keys")
|
||||
enabled: fileButton.description.length > 0 && passphraseField.text.length > 0
|
||||
onClicked: {
|
||||
banner.visible = false;
|
||||
let error = KeyImport.importKeys(Controller.loadFileContent(fileButton.description), passphraseField.text, root.connection);
|
||||
if (error === KeyImport.Success) {
|
||||
root.closeDialog();
|
||||
} else if (error === KeyImport.InvalidPassphrase) {
|
||||
banner.text = i18nc("@info", "Invalid passphrase");
|
||||
banner.visible = true;
|
||||
} else if (error === KeyImport.InvalidData) {
|
||||
banner.text = i18nc("@info", "Invalid key backup data");
|
||||
banner.visible = true;
|
||||
} else {
|
||||
banner.text = i18nc("@info", "Unknown error");
|
||||
banner.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,6 +33,31 @@ FormCard.FormCardPage {
|
||||
description: i18n("Device id")
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Encryption Keys")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Import Encryption Keys")
|
||||
icon.name: "document-import"
|
||||
onClicked: pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat.settings", "ImportKeysDialog"), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18nc("@title", "Import Keys")
|
||||
})
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Export Encryption Keys")
|
||||
icon.name: "document-export"
|
||||
onClicked: pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat.settings", "ExportKeysDialog"), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18nc("@title", "Export Keys")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title:group", "Ignored Users")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user