Improve import keys password popup

This commit is contained in:
miruka 2019-08-27 22:25:13 -04:00
parent 05b248e31a
commit ebfebbeae1
8 changed files with 160 additions and 34 deletions

View File

@ -8,8 +8,6 @@
- Remove the filled theme
- Have a default background
- Use [Animators](https://doc.qt.io/qt-5/qml-qtquick-animator.html)
- Choose a better default easing type for animations
- Sendbox
- Room Sidepane
- Hide when window too small
@ -34,6 +32,7 @@
- Terrible performance using `QT_QPA_PLATFORM=wayland-egl`, must use `xcb`
- UI
- Choose a better default easing type for animations
- 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
or clicked on it once
@ -42,8 +41,6 @@
- Adapt UI for small heights
- Popup:
- label size
- Accept/cancel buttons
- Transitions
- Restoring UI state:

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
viewBox="0 0 24 24"
version="1.1"
id="svg4"
sodipodi:docname="invite_accept.svg"
inkscape:version="">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview6"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-28.271186"
inkscape:cy="12"
inkscape:current-layer="svg4" />
<path
d="M9 21.035l-9-8.638 2.791-2.87 6.156 5.874 12.21-12.436 2.843 2.817z"
id="path2"
style="fill:#0d8967;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -121,13 +121,21 @@ class Backend:
# General functions
@staticmethod
def hsluv(hue: int, saturation: int, lightness: int) -> List[float]:
# (0-360, 0-100, 0-100) -> [0-1, 0-1, 0-1]
return hsluv.hsluv_to_rgb([hue, saturation, lightness])
@staticmethod
def check_exported_keys_password(file_path: str, password: str) -> bool:
try:
nio.crypto.key_export.decrypt_and_read(file_path, password)
return True
except (FileNotFoundError, ValueError):
return False
async def load_settings(self) -> tuple:
from .config_files import Theme
settings = await self.ui_settings.read()

View File

@ -59,11 +59,15 @@ HRectangle {
spacing: interfaceBox.verticalSpacing
Layout.fillWidth: true
Layout.topMargin:
interfaceTitle.visible ? 0 : interfaceBox.verticalSpacing
Layout.leftMargin: interfaceBox.horizontalSpacing
Layout.rightMargin: interfaceBox.horizontalSpacing
}
HRowLayout {
visible: buttonModel.length > 0
Repeater {
id: interfaceButtonsRepeater
model: []
@ -74,7 +78,9 @@ HRectangle {
id: button
text: modelData.text
icon.name: modelData.iconName || ""
enabled: modelData.enabled && ! button.loading
enabled: (modelData.enabled == undefined ?
true : modelData.enabled) &&
! button.loading
onClicked: buttonCallbacks[modelData.name](button)
Layout.fillWidth: true

View File

@ -5,48 +5,105 @@ import "../SidePane"
Popup {
id: popup
width: window.width
anchors.centerIn: Overlay.overlay
modal: true
padding: 0
onOpened: passwordField.forceActiveFocus()
property bool validateWhileTyping: false
property string acceptedPassword: ""
property var passwordValid: null
property bool okClicked: false
property alias label: popupLabel
property alias field: passwordField
property string password: ""
function verifyPassword(pass) {
// Implement me when using this component
return false
}
enter: Transition {
HNumberAnimation { property: "scale"; from: 0; to: 1; overshoot: 4 }
}
exit: Transition {
HNumberAnimation { property: "scale"; to: 0 }
}
background: HRectangle {
color: theme.controls.popup.background
}
HColumnLayout {
width: parent.width
spacing: theme.spacing
contentItem: HInterfaceBox {
id: box
implicitWidth: theme.minimumSupportedWidthPlusSpacing
enterButtonTarget: "ok"
buttonModel: [
{ name: "ok", text: qsTr("OK"), iconName: "ok",
enabled: passwordField.text &&
(validateWhileTyping ? passwordValid : true) },
{ name: "cancel", text: qsTr("Cancel"), iconName: "cancel" },
]
buttonCallbacks: ({
ok: button => {
let password = passwordField.text
okClicked = true
button.loading = true
if (verifyPassword(password)) {
passwordValid = true
popup.acceptedPassword = password
popup.close()
} else {
passwordValid = false
}
button.loading = false
},
cancel: button => { popup.close() },
})
HLabel {
id: popupLabel
wrapMode: Text.Wrap
Layout.alignment: Qt.AlignCenter
Layout.minimumWidth: theme.minimumSupportedWidth
Layout.maximumWidth:
Math.min(480, window.width - theme.spacing * 2)
Layout.fillWidth: true
}
HRowLayout {
spacing: box.horizontalSpacing
HTextField {
id: passwordField
placeholderText: qsTr("Passphrase")
echoMode: TextInput.Password
focus: true
onAccepted: {
popup.password = text
popup.close()
}
error: passwordValid === false
onTextChanged: passwordValid =
validateWhileTyping ? verifyPassword(text) : null
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
}
Layout.preferredWidth: popupLabel.width
Layout.maximumWidth: popupLabel.width
HIcon {
svgName: passwordValid ? "ok" : "cancel"
visible: Layout.preferredWidth > 0
Layout.preferredWidth:
passwordValid == null ||
(validateWhileTyping && ! okClicked && ! passwordValid) ?
0 :implicitWidth
Behavior on Layout.preferredWidth { HNumberAnimation {} }
}
}
}
}

View File

@ -8,9 +8,12 @@ TextField {
readonly property QtObject _tf: theme.controls.textField
property bool error: false
property bool bordered: true
property color backgroundColor: _tf.background
property color borderColor: _tf.border
property color errorBorder: _tf.errorBorder
property color focusedBackgroundColor: _tf.focusedBackground
property color focusedBorderColor: _tf.focusedBorder
property alias radius: textFieldBackground.radius
@ -20,7 +23,8 @@ TextField {
background: Rectangle {
id: textFieldBackground
color: field.activeFocus ? focusedBackgroundColor : backgroundColor
border.color: field.activeFocus ? focusedBorderColor : borderColor
border.color: error ? errorBorder :
field.activeFocus ? focusedBorderColor : borderColor
border.width: bordered ? theme.controls.textField.borderWidth : 0
Behavior on color { HColorAnimation { factor: 0.25 } }

View File

@ -63,14 +63,16 @@ HColumnLayout {
HPasswordPopup {
property url file: ""
function verifyPassword(pass) {
return py.callSync(
"check_exported_keys_password", [file.toString(), pass]
)
}
id: importPasswordPopup
label.text: qsTr(
"Please enter the passphrase that was used to protect this " +
"file.\n\n" +
"The import can take a few minutes. " +
"You can leave the account settings page while it is running. " +
"Messages may not be sent or received until the operation is done."
"Please enter the passphrase that was used to protect this file:"
)
onPasswordChanged: importKeys(file, password)
onAcceptedPasswordChanged: importKeys(file, password)
}
}

View File

@ -133,6 +133,7 @@ controls:
int borderWidth: 1
color border: "transparent"
color focusedBorder: colors.strongAccentBackground
color errorBorder: colors.errorText
color text: colors.text
color focusedText: colors.text