// Copyright (C) 2026 Danilo M. // // 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 ".." import "ListFile.js" as LF // The wallpapers the companion blushes at, and what wallp has on each // monitor. The companion reads both; the wallpaper picker toggles entries. // What is on each monitor is read from wallp's own files here rather than // through the appearance module's Wallpapers, which scans every wallpaper // on creation, and the companion runs all session. Singleton { id: root readonly property string home: Quickshell.env("HOME") readonly property string defaultPath: (Quickshell.env("XDG_CONFIG_HOME") || root.home + "/.config") + "/keystone/companion-blush.txt" readonly property string path: Prefs.companionBlushFile !== "" ? Prefs.companionBlushFile.replace(/^~(?=\/|$)/, root.home) : root.defaultPath property string listText: "" readonly property var paths: LF.parse(root.listText) function listed(p) { return p !== "" && root.paths.indexOf(p) >= 0; } // The wallpaper on a monitor, by connector name; "" for one wallp does // not set. property var outputs: ({}) property string wallH: "" property string wallV: "" function on(monitor) { const w = root.outputs[monitor]; return w === "H" ? root.wallH : w === "V" ? root.wallV : ""; } // ponytail: a list file created by hand after start may not be watched // until a restart (the watch is on a path that did not exist); the // heart writes through the process below, which sets listText itself. FileView { path: root.path watchChanges: true printErrors: false onFileChanged: reload() onLoaded: root.listText = text() onLoadFailed: root.listText = "" } FileView { path: root.home + "/.config/wallp/wallp.conf" watchChanges: true printErrors: false onFileChanged: reload() onLoaded: root.outputs = LF.outputs(text()) } FileView { path: root.home + "/.config/wallp/wall_h" watchChanges: true printErrors: false onFileChanged: reload() onLoaded: root.wallH = text().trim() } FileView { path: root.home + "/.config/wallp/wall_v" watchChanges: true printErrors: false onFileChanged: reload() onLoaded: root.wallV = text().trim() } // Through cat rather than FileView.setText, because the list can become // empty and setText("") on a path the view has not loaded writes no // file (AGENTS.md). function toggle(p) { writer.data = LF.toggle(root.listText, p); root.listText = writer.data; writer.command = ["sh", "-c", 'mkdir -p "$(dirname "$1")" && cat > "$1"', "sh", root.path]; writer.stdinEnabled = true; writer.running = false; writer.running = true; } Process { id: writer property string data: "" onStarted: { writer.write(writer.data); writer.stdinEnabled = false; } onExited: code => { if (code !== 0) console.warn("Admired: writing", root.path, "failed"); } } }