aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/status/LockRow.qml
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules/status/LockRow.qml')
-rw-r--r--desktop/modules/status/LockRow.qml113
1 files changed, 113 insertions, 0 deletions
diff --git a/desktop/modules/status/LockRow.qml b/desktop/modules/status/LockRow.qml
new file mode 100644
index 0000000..c59c2f1
--- /dev/null
+++ b/desktop/modules/status/LockRow.qml
@@ -0,0 +1,113 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+import QtQuick
+import QtQuick.Controls
+import "../.."
+
+// A switch plus an optional minutes field. The switch is the auto-lock state:
+// on means the screen locks on idle as usual. Turning it off asserts the idle
+// inhibitor, which is the only thing that stops hypridle. A number in the field
+// makes that disable temporary and it re-enables itself; an empty field makes
+// it permanent. The singleton owns the state and the timer, so the effect
+// outlives this row, which dies with the drawer page.
+Item {
+ id: row
+
+ // A tick so the row repaints when a timed disable expires on its own.
+ property double now: Date.now()
+ Timer {
+ interval: 1000
+ running: true
+ repeat: true
+ onTriggered: row.now = Date.now()
+ }
+
+ readonly property bool lockOn: !Status.nolock
+ readonly property bool timed: Status.nolockUntil > row.now
+
+ implicitHeight: Math.max(texts.implicitHeight, controls.implicitHeight) + 16
+
+ function hhmm(ts) {
+ const d = new Date(ts);
+ return ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2);
+ }
+
+ function apply(lockOn) {
+ if (lockOn) {
+ Status.setMode("nolock", false);
+ } else {
+ const n = parseInt(minutes.text, 10);
+ Status.disableLockFor(isNaN(n) || n < 1 ? 0 : n);
+ }
+ }
+
+ Column {
+ id: texts
+ anchors {
+ left: parent.left
+ right: controls.left
+ rightMargin: 12
+ verticalCenter: parent.verticalCenter
+ }
+ spacing: 2
+
+ Text {
+ text: "Screen lock"
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true }
+ color: Theme.text
+ }
+
+ Text {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ text: row.lockOn ? "The screen locks automatically when the session is idle."
+ : row.timed ? "Auto-lock is off until " + row.hhmm(Status.nolockUntil) + "."
+ : "Auto-lock stays off until you turn it back on."
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
+ color: Theme.subtext
+ }
+ }
+
+ Row {
+ id: controls
+ anchors { right: parent.right; verticalCenter: parent.verticalCenter }
+ spacing: 8
+
+ TextField {
+ id: minutes
+ width: 48
+ height: 28
+ placeholderText: "min"
+ horizontalAlignment: TextInput.AlignHCenter
+ color: Theme.text
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
+ background: Rectangle {
+ radius: 6
+ color: Qt.alpha(Theme.surface, 0.9)
+ border.width: 1
+ border.color: Qt.alpha(Theme.text, 0.15)
+ }
+ validator: IntValidator { bottom: 1; top: 1440 }
+ }
+
+ Switch {
+ id: sw
+ checked: row.lockOn
+ onToggled: row.apply(!row.lockOn)
+ }
+ }
+
+ // The shared Switch's click handler writes `checked` directly, which drops
+ // the declarative binding above. Resync on any state change so the timer,
+ // statusctl or presentation mode moves the switch back into agreement.
+ onLockOnChanged: sw.checked = row.lockOn
+}