lock: input field + separate pam
This commit is contained in:
parent
ba1c6fda43
commit
56ca1632c5
6 changed files with 303 additions and 85 deletions
|
|
@ -5,23 +5,6 @@ JsonObject {
|
||||||
property Sizes sizes: Sizes {}
|
property Sizes sizes: Sizes {}
|
||||||
|
|
||||||
component Sizes: JsonObject {
|
component Sizes: JsonObject {
|
||||||
property int clockWidth: 800
|
property int centerWidth: 600
|
||||||
property int clockHeight: 200
|
|
||||||
property int inputWidth: 600
|
|
||||||
property int inputHeight: 200
|
|
||||||
property int faceSize: 200
|
|
||||||
property int weatherWidth: 400
|
|
||||||
property int weatherHeight: 100
|
|
||||||
property int mediaWidth: 600
|
|
||||||
property int mediaWidthSmall: 450
|
|
||||||
property int mediaHeight: 170
|
|
||||||
property int mediaHeightSmall: 150
|
|
||||||
property int mediaCoverSize: 150
|
|
||||||
property int mediaCoverSizeSmall: 120
|
|
||||||
property int mediaCoverBorder: 3
|
|
||||||
property int largeScreenWidth: 2560
|
|
||||||
property int smallScreenWidth: 1080
|
|
||||||
property int buttonsWidth: 400
|
|
||||||
property int buttonsWidthSmall: 300
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
214
modules/lock/Center.qml
Normal file
214
modules/lock/Center.qml
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import qs.components
|
||||||
|
import qs.components.images
|
||||||
|
import qs.services
|
||||||
|
import qs.config
|
||||||
|
import qs.utils
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var lock
|
||||||
|
readonly property list<string> timeComponents: Time.format(Config.services.useTwelveHourClock ? "hh:mm:A" : "hh:mm").split(":")
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.minimumWidth: Config.lock.sizes.centerWidth
|
||||||
|
|
||||||
|
spacing: Appearance.spacing.large * 2
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.bottomMargin: Appearance.spacing.large
|
||||||
|
spacing: Appearance.spacing.small
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: root.timeComponents[0]
|
||||||
|
color: Colours.palette.m3secondary
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: ":"
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: root.timeComponents[1]
|
||||||
|
color: Colours.palette.m3secondary
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
Layout.leftMargin: Appearance.spacing.normal
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
asynchronous: true
|
||||||
|
active: Config.services.useTwelveHourClock
|
||||||
|
visible: active
|
||||||
|
|
||||||
|
sourceComponent: StyledText {
|
||||||
|
text: root.timeComponents[2] ?? ""
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge * 2
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledClippingRect {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
implicitWidth: Config.lock.sizes.centerWidth / 2
|
||||||
|
implicitHeight: Config.lock.sizes.centerWidth / 2
|
||||||
|
|
||||||
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
text: "person"
|
||||||
|
fill: 1
|
||||||
|
grade: 200
|
||||||
|
font.pointSize: Math.floor(Config.lock.sizes.centerWidth / 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
CachingImage {
|
||||||
|
id: pfp
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
path: `${Paths.stringify(Paths.home)}/.face`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
implicitWidth: Config.lock.sizes.centerWidth * 0.8
|
||||||
|
implicitHeight: input.implicitHeight + Appearance.padding.small * 2
|
||||||
|
|
||||||
|
color: Colours.palette.m3surfaceContainer
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
focus: true
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if (!activeFocus)
|
||||||
|
forceActiveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: event => root.lock.pam.handleKey(event)
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: input
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.small
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
Layout.leftMargin: Appearance.padding.smaller
|
||||||
|
text: "lock"
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: passwordList
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: Appearance.font.size.normal
|
||||||
|
|
||||||
|
orientation: Qt.Horizontal
|
||||||
|
clip: true
|
||||||
|
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 {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
implicitWidth: implicitHeight
|
||||||
|
implicitHeight: enterIcon.implicitHeight + Appearance.padding.small * 2
|
||||||
|
|
||||||
|
color: root.lock.pam.buffer ? Colours.palette.m3primary : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.lock.pam.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: enterIcon
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "arrow_forward"
|
||||||
|
color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Anim: NumberAnimation {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.images
|
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
import qs.utils
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
GridLayout {
|
RowLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property var lock
|
required property var lock
|
||||||
|
|
@ -16,15 +12,13 @@ GridLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Appearance.padding.large
|
anchors.margins: Appearance.padding.large
|
||||||
|
|
||||||
rowSpacing: Appearance.spacing.large
|
spacing: Appearance.spacing.large
|
||||||
columnSpacing: Appearance.spacing.large
|
|
||||||
|
|
||||||
rows: 2
|
ColumnLayout {
|
||||||
columns: 3
|
Layout.fillWidth: true
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
Layout.row: 0
|
|
||||||
Layout.column: 0
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
|
@ -33,53 +27,23 @@ GridLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
Layout.row: 1
|
|
||||||
Layout.column: 0
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Appearance.rounding.small
|
radius: Appearance.rounding.small
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledClippingRect {
|
|
||||||
Layout.row: 0
|
|
||||||
Layout.column: 1
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
|
|
||||||
implicitWidth: Config.lock.sizes.faceSize
|
|
||||||
implicitHeight: Config.lock.sizes.faceSize
|
|
||||||
|
|
||||||
radius: Appearance.rounding.large
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
text: "person"
|
|
||||||
fill: 1
|
|
||||||
grade: 200
|
|
||||||
font.pointSize: Math.floor(Config.lock.sizes.faceSize / 2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CachingImage {
|
Center {
|
||||||
id: pfp
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
path: `${Paths.stringify(Paths.home)}/.face`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Input {
|
|
||||||
Layout.row: 1
|
|
||||||
Layout.column: 1
|
|
||||||
|
|
||||||
lock: root.lock
|
lock: root.lock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
Layout.row: 0
|
|
||||||
Layout.column: 2
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
|
@ -88,14 +52,13 @@ GridLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
Layout.row: 1
|
|
||||||
Layout.column: 2
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Appearance.rounding.small
|
radius: Appearance.rounding.small
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component Anim: NumberAnimation {
|
component Anim: NumberAnimation {
|
||||||
duration: Appearance.anim.durations.normal
|
duration: Appearance.anim.durations.normal
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,16 @@ Scope {
|
||||||
|
|
||||||
LockSurface {
|
LockSurface {
|
||||||
lock: lock
|
lock: lock
|
||||||
|
pam: pam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pam {
|
||||||
|
id: pam
|
||||||
|
|
||||||
|
lock: lock
|
||||||
|
}
|
||||||
|
|
||||||
CustomShortcut {
|
CustomShortcut {
|
||||||
name: "lock"
|
name: "lock"
|
||||||
description: "Lock the current session"
|
description: "Lock the current session"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ WlSessionLockSurface {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property WlSessionLock lock
|
required property WlSessionLock lock
|
||||||
|
required property Pam pam
|
||||||
|
|
||||||
property bool locked
|
property bool locked
|
||||||
|
|
||||||
|
|
|
||||||
50
modules/lock/Pam.qml
Normal file
50
modules/lock/Pam.qml
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Services.Pam
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
PamContext {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property WlSessionLock lock
|
||||||
|
|
||||||
|
property string state: "none"
|
||||||
|
property string buffer: ""
|
||||||
|
|
||||||
|
function handleKey(event: KeyEvent): void {
|
||||||
|
if (active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
|
||||||
|
start();
|
||||||
|
} else if (event.key === Qt.Key_Backspace) {
|
||||||
|
if (event.modifiers & Qt.ControlModifier) {
|
||||||
|
buffer = "";
|
||||||
|
} else {
|
||||||
|
buffer = buffer.slice(0, -1);
|
||||||
|
}
|
||||||
|
} else if (" abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?".includes(event.text.toLowerCase())) {
|
||||||
|
// No illegal characters (you are insane if you use unicode in your password)
|
||||||
|
buffer += event.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onResponseRequiredChanged: {
|
||||||
|
if (!responseRequired)
|
||||||
|
return;
|
||||||
|
|
||||||
|
respond(buffer);
|
||||||
|
buffer = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleted: res => {
|
||||||
|
if (res === PamResult.Success)
|
||||||
|
return lock.unlock();
|
||||||
|
|
||||||
|
if (res === PamResult.Error)
|
||||||
|
state = "error";
|
||||||
|
else if (res === PamResult.MaxTries)
|
||||||
|
state = "max";
|
||||||
|
else if (res === PamResult.Failed)
|
||||||
|
state = "fail";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue