Show import keys error in the UI
This commit is contained in:
parent
7d2cbae26f
commit
ce3404a516
8
TODO.md
8
TODO.md
|
@ -22,9 +22,7 @@ translated arg for avatar upload and login
|
||||||
- Fixes
|
- Fixes
|
||||||
- Restore previous focus after closing right click context menu
|
- Restore previous focus after closing right click context menu
|
||||||
|
|
||||||
- Run import in thread and AsyncClient.olm functions, they block async loop
|
- Show error if uploading avatar fails
|
||||||
- Handle import keys errors
|
|
||||||
- Show error box if uploading avatar fails
|
|
||||||
|
|
||||||
- Don't strip user spacing in html
|
- Don't strip user spacing in html
|
||||||
- Do something when access token is invalid
|
- Do something when access token is invalid
|
||||||
|
@ -35,9 +33,7 @@ translated arg for avatar upload and login
|
||||||
- Terrible performance using `QT_QPA_PLATFORM=wayland-egl`, must use `xcb`
|
- Terrible performance using `QT_QPA_PLATFORM=wayland-egl`, must use `xcb`
|
||||||
|
|
||||||
- UI
|
- UI
|
||||||
- When starting a long task, e.g. importing keys, quitting the page,
|
- Decrypt messages again after importing keys
|
||||||
and coming back, show the buttons as still loading until operation is done
|
|
||||||
|
|
||||||
- Choose a better default easing type for animations
|
- Choose a better default easing type for animations
|
||||||
- Make invite icon blink if there's no one but ourself in the room,
|
- Make invite icon blink if there's no one but ourself in the room,
|
||||||
but never do it again once the user hovered it long enough to show tooltip
|
but never do it again once the user hovered it long enough to show tooltip
|
||||||
|
|
1
src/icons/light-thin/retry.svg
Normal file
1
src/icons/light-thin/retry.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13.5 2c-5.629 0-10.212 4.436-10.475 10h-3.025l4.537 5.917 4.463-5.917h-2.975c.26-3.902 3.508-7 7.475-7 4.136 0 7.5 3.364 7.5 7.5s-3.364 7.5-7.5 7.5c-2.381 0-4.502-1.119-5.876-2.854l-1.847 2.449c1.919 2.088 4.664 3.405 7.723 3.405 5.798 0 10.5-4.702 10.5-10.5s-4.702-10.5-10.5-10.5z"/></svg>
|
After Width: | Height: | Size: 383 B |
|
@ -304,17 +304,21 @@ class MatrixClient(nio.AsyncClient):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def import_keys(self, infile: str, passphrase: str) -> Optional[str]:
|
async def import_keys(self, infile: str, passphrase: str) -> None:
|
||||||
# Reimplemented until better solutions are worked on in nio
|
# Reimplemented until better solutions are worked on in nio
|
||||||
|
await self.clear_import_error()
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
account = self.models[Account][self.user_id]
|
||||||
import_keys = partial(self.olm.import_keys_static, infile, passphrase)
|
import_keys = partial(self.olm.import_keys_static, infile, passphrase)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sessions = await loop.run_in_executor(None, import_keys)
|
sessions = await loop.run_in_executor(None, import_keys)
|
||||||
except nio.EncryptionError as err:
|
except nio.EncryptionError as err:
|
||||||
return str(err)
|
account.import_error = (infile, passphrase, str(err))
|
||||||
|
return
|
||||||
|
|
||||||
account = self.models[Account][self.user_id]
|
|
||||||
account.importing_key = 0
|
account.importing_key = 0
|
||||||
account.total_keys_to_import = len(sessions)
|
account.total_keys_to_import = len(sessions)
|
||||||
|
|
||||||
|
@ -330,6 +334,10 @@ class MatrixClient(nio.AsyncClient):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def clear_import_error(self) -> None:
|
||||||
|
self.models[Account][self.user_id].import_error = ("", "", "")
|
||||||
|
|
||||||
|
|
||||||
# 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:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from ..html_filter import HTML_FILTER
|
from ..html_filter import HTML_FILTER
|
||||||
from ..utils import AutoStrEnum, auto
|
from ..utils import AutoStrEnum, auto
|
||||||
|
@ -18,6 +18,7 @@ class Account(ModelItem):
|
||||||
|
|
||||||
importing_key: int = 0
|
importing_key: int = 0
|
||||||
total_keys_to_import: int = 0
|
total_keys_to_import: int = 0
|
||||||
|
import_error: Tuple[str, str, str] = ("", "", "") # path,pw,err
|
||||||
|
|
||||||
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:]
|
||||||
|
|
|
@ -10,7 +10,7 @@ Item {
|
||||||
rotation: 45 * 3
|
rotation: 45 * 3
|
||||||
gradient: Gradient {
|
gradient: Gradient {
|
||||||
GradientStop { position: 0.0; color: Qt.hsla(0.73, 0.25, 0.25, 1) }
|
GradientStop { position: 0.0; color: Qt.hsla(0.73, 0.25, 0.25, 1) }
|
||||||
GradientStop { position: 1.0; color: Qt.hsla(0.52, 1, 0.08, 1) }
|
GradientStop { position: 1.0; color: Qt.hsla(0.52, 1, 0.06, 1) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,39 @@ import QtQuick 2.12
|
||||||
import "../../Base"
|
import "../../Base"
|
||||||
|
|
||||||
HLoader {
|
HLoader {
|
||||||
id: loader
|
property bool importing: false
|
||||||
source: accountInfo.total_keys_to_import ?
|
|
||||||
"ImportingKeys.qml" : "ImportExportKeys.qml"
|
|
||||||
|
function importKeys(file, passphrase, button=null) {
|
||||||
|
if (button) button.loading = true
|
||||||
|
importing = true
|
||||||
|
|
||||||
|
let path = file.toString().replace(/^file:\/\//, "")
|
||||||
|
|
||||||
|
py.callClientCoro(
|
||||||
|
editAccount.userId, "import_keys", [path, passphrase], () => {
|
||||||
|
importing = false
|
||||||
|
if (button) button.loading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
id: encryptionUI
|
||||||
|
source:
|
||||||
|
accountInfo.import_error[0] ? "ImportError.qml" :
|
||||||
|
importing || accountInfo.total_keys_to_import ? "ImportingKeys.qml" :
|
||||||
|
"ImportExportKeys.qml"
|
||||||
|
|
||||||
onSourceChanged: animation.running = true
|
onSourceChanged: animation.running = true
|
||||||
|
|
||||||
HNumberAnimation {
|
SequentialAnimation {
|
||||||
id: animation
|
id: animation
|
||||||
target: loader.item
|
HNumberAnimation {
|
||||||
property: "scale"
|
target: encryptionUI; property: "scale"; to: 0;
|
||||||
from: 0
|
}
|
||||||
to: 1
|
HNumberAnimation {
|
||||||
overshoot: 3
|
target: encryptionUI; property: "scale"; to: 1; overshoot: 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
33
src/qml/Pages/EditAccount/ImportError.qml
Normal file
33
src/qml/Pages/EditAccount/ImportError.qml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Controls 2.12
|
||||||
|
import QtQuick.Layouts 1.12
|
||||||
|
import "../../Base"
|
||||||
|
import "../../utils.js" as Utils
|
||||||
|
|
||||||
|
HInterfaceBox {
|
||||||
|
buttonModel: [
|
||||||
|
{ name: "retry", text: qsTr("Retry"), iconName: "retry" },
|
||||||
|
{ name: "cancel", text: qsTr("Cancel"), iconName: "cancel" },
|
||||||
|
]
|
||||||
|
|
||||||
|
buttonCallbacks: ({
|
||||||
|
retry: button => {
|
||||||
|
encryptionUI.importKeys(
|
||||||
|
accountInfo.import_error[0],
|
||||||
|
accountInfo.import_error[1],
|
||||||
|
button,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
cancel: button => { py.callClientCoro(userId, "clear_import_error") },
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
HLabel {
|
||||||
|
color: theme.colors.errorText
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text: qsTr("Couldn't import decryption keys file: %1")
|
||||||
|
.arg(qsTr(accountInfo.import_error[2]))
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,18 +5,6 @@ import "../../Base"
|
||||||
import "../../utils.js" as Utils
|
import "../../utils.js" as Utils
|
||||||
|
|
||||||
HColumnLayout {
|
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 {
|
HLabel {
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
text: qsTr(
|
text: qsTr(
|
||||||
|
@ -75,6 +63,7 @@ HColumnLayout {
|
||||||
label.text: qsTr(
|
label.text: qsTr(
|
||||||
"Please enter the passphrase that was used to protect this file:"
|
"Please enter the passphrase that was used to protect this file:"
|
||||||
)
|
)
|
||||||
onAcceptedPasswordChanged: importKeys(file, acceptedPassword)
|
onAcceptedPasswordChanged:
|
||||||
|
encryptionUI.importKeys(file, acceptedPassword, importButton)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user