Show key import progression
This commit is contained in:
parent
f65c0176ba
commit
7d2cbae26f
|
@ -7,6 +7,7 @@ import platform
|
|||
from contextlib import suppress
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import DefaultDict, Dict, Optional, Set, Tuple, Type, Union
|
||||
|
@ -303,6 +304,32 @@ class MatrixClient(nio.AsyncClient):
|
|||
return True
|
||||
|
||||
|
||||
async def import_keys(self, infile: str, passphrase: str) -> Optional[str]:
|
||||
# Reimplemented until better solutions are worked on in nio
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
import_keys = partial(self.olm.import_keys_static, infile, passphrase)
|
||||
try:
|
||||
sessions = await loop.run_in_executor(None, import_keys)
|
||||
except nio.EncryptionError as err:
|
||||
return str(err)
|
||||
|
||||
account = self.models[Account][self.user_id]
|
||||
account.importing_key = 0
|
||||
account.total_keys_to_import = len(sessions)
|
||||
|
||||
for session in sessions:
|
||||
if self.olm.inbound_group_store.add(session):
|
||||
await loop.run_in_executor(
|
||||
None, self.store.save_inbound_group_session, session,
|
||||
)
|
||||
account.importing_key += 1
|
||||
|
||||
account.importing_key = 0
|
||||
account.total_keys_to_import = 0
|
||||
return None
|
||||
|
||||
|
||||
# Functions to register data into models
|
||||
|
||||
async def event_is_past(self, ev: Union[nio.Event, Event]) -> bool:
|
||||
|
|
|
@ -16,6 +16,9 @@ class Account(ModelItem):
|
|||
first_sync_done: bool = False
|
||||
profile_updated: Optional[datetime] = None
|
||||
|
||||
importing_key: int = 0
|
||||
total_keys_to_import: int = 0
|
||||
|
||||
def __lt__(self, other: "Account") -> bool:
|
||||
name = self.display_name or self.user_id[1:]
|
||||
other_name = other.display_name or other.user_id[1:]
|
||||
|
|
|
@ -1,81 +1,19 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import "../../Base"
|
||||
import "../../utils.js" as Utils
|
||||
|
||||
HColumnLayout {
|
||||
function importKeys(file, passphrase) {
|
||||
importButton.loading = true
|
||||
HLoader {
|
||||
id: loader
|
||||
source: accountInfo.total_keys_to_import ?
|
||||
"ImportingKeys.qml" : "ImportExportKeys.qml"
|
||||
|
||||
let path = file.toString().replace(/^file:\/\//, "")
|
||||
onSourceChanged: animation.running = true
|
||||
|
||||
py.callClientCoro(
|
||||
editAccount.userId, "import_keys", [path, passphrase], () => {
|
||||
print("import done")
|
||||
importButton.loading = false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
HLabel {
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr(
|
||||
"The decryption keys for messages you received in encrypted " +
|
||||
"rooms can be exported to a passphrase-protected file.%1" +
|
||||
"You will then be able to import this file in another " +
|
||||
"Matrix client."
|
||||
).arg(pageLoader.isWide ? "\n" :"\n\n")
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: currentSpacing
|
||||
}
|
||||
|
||||
HRowLayout {
|
||||
HButton {
|
||||
id: exportButton
|
||||
icon.name: "export-keys"
|
||||
text: qsTr("Export")
|
||||
enabled: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
}
|
||||
|
||||
HButton {
|
||||
id: importButton
|
||||
icon.name: "import-keys"
|
||||
text: qsTr("Import")
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
|
||||
HFileDialogOpener {
|
||||
id: fileDialog
|
||||
dialog.title: qsTr("Select a decryption key file to import")
|
||||
onFileChanged: {
|
||||
importPasswordPopup.file = file
|
||||
importPasswordPopup.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HPasswordPopup {
|
||||
property url file: ""
|
||||
|
||||
function verifyPassword(pass, callback) {
|
||||
return py.callCoro(
|
||||
"check_exported_keys_passphrase",
|
||||
[file.toString().replace(/^file:\/\//, ""), pass],
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
id: importPasswordPopup
|
||||
label.text: qsTr(
|
||||
"Please enter the passphrase that was used to protect this file:"
|
||||
)
|
||||
onAcceptedPasswordChanged: importKeys(file, acceptedPassword)
|
||||
HNumberAnimation {
|
||||
id: animation
|
||||
target: loader.item
|
||||
property: "scale"
|
||||
from: 0
|
||||
to: 1
|
||||
overshoot: 3
|
||||
}
|
||||
}
|
||||
|
|
80
src/qml/Pages/EditAccount/ImportExportKeys.qml
Normal file
80
src/qml/Pages/EditAccount/ImportExportKeys.qml
Normal file
|
@ -0,0 +1,80 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import "../../Base"
|
||||
import "../../utils.js" as Utils
|
||||
|
||||
HColumnLayout {
|
||||
function importKeys(file, passphrase) {
|
||||
importButton.loading = true
|
||||
|
||||
let path = file.toString().replace(/^file:\/\//, "")
|
||||
|
||||
py.callClientCoro(
|
||||
editAccount.userId, "import_keys", [path, passphrase], () => {
|
||||
if (importButton) importButton.loading = false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
HLabel {
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr(
|
||||
"The decryption keys for messages you received in encrypted " +
|
||||
"rooms can be exported to a passphrase-protected file.%1" +
|
||||
"You will then be able to import this file in another " +
|
||||
"Matrix client."
|
||||
).arg(pageLoader.isWide ? "\n" :"\n\n")
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: currentSpacing
|
||||
}
|
||||
|
||||
HRowLayout {
|
||||
HButton {
|
||||
id: exportButton
|
||||
icon.name: "export-keys"
|
||||
text: qsTr("Export")
|
||||
enabled: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
}
|
||||
|
||||
HButton {
|
||||
id: importButton
|
||||
icon.name: "import-keys"
|
||||
text: qsTr("Import")
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
|
||||
HFileDialogOpener {
|
||||
id: fileDialog
|
||||
dialog.title: qsTr("Select a decryption key file to import")
|
||||
onFileChanged: {
|
||||
importPasswordPopup.file = file
|
||||
importPasswordPopup.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HPasswordPopup {
|
||||
property url file: ""
|
||||
|
||||
function verifyPassword(pass, callback) {
|
||||
return py.callCoro(
|
||||
"check_exported_keys_passphrase",
|
||||
[file.toString().replace(/^file:\/\//, ""), pass],
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
id: importPasswordPopup
|
||||
label.text: qsTr(
|
||||
"Please enter the passphrase that was used to protect this file:"
|
||||
)
|
||||
onAcceptedPasswordChanged: importKeys(file, acceptedPassword)
|
||||
}
|
||||
}
|
36
src/qml/Pages/EditAccount/ImportingKeys.qml
Normal file
36
src/qml/Pages/EditAccount/ImportingKeys.qml
Normal file
|
@ -0,0 +1,36 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import "../../Base"
|
||||
import "../../utils.js" as Utils
|
||||
|
||||
HColumnLayout {
|
||||
HRowLayout {
|
||||
HLabel {
|
||||
text: qsTr("Importing decryption keys...")
|
||||
elide: Text.ElideRight
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: currentSpacing
|
||||
}
|
||||
|
||||
HLabel {
|
||||
text: qsTr("%1/%2")
|
||||
.arg(Math.ceil(progressBar.value)).arg(progressBar.to)
|
||||
|
||||
Layout.margins: currentSpacing
|
||||
Layout.leftMargin: 0
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar
|
||||
from: 0
|
||||
value: accountInfo.importing_key
|
||||
to: accountInfo.total_keys_to_import
|
||||
|
||||
Behavior on value { HNumberAnimation { factor: 5 } }
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user