diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-13 09:53:30 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-13 09:53:30 +0200 |
| commit | 7512e5d631d6580c0dfe3558d9f7429729e397c8 (patch) | |
| tree | 49bc6a1fed5bde71c1d67225117bc69e53f6f3e6 /desktop/Prefs.qml | |
| parent | 2c4b0de14d3ec8d6410a0fbf7d32501b66d7703b (diff) | |
| download | quickshell-7512e5d631d6580c0dfe3558d9f7429729e397c8.tar.gz quickshell-7512e5d631d6580c0dfe3558d9f7429729e397c8.zip | |
feat(desktop): preferences file under the state home
The first preference is the controls panel's visible tiles. The file is
written only on a change and keeps keys it does not know, so a broken or
newer file is never clobbered by a shell that only read it. State home
rather than the runtime dir because it must survive a reboot, rather
than ~/.config because the shell writes it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/Prefs.qml')
| -rw-r--r-- | desktop/Prefs.qml | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/desktop/Prefs.qml b/desktop/Prefs.qml new file mode 100644 index 0000000..dd2fdfc --- /dev/null +++ b/desktop/Prefs.qml @@ -0,0 +1,69 @@ +// 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. + +pragma Singleton + +import Quickshell +import Quickshell.Io +import QtQuick +import "island/Controls.js" as Controls + +// Preferences that must survive a reboot, in one JSON file under the state +// home. Only the shell writes it, which is why it is not in ~/.config. +// +// Nothing is written until the user changes something. A file that fails to +// parse reads as the defaults and stays on disk as it is, so a hand edit +// with a typo is not replaced by a panel that was merely opened. +Singleton { + id: root + + readonly property string path: + (Quickshell.env("XDG_STATE_HOME") || Quickshell.env("HOME") + "/.local/state") + + "/quickshell/desktop.json" + + // Visible control tiles, in display order. + property var controls: Controls.defaults() + + // The whole parsed object, so a write keeps keys this version does not + // know about. + property var data: ({}) + + function setControls(list) { + root.controls = Controls.normalize(list); + const out = Object.assign({}, root.data, { controls: root.controls }); + root.data = out; + file.setText(JSON.stringify(out, null, 2) + "\n"); + } + + function reparse() { + let parsed = {}; + try { + const v = JSON.parse(file.text()); + if (v && typeof v === "object" && !Array.isArray(v)) parsed = v; + } catch (e) {} + root.data = parsed; + const next = "controls" in parsed ? Controls.normalize(parsed.controls) : Controls.defaults(); + // The watch also fires on our own write; compare so it is a no-op. + if (JSON.stringify(next) !== JSON.stringify(root.controls)) root.controls = next; + } + + FileView { + id: file + path: root.path + atomicWrites: true + watchChanges: true + printErrors: false + onFileChanged: reload() + onLoaded: root.reparse() + // Missing file: the defaults, and nothing written. + onLoadFailed: { root.data = {}; root.controls = Controls.defaults(); } + } +} |
