pragma Singleton // Generated lock-screen state. Visual preferences are coalesced into one // helper invocation, while the last valid status remains visible if a helper // response is malformed. import Quickshell import Quickshell.Io import QtQuick import qs.config Singleton { id: root readonly property string helperPath: Quickshell.shellDir + "/scripts/panama-lock" property bool generated: false property string path: "" property bool fallback: true property string lastError: "" property string watchedSignature: "" property bool regenerateAfterCurrent: false readonly property bool busy: generateProcess.running || statusProcess.running function preferenceSignature(): string { DesktopPreferences.revision; return JSON.stringify([ DesktopPreferences.get("lockBackgroundMode"), DesktopPreferences.get("lockBlurLevel"), DesktopPreferences.get("lockShowClock"), DesktopPreferences.get("lockShowDate"), DesktopPreferences.get("lockShowUser"), DesktopPreferences.get("lockFadeOnEmpty"), DesktopPreferences.get("use24Hour"), DesktopPreferences.get("colorScheme"), DesktopPreferences.get("wallpaperPath"), DesktopPreferences.get("wallpaperMode"), DesktopPreferences.get("wallpaperPerMonitor") ]); } function applyStatus(text: string): void { try { const state = JSON.parse(text); if (!state || typeof state.generated !== "boolean" || typeof state.path !== "string" || state.path.length === 0) throw new Error("invalid lock status"); root.generated = state.generated; root.path = state.path; root.fallback = state.fallback === true; root.lastError = typeof state.error === "string" ? state.error : ""; } catch (error) { root.lastError = "The lock-screen configuration could not be read."; } } function refresh(): void { if (!statusProcess.running) statusProcess.exec([root.helperPath, "status"]); } function regenerate(): void { if (generateProcess.running) { root.regenerateAfterCurrent = true; return; } generateProcess.exec([root.helperPath, "generate"]); } Process { id: statusProcess property bool parsed: false onRunningChanged: { if (running) parsed = false; } stdout: StdioCollector { onStreamFinished: { statusProcess.parsed = true; root.applyStatus(this.text); } } onExited: (exitCode, exitStatus) => { if (exitCode !== 0 && !statusProcess.parsed) root.lastError = "The lock-screen configuration could not be read."; } } Process { id: generateProcess onExited: (exitCode, exitStatus) => { if (exitCode !== 0) root.lastError = "The lock-screen configuration could not be generated."; root.refresh(); if (root.regenerateAfterCurrent) { root.regenerateAfterCurrent = false; regenerateTimer.restart(); } } } Connections { target: DesktopPreferences function onRevisionChanged(): void { const signature = root.preferenceSignature(); if (signature === root.watchedSignature) return; root.watchedSignature = signature; regenerateTimer.restart(); } } Timer { id: regenerateTimer interval: 250 onTriggered: root.regenerate() } Component.onCompleted: { root.watchedSignature = root.preferenceSignature(); root.refresh(); regenerateTimer.restart(); } }