lock: center password field + placeholder states
This commit is contained in:
parent
31cc51b6e9
commit
aa08957538
3 changed files with 172 additions and 81 deletions
|
|
@ -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
|
||||
InputField {
|
||||
id: inputField
|
||||
|
||||
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
|
||||
|
||||
opacity: root.lock.pam.buffer ? 0 : 1
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
pam: root.lock.pam
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
|
|
|
|||
159
modules/lock/InputField.qml
Normal file
159
modules/lock/InputField.qml
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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 = ""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue