diff options
Diffstat (limited to 'modules/lock')
| -rw-r--r-- | modules/lock/Center.qml | 87 | ||||
| -rw-r--r-- | modules/lock/InputField.qml | 159 | ||||
| -rw-r--r-- | modules/lock/Pam.qml | 7 |
3 files changed, 172 insertions, 81 deletions
diff --git a/modules/lock/Center.qml b/modules/lock/Center.qml index bcc5130..f760ef8 100644 --- a/modules/lock/Center.qml +++ b/modules/lock/Center.qml @@ -108,7 +108,12 @@ ColumnLayout { forceActiveFocus(); } - Keys.onPressed: event => root.lock.pam.handleKey(event) + Keys.onPressed: event => { + if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) + inputField.placeholder.animate = false; + + root.lock.pam.handleKey(event); + } StateLayer { hoverEnabled: false @@ -131,84 +136,10 @@ ColumnLayout { text: "lock" } - Item { - Layout.fillWidth: true - Layout.fillHeight: true - - ListView { - id: passwordList - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - implicitHeight: Appearance.font.size.normal - - orientation: Qt.Horizontal - clip: true - interactive: false - spacing: Appearance.spacing.small / 2 - highlightRangeMode: ListView.StrictlyEnforceRange - preferredHighlightBegin: 0 - preferredHighlightEnd: count ? width - implicitHeight * 2 : 0 - currentIndex: count - 1 - - model: ScriptModel { - values: root.lock.pam.buffer - } - - delegate: StyledRect { - implicitWidth: implicitHeight - implicitHeight: passwordList.implicitHeight - - color: Colours.palette.m3onSurface - radius: Appearance.rounding.small / 2 - } - - add: Transition { - Anim { - property: "scale" - from: 0 - to: 1 - duration: Appearance.anim.durations.expressiveFastSpatial - easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial - } - } - - remove: Transition { - Anim { - property: "scale" - to: 0.5 - } - Anim { - property: "opacity" - to: 0 - } - } - - highlightFollowsCurrentItem: false - highlight: Item { - x: passwordList.currentItem?.x ?? 0 - - Behavior on x { - Anim {} - } - } - } - - StyledText { - anchors.centerIn: parent - - text: qsTr("Enter your password") - color: Colours.palette.m3outline - font.pointSize: Appearance.font.size.normal - font.family: Appearance.font.family.mono + InputField { + id: inputField - opacity: root.lock.pam.buffer ? 0 : 1 - - Behavior on opacity { - Anim {} - } - } + pam: root.lock.pam } StyledRect { diff --git a/modules/lock/InputField.qml b/modules/lock/InputField.qml new file mode 100644 index 0000000..9472d41 --- /dev/null +++ b/modules/lock/InputField.qml @@ -0,0 +1,159 @@ +pragma ComponentBehavior: Bound + +import qs.components +import qs.services +import qs.config +import Quickshell +import QtQuick +import QtQuick.Layouts + +Item { + id: root + + required property Pam pam + readonly property alias placeholder: placeholder + property string buffer + + Layout.fillWidth: true + Layout.fillHeight: true + + clip: true + + Connections { + target: root.pam + + function onBufferChanged(): void { + if (root.pam.buffer.length > root.buffer.length) { + charList.bindImWidth(); + } else if (root.pam.buffer.length === 0) { + charList.implicitWidth = charList.implicitWidth; + placeholder.animate = true; + } + + root.buffer = root.pam.buffer; + } + } + + StyledText { + id: placeholder + + anchors.centerIn: parent + + text: { + if (root.pam.active) + return qsTr("Loading..."); + if (root.pam.state === "error") + return qsTr("An error occured"); + if (root.pam.state === "max") + return qsTr("You have reached the maximum number of tries"); + if (root.pam.state === "fail") + return qsTr("Incorrect password"); + return qsTr("Enter your password"); + } + + animate: true + color: root.pam.active ? Colours.palette.m3secondary : root.pam.state ? Colours.palette.m3error : Colours.palette.m3outline + font.pointSize: Appearance.font.size.normal + font.family: Appearance.font.family.mono + + opacity: root.buffer ? 0 : 1 + + Behavior on opacity { + Anim {} + } + } + + ListView { + id: charList + + readonly property int fullWidth: count * (implicitHeight + spacing) - spacing + + function bindImWidth(): void { + imWidthBehavior.enabled = false; + implicitWidth = Qt.binding(() => fullWidth); + imWidthBehavior.enabled = true; + } + + anchors.centerIn: parent + anchors.horizontalCenterOffset: implicitWidth > root.width ? -(implicitWidth - root.width) / 2 : 0 + + implicitWidth: fullWidth + implicitHeight: Appearance.font.size.normal + + orientation: Qt.Horizontal + spacing: Appearance.spacing.small / 2 + interactive: false + + model: ScriptModel { + values: root.buffer.split("") + } + + delegate: StyledRect { + id: ch + + implicitWidth: implicitHeight + implicitHeight: charList.implicitHeight + + color: Colours.palette.m3onSurface + radius: Appearance.rounding.small / 2 + + opacity: 0 + scale: 0 + Component.onCompleted: { + opacity = 1; + scale = 1; + } + ListView.onRemove: removeAnim.start() + + SequentialAnimation { + id: removeAnim + + PropertyAction { + target: ch + property: "ListView.delayRemove" + value: true + } + ParallelAnimation { + Anim { + target: ch + property: "opacity" + to: 0 + } + Anim { + target: ch + property: "scale" + to: 0.5 + } + } + PropertyAction { + target: ch + property: "ListView.delayRemove" + value: false + } + } + + Behavior on opacity { + Anim {} + } + + Behavior on scale { + Anim { + duration: Appearance.anim.durations.expressiveFastSpatial + easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial + } + } + } + + Behavior on implicitWidth { + id: imWidthBehavior + + Anim {} + } + } + + component Anim: NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } +} diff --git a/modules/lock/Pam.qml b/modules/lock/Pam.qml index 7863603..6752d30 100644 --- a/modules/lock/Pam.qml +++ b/modules/lock/Pam.qml @@ -8,8 +8,9 @@ Scope { required property WlSessionLock lock - property string state: "none" - property string buffer: "" + readonly property bool active: passwd.active + property string state + property string buffer function handleKey(event: KeyEvent): void { if (passwd.active) @@ -59,6 +60,6 @@ Scope { id: stateReset interval: 4000 - onTriggered: root.state = "none" + onTriggered: root.state = "" } } |