Update password entry fields
This commit is contained in:
parent
1f40b7f963
commit
ff232f2e4b
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user