diff options
Diffstat (limited to '')
| -rw-r--r-- | modules/lock/Pam.qml | 127 |
1 files changed, 123 insertions, 4 deletions
diff --git a/modules/lock/Pam.qml b/modules/lock/Pam.qml index 2675405..0186c2f 100644 --- a/modules/lock/Pam.qml +++ b/modules/lock/Pam.qml @@ -1,4 +1,6 @@ +import qs.config import Quickshell +import Quickshell.Io import Quickshell.Wayland import Quickshell.Services.Pam import QtQuick @@ -9,12 +11,16 @@ Scope { required property WlSessionLock lock readonly property alias passwd: passwd - readonly property bool active: passwd.active + readonly property alias fprint: fprint + property string lockMessage property string state + property string fprintState property string buffer + signal flashMsg + function handleKey(event: KeyEvent): void { - if (passwd.active) + if (passwd.active || state === "max") return; if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { @@ -34,6 +40,16 @@ Scope { PamContext { id: passwd + config: "passwd" + configDirectory: Quickshell.shellDir + "/assets/pam.d" + + onMessageChanged: { + if (message.startsWith("The account is locked")) + root.lockMessage = message; + else if (root.lockMessage && message.endsWith(" left to unlock)")) + root.lockMessage += "\n" + message; + } + onResponseRequiredChanged: { if (!responseRequired) return; @@ -53,22 +69,125 @@ Scope { else if (res === PamResult.Failed) root.state = "fail"; + root.flashMsg(); stateReset.restart(); } } + PamContext { + id: fprint + + property bool available + property int tries + property int errorTries + + function checkAvail(): void { + if (!available || !Config.lock.enableFprint || !root.lock.secure) { + abort(); + return; + } + + tries = 0; + errorTries = 0; + start(); + } + + config: "fprint" + configDirectory: Quickshell.shellDir + "/assets/pam.d" + + onCompleted: res => { + if (!available) + return; + + if (res === PamResult.Success) + return root.lock.unlock(); + + if (res === PamResult.Error) { + root.fprintState = "error"; + errorTries++; + if (errorTries < 5) { + abort(); + errorRetry.restart(); + } + } else if (res === PamResult.MaxTries) { + // Isn't actually the real max tries as pam only reports completed + // when max tries is reached. + tries++; + if (tries < Config.lock.maxFprintTries) { + // Restart if not actually real max tries + root.fprintState = "fail"; + start(); + } else { + root.fprintState = "max"; + abort(); + } + } + + root.flashMsg(); + fprintStateReset.start(); + } + } + + Process { + id: availProc + + command: ["sh", "-c", "fprintd-list $USER"] + onExited: code => { + fprint.available = code === 0; + fprint.checkAvail(); + } + } + + Timer { + id: errorRetry + + interval: 800 + onTriggered: fprint.start() + } + Timer { id: stateReset interval: 4000 - onTriggered: root.state = "" + onTriggered: { + if (root.state !== "max") + root.state = ""; + } + } + + Timer { + id: fprintStateReset + + interval: 4000 + onTriggered: { + root.fprintState = ""; + fprint.errorTries = 0; + } } Connections { target: root.lock + function onSecureChanged(): void { + if (root.lock.secure) { + availProc.running = true; + root.buffer = ""; + root.state = ""; + root.fprintState = ""; + root.lockMessage = ""; + } + } + function onUnlock(): void { - root.buffer = ""; + fprint.abort(); + } + } + + Connections { + target: Config.lock + + function onEnableFprintChanged(): void { + fprint.checkAvail(); } } } |