78 lines
2.1 KiB
QML
78 lines
2.1 KiB
QML
// Four segments saying how much a password has going for it.
|
|
//
|
|
// The score is computed here, from length and which character classes appear,
|
|
// and from nothing else. There is no dictionary, no breach list and no network
|
|
// call, so the row claims exactly what it can back up: it is headed "Strength"
|
|
// and says in its own detail line that it only measures shape. A meter that
|
|
// says "Strong" about a leaked password is worse than no meter, so this one
|
|
// never uses that word.
|
|
|
|
import QtQuick
|
|
import qs.config
|
|
|
|
SettingRow {
|
|
id: root
|
|
|
|
property string password: ""
|
|
|
|
readonly property int score: {
|
|
const value = root.password;
|
|
if (value === "")
|
|
return 0;
|
|
|
|
let classes = 0;
|
|
if (/[a-z]/.test(value))
|
|
classes += 1;
|
|
if (/[A-Z]/.test(value))
|
|
classes += 1;
|
|
if (/[0-9]/.test(value))
|
|
classes += 1;
|
|
if (/[^A-Za-z0-9]/.test(value))
|
|
classes += 1;
|
|
|
|
let points = Math.max(0, classes - 1);
|
|
if (value.length >= 8)
|
|
points += 1;
|
|
if (value.length >= 12)
|
|
points += 1;
|
|
if (value.length >= 16)
|
|
points += 1;
|
|
|
|
if (value.length < 8)
|
|
return 1;
|
|
return Math.max(1, Math.min(4, points));
|
|
}
|
|
|
|
readonly property color tone: {
|
|
if (root.score <= 1)
|
|
return Theme.danger;
|
|
if (root.score === 2)
|
|
return Theme.warn;
|
|
return Theme.ok;
|
|
}
|
|
|
|
label: "Strength"
|
|
detail: "Length and variety of characters, measured here — nothing is sent anywhere, and nothing is checked against known passwords"
|
|
controlWidth: 150
|
|
|
|
Row {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 5
|
|
|
|
Repeater {
|
|
model: 4
|
|
|
|
delegate: Rectangle {
|
|
required property int index
|
|
|
|
width: 32
|
|
height: 5
|
|
radius: 2.5
|
|
color: index < root.score ? root.tone : Theme.alpha(Theme.fg, 0.12)
|
|
border.width: 0
|
|
}
|
|
}
|
|
}
|
|
}
|