Update password entry fields

This commit is contained in:
Michael Zanetti 2019-11-22 17:31:46 +01:00
parent 1f40b7f963
commit ff232f2e4b
4 changed files with 74 additions and 66 deletions

View File

@ -180,23 +180,10 @@ Page {
}
RowLayout {
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
TextField {
PasswordTextField {
id: passwordTextField
Layout.fillWidth: true
echoMode: hiddenPassword ? TextInput.Password : TextInput.Normal
property bool hiddenPassword: true
}
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "../images/eye.svg"
color: passwordTextField.hiddenPassword ? keyColor : app.accentColor
MouseArea {
anchors.fill: parent
onClicked: {
passwordTextField.hiddenPassword = !passwordTextField.hiddenPassword
}
}
signup: false
}
}
@ -208,7 +195,7 @@ Page {
enabled: usernameTextField.acceptableInput
onClicked: {
busyOverlay.shown = true
AWSClient.login(usernameTextField.text, passwordTextField.text);
AWSClient.login(usernameTextField.text, passwordTextField.password);
}
}
@ -338,13 +325,18 @@ Page {
id: passwordTextField
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
Layout.fillWidth: true
minPasswordLength: 8
requireLowerCaseLetter: true
requireUpperCaseLetter: true
requireNumber: true
requireSpecialChar: false
}
Button {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
text: qsTr("Sign up")
enabled: usernameTextField.acceptableInput && passwordTextField.isValidPassword
enabled: usernameTextField.acceptableInput && passwordTextField.isValid
onClicked: {
busyOverlay.shown = true;
AWSClient.signup(usernameTextField.text, passwordTextField.password)
@ -576,13 +568,18 @@ Page {
PasswordTextField {
id: passwordTextField
minPasswordLength: 8
requireLowerCaseLetter: true
requireUpperCaseLetter: true
requireNumber: true
requireSpecialChar: false
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
}
Button {
Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
text: qsTr("Reset password")
enabled: passwordTextField.isValidPassword && codeTextField.text.length > 0
enabled: passwordTextField.isValid && codeTextField.text.length > 0
onClicked: {
busyOverlay.shown = true
AWSClient.confirmForgotPassword(confirmResetPasswordPage.email, codeTextField.text, passwordTextField.password)

View File

@ -5,18 +5,31 @@ import QtQuick.Layouts 1.2
ColumnLayout {
id: root
property int minPasswordLength: 12
property bool signup: true
// Only used when signup is true
property int minPasswordLength: 12
property bool requireSpecialChar: true
property bool requireNumber: true
property bool requireUpperCaseLetter: true
property bool requireLowerCaseLetter: true
readonly property alias password: passwordTextField.text
readonly property bool isValidPassword: isLongEnough && hasLower && hasUpper && hasNumbers && hasSpecialChar && (confirmationMatches || !signup)
readonly property bool isValidPassword:
isLongEnough &&
(hasLower || !requireLowerCaseLetter) &&
(hasUpper || !requireUpperCaseLetter) &&
(hasNumbers || !requireNumber) &&
(hasSpecialChar || !requireSpecialChar)
readonly property bool isValid: !signup || (isValidPassword && confirmationMatches)
readonly property bool isLongEnough: passwordTextField.text.length >= minPasswordLength
readonly property bool hasLower: passwordTextField.text.search(/[a-z]/) >= 0
readonly property bool hasUpper: passwordTextField.text.search(/[A-Z/]/) >= 0
readonly property bool hasNumbers: passwordTextField.text.search(/[0-9]/) >= 0
readonly property bool hasSpecialChar: passwordTextField.text.search(/[\.,\*!"$%&/()=?`'+#'¡^°²³¼\[\]|{}\\@]/) >= 0
readonly property bool hasNumbers: passwordTextField.text.search(/[0-9]/) >= 0
readonly property bool hasSpecialChar: passwordTextField.text.search(/(?=.*?[$*.\[\]{}()?\-'"!@#%&/\\,><':;|_~`^])/) >= 0
readonly property bool confirmationMatches: passwordTextField.text === confirmationPasswordTextField.text
property bool hiddenPassword: true
@ -29,6 +42,41 @@ ColumnLayout {
Layout.fillWidth: true
echoMode: root.hiddenPassword ? TextInput.Password : TextInput.Normal
placeholderText: root.signup ? qsTr("Pick a password") : ""
ToolTip.visible: root.signup && focus && !root.isValidPassword
ToolTip.delay: 1000
ToolTip.onVisibleChanged: print("Tooltip visible changed:", ToolTip.visible, focus, root.isValidPassword)
ToolTip.text: {
var texts = []
var checks = []
texts.push(qsTr("Minimum %1 characters").arg(root.minPasswordLength))
checks.push(root.isLongEnough)
if (root.requireLowerCaseLetter) {
texts.push(qsTr("Lowercase letters"))
checks.push(root.hasLower)
}
if (root.requireUpperCaseLetter) {
texts.push(qsTr("Uppercase letters"))
checks.push(root.hasUpper)
}
if (root.requireNumber) {
texts.push(qsTr("Numbers"))
checks.push(root.hasNumbers)
}
if (root.requireSpecialChar) {
texts.push(qsTr("Special characters"))
checks.push(root.hasSpecialChar)
}
var ret = []
for (var i = 0; i < texts.length; i++) {
var entry = "<font color=\"%1\">• ".arg(checks[i] ? app.foregroundColor : app.accentColor)
entry += texts[i]
entry += "</font>"
ret.push(entry)
}
return ret.join("<br>")
}
}
ColorIcon {
Layout.preferredHeight: app.iconSize
@ -44,24 +92,6 @@ ColumnLayout {
}
}
Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
visible: root.signup
// TRANSLATORS: %1 will be replaced with the normal text color, %2 the color for the length check
text: qsTr("<font color=\"%1\">The password needs to be </font><font color=\"%2\">at least %3 characters long</font><font color=\"%1\">, contain </font><font color=\"%4\">lowercase</font><font color=\"%1\">, </font><font color=\"%5\">uppercase</font><font color=\"%1\"> letters as well as </font><font color=\"%6\">numbers</font><font color=\"%1\"> and </font><font color=\"%7\">special characters</font><font color=\"%1\">.</font>")
.arg(app.accentColor)
.arg(!root.isLongEnough ? "red" : app.accentColor)
.arg(root.minPasswordLength)
.arg(!root.hasLower ? "red" : app.accentColor)
.arg(!root.hasUpper ? "red" : app.accentColor)
.arg(!root.hasNumbers ? "red" : app.accentColor)
.arg(!root.hasSpecialChar ? "red" : app.accentColor)
font.pixelSize: app.smallFont
}
RowLayout {
visible: root.signup
@ -71,28 +101,5 @@ ColumnLayout {
echoMode: root.hiddenPassword ? TextInput.Password : TextInput.Normal
placeholderText: qsTr("Confirm password")
}
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "../images/eye.svg"
color: root.hiddenPassword ? keyColor : app.accentColor
MouseArea {
anchors.fill: parent
onClicked: {
root.hiddenPassword = !root.hiddenPassword
}
}
}
}
Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
visible: root.signup
text: root.confirmationMatches ? qsTr("<font color=\"%1\">The passwords match.</font>").arg(app.accentColor) : qsTr("<font color=\"%1\">The passwords </font><font color=\"%2\">do not</font><font color=\"%1\"> match.</font>").arg(app.accentColor).arg("red")
font.pixelSize: app.smallFont
}
}

View File

@ -104,6 +104,10 @@ Page {
id: passwordTextField
Layout.fillWidth: true
minPasswordLength: 8
requireLowerCaseLetter: true
requireUpperCaseLetter: true
requireNumber: true
requireSpecialChar: false
signup: engine.jsonRpcClient.initialSetupRequired
}
}
@ -112,7 +116,7 @@ Page {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.bottomMargin: app.margins
text: qsTr("OK")
enabled: passwordTextField.isValidPassword
enabled: passwordTextField.isValid
onClicked: {
if (engine.jsonRpcClient.initialSetupRequired) {
print("create user")

View File

@ -440,11 +440,11 @@ Page {
visible: pairingPage.setupMethod === "SetupMethodUserAndPassword"
}
TextField {
PasswordTextField {
id: pinTextField
Layout.fillWidth: true
visible: pairingPage.setupMethod === "SetupMethodDisplayPin" || pairingPage.setupMethod === "SetupMethodUserAndPassword"
echoMode: TextField.Password
signup: false
}