Files
arthur-os/shell/plugins/lock/LockView.qml
T

153 lines
4.6 KiB
QML

import QtQuick
import QtQuick.Effects
import qs.Commons
Item {
id: root
property string backgroundPath: ""
property int backgroundVersion: 0
property bool fingerprintConfigured: false
property bool authenticatingPassword: false
property string failureMessage: ""
property int failedAttempts: 0
property bool inputEnabled: true
property real scaleFactor: 1
property bool hasTyped: false
readonly property string fingerprintGlyph: "\uDB80\uDE37"
readonly property string placeholderText: fingerprintConfigured ? "Enter Password " + fingerprintGlyph : "Enter Password"
readonly property real effectiveScale: Math.max(1, scaleFactor)
readonly property int fieldWidth: Math.round(650 / effectiveScale)
readonly property int fieldHeight: Math.round(100 / effectiveScale)
readonly property int outlineThickness: Math.max(1, Math.round(4 / effectiveScale))
readonly property int fieldFontSize: Style.font.heading
signal submitPassword(string password)
function withAlpha(color, alpha) {
return Qt.rgba(color.r, color.g, color.b, alpha)
}
function fileUrl(path) {
if (!path) return ""
var encoded = String(path).split("/").map(encodeURIComponent).join("/")
return "file://" + encoded + "?v=" + backgroundVersion
}
function forcePasswordFocus() {
passwordInput.forceActiveFocus()
}
function clearPassword() {
passwordInput.text = ""
hasTyped = false
}
onInputEnabledChanged: {
hasTyped = false
if (inputEnabled) Qt.callLater(forcePasswordFocus)
}
Component.onCompleted: {
hasTyped = false
if (inputEnabled) Qt.callLater(forcePasswordFocus)
}
Rectangle {
anchors.fill: parent
color: Color.background
Image {
id: wallpaper
anchors.fill: parent
source: root.fileUrl(root.backgroundPath)
fillMode: Image.PreserveAspectCrop
asynchronous: true
cache: false
sourceSize.width: width
sourceSize.height: height
}
MultiEffect {
anchors.fill: wallpaper
source: wallpaper
blurEnabled: wallpaper.status === Image.Ready
blur: 1.0
blurMax: 64
blurMultiplier: 1.0
}
MouseArea {
anchors.fill: parent
onClicked: root.forcePasswordFocus()
}
Rectangle {
id: inputField
width: root.fieldWidth
height: root.fieldHeight
anchors.centerIn: parent
color: root.withAlpha(Color.background, 0.8)
border.color: root.failureMessage.length > 0 ? Color.urgent : (root.authenticatingPassword ? Color.accent : Color.foreground)
border.width: root.outlineThickness
radius: Style.cornerRadius
clip: true
TextInput {
id: passwordInput
anchors.fill: parent
anchors.leftMargin: root.outlineThickness + 18
anchors.rightMargin: root.outlineThickness + 18
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
activeFocusOnPress: true
clip: true
enabled: root.inputEnabled && !root.authenticatingPassword
readOnly: root.authenticatingPassword
echoMode: TextInput.Password
passwordCharacter: "\u2022"
passwordMaskDelay: 0
color: Color.foreground
selectionColor: root.withAlpha(Color.accent, 0.45)
selectedTextColor: Color.foreground
font.family: "monospace"
font.pixelSize: root.fieldFontSize
cursorVisible: activeFocus && !root.authenticatingPassword && root.hasTyped
onTextChanged: {
if (text.length > 0) root.hasTyped = true
if (text.length > 0 && root.failureMessage.length > 0) root.failureMessage = ""
}
onAccepted: {
var submitted = text
text = ""
root.hasTyped = false
if (submitted.length > 0) root.submitPassword(submitted)
}
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape || (event.modifiers & Qt.ControlModifier && event.key === Qt.Key_U)) {
text = ""
root.hasTyped = false
event.accepted = true
}
}
}
Text {
anchors.fill: passwordInput
text: root.failureMessage.length > 0 ? root.failureMessage : root.placeholderText
visible: passwordInput.text.length === 0
color: root.failureMessage.length > 0 ? Color.urgent : Color.foreground
font.family: "monospace"
font.pixelSize: root.fieldFontSize
font.italic: root.failureMessage.length > 0
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
}
}