Show key import progression

This commit is contained in:
miruka 2019-08-28 03:54:53 -04:00
parent f65c0176ba
commit 7d2cbae26f
5 changed files with 158 additions and 74 deletions

View File

@ -7,6 +7,7 @@ import platform
from contextlib import suppress from contextlib import suppress
from datetime import datetime from datetime import datetime
from enum import Enum from enum import Enum
from functools import partial
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import DefaultDict, Dict, Optional, Set, Tuple, Type, Union from typing import DefaultDict, Dict, Optional, Set, Tuple, Type, Union
@ -303,6 +304,32 @@ class MatrixClient(nio.AsyncClient):
return True 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 # Functions to register data into models
async def event_is_past(self, ev: Union[nio.Event, Event]) -> bool: async def event_is_past(self, ev: Union[nio.Event, Event]) -> bool:

View File

@ -16,6 +16,9 @@ class Account(ModelItem):
first_sync_done: bool = False first_sync_done: bool = False
profile_updated: Optional[datetime] = None profile_updated: Optional[datetime] = None
importing_key: int = 0
total_keys_to_import: int = 0
def __lt__(self, other: "Account") -> bool: def __lt__(self, other: "Account") -> bool:
name = self.display_name or self.user_id[1:] name = self.display_name or self.user_id[1:]
other_name = other.display_name or other.user_id[1:] other_name = other.display_name or other.user_id[1:]

View File

@ -1,81 +1,19 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import "../../Base" import "../../Base"
import "../../utils.js" as Utils
HColumnLayout { HLoader {
function importKeys(file, passphrase) { id: loader
importButton.loading = true source: accountInfo.total_keys_to_import ?
"ImportingKeys.qml" : "ImportExportKeys.qml"
let path = file.toString().replace(/^file:\/\//, "") onSourceChanged: animation.running = true
py.callClientCoro( HNumberAnimation {
editAccount.userId, "import_keys", [path, passphrase], () => { id: animation
print("import done") target: loader.item
importButton.loading = false property: "scale"
} from: 0
) to: 1
} overshoot: 3
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)
} }
} }

View 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)
}
}

View 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
}
}