summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/LockConfig.qml19
-rw-r--r--modules/lock/Center.qml214
-rw-r--r--modules/lock/Content.qml97
-rw-r--r--modules/lock/Lock.qml7
-rw-r--r--modules/lock/LockSurface.qml1
-rw-r--r--modules/lock/Pam.qml50
6 files changed, 303 insertions, 85 deletions
diff --git a/config/LockConfig.qml b/config/LockConfig.qml
index 0a62493..a64dd74 100644
--- a/config/LockConfig.qml
+++ b/config/LockConfig.qml
@@ -5,23 +5,6 @@ JsonObject {
property Sizes sizes: Sizes {}
component Sizes: JsonObject {
- property int clockWidth: 800
- 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
+ property int centerWidth: 600
}
}
diff --git a/modules/lock/Center.qml b/modules/lock/Center.qml
new file mode 100644
index 0000000..9610da2
--- /dev/null
+++ b/modules/lock/Center.qml
@@ -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
+ }
+}
diff --git a/modules/lock/Content.qml b/modules/lock/Content.qml
index 15e1425..43cf871 100644
--- a/modules/lock/Content.qml
+++ b/modules/lock/Content.qml
@@ -1,14 +1,10 @@
-pragma ComponentBehavior: Bound
-
import qs.components
-import qs.components.images
import qs.services
import qs.config
-import qs.utils
import QtQuick
import QtQuick.Layouts
-GridLayout {
+RowLayout {
id: root
required property var lock
@@ -16,85 +12,52 @@ GridLayout {
anchors.fill: parent
anchors.margins: Appearance.padding.large
- rowSpacing: Appearance.spacing.large
- columnSpacing: Appearance.spacing.large
-
- rows: 2
- columns: 3
+ spacing: Appearance.spacing.large
- StyledRect {
- Layout.row: 0
- Layout.column: 0
+ ColumnLayout {
Layout.fillWidth: true
- Layout.fillHeight: true
-
- radius: Appearance.rounding.small
- color: Colours.tPalette.m3surfaceContainer
- }
-
- StyledRect {
- Layout.row: 1
- Layout.column: 0
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- radius: Appearance.rounding.small
- color: Colours.tPalette.m3surfaceContainer
- }
-
- StyledClippingRect {
- Layout.row: 0
- Layout.column: 1
- Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ spacing: Appearance.spacing.normal
- implicitWidth: Config.lock.sizes.faceSize
- implicitHeight: Config.lock.sizes.faceSize
+ StyledRect {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
- 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)
+ radius: Appearance.rounding.small
+ color: Colours.tPalette.m3surfaceContainer
}
- CachingImage {
- id: pfp
+ StyledRect {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
- anchors.fill: parent
- path: `${Paths.stringify(Paths.home)}/.face`
+ radius: Appearance.rounding.small
+ color: Colours.tPalette.m3surfaceContainer
}
}
- Input {
- Layout.row: 1
- Layout.column: 1
-
+ Center {
lock: root.lock
}
- StyledRect {
- Layout.row: 0
- Layout.column: 2
+ ColumnLayout {
Layout.fillWidth: true
- Layout.fillHeight: true
+ spacing: Appearance.spacing.normal
- radius: Appearance.rounding.small
- color: Colours.tPalette.m3surfaceContainer
- }
+ StyledRect {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
- StyledRect {
- Layout.row: 1
- Layout.column: 2
- Layout.fillWidth: true
- Layout.fillHeight: true
+ radius: Appearance.rounding.small
+ color: Colours.tPalette.m3surfaceContainer
+ }
- radius: Appearance.rounding.small
- color: Colours.tPalette.m3surfaceContainer
+ StyledRect {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ radius: Appearance.rounding.small
+ color: Colours.tPalette.m3surfaceContainer
+ }
}
component Anim: NumberAnimation {
diff --git a/modules/lock/Lock.qml b/modules/lock/Lock.qml
index 0017086..fc0bff8 100644
--- a/modules/lock/Lock.qml
+++ b/modules/lock/Lock.qml
@@ -14,9 +14,16 @@ Scope {
LockSurface {
lock: lock
+ pam: pam
}
}
+ Pam {
+ id: pam
+
+ lock: lock
+ }
+
CustomShortcut {
name: "lock"
description: "Lock the current session"
diff --git a/modules/lock/LockSurface.qml b/modules/lock/LockSurface.qml
index 3b6b86c..8dec866 100644
--- a/modules/lock/LockSurface.qml
+++ b/modules/lock/LockSurface.qml
@@ -12,6 +12,7 @@ WlSessionLockSurface {
id: root
required property WlSessionLock lock
+ required property Pam pam
property bool locked
diff --git a/modules/lock/Pam.qml b/modules/lock/Pam.qml
new file mode 100644
index 0000000..44e8671
--- /dev/null
+++ b/modules/lock/Pam.qml
@@ -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";
+ }
+}