From 412dec827b5d87c4138491faf49a0babb229f7e2 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 30 Oct 2026 17:34:33 +0100 Subject: Drop breaktimer and the archived AI apps breaktimer is parked and imggen and fanfictioner are archived and uninstalled, so the shell was reading files nothing writes and offering buttons that call commands that no longer exist. Status: remove the bt* properties, the file watchers behind them, the verb runner and the presentation-mode pause/resume. The status page loses BreakRow and the tile falls back to "All clear". AI: remove the imggen and fanfictioner rows from ai-state.sh, their labels and controls, and the pid-based fanfictioner stop. The sd-cli engine row stays, since the wallpaper upscaler uses sd-cli too. Co-Authored-By: Claude Opus 5.5 --- shared/Notify.qml | 5 ++- shared/Status.qml | 97 +------------------------------------------------------ 2 files changed, 3 insertions(+), 99 deletions(-) (limited to 'shared') diff --git a/shared/Notify.qml b/shared/Notify.qml index a85ed6a..836dc21 100644 --- a/shared/Notify.qml +++ b/shared/Notify.qml @@ -42,9 +42,8 @@ Singleton { // Read from the status registry's own file rather than from the Status // singleton. The renderers only read DND; referencing Status here would - // instantiate it, and its onPresentationChanged writes status.dnd and - // shells out to breaktimer.sh, side effects a read-only consumer must not - // trigger. The file is the interface, so reading it directly is the same + // instantiate it, and its onPresentationChanged writes status.dnd, a side + // effect a read-only consumer must not trigger. The file is the interface, so reading it directly is the same // value with none of the write side. property bool dnd: false diff --git a/shared/Status.qml b/shared/Status.qml index 523ea7d..f32cd35 100644 --- a/shared/Status.qml +++ b/shared/Status.qml @@ -44,23 +44,6 @@ Singleton { // drawer's view of it. readonly property bool quiet: quietFile.value - // Breaktimer, read only. The daemon publishes these three files and owns - // them; the shell calls verbs and never writes them, because the daemon - // loop rewrites state and phase on every transition. - // - // A stopped daemon is read from the state file rather than probed: both - // paths that end it, stop_daemon and the cleanup trap, write "stopped" - // there. A daemon lost to SIGKILL leaves a stale "running" and the drawer - // shows a frozen countdown, which is a visible wrong answer the start - // button resolves. That is cheaper than a liveness probe per repaint. - readonly property string btState: btStateFile.value - readonly property string btPhase: btPhaseFile.value - readonly property int btRemain: btRemainFile.value - - readonly property bool btRunning: root.btState === "running" - || root.btState === "paused" - readonly property bool btPaused: root.btState === "paused" - readonly property int activeCount: (root.dnd ? 1 : 0) + (root.presentation ? 1 : 0) + (root.nolock ? 1 : 0) + (root.quiet ? 1 : 0) @@ -144,49 +127,17 @@ Singleton { root.setMode("dnd", true); root.setMode("nolock", true); root.setMode("quiet", true); - // pause/resume write the state file whether or not a daemon - // runs, so send the verb only when one exists. - if (root.btRunning) root.runBreaktimer("pause"); } else { root.setMode("dnd", root.dndBeforePresentation); root.setMode("nolock", root.nolockBeforePresentation); root.setMode("quiet", root.quietBeforePresentation); - if (root.btRunning) root.runBreaktimer("resume"); - } - } - - function runBreaktimer(verb) { - breakProc.command = ["breaktimer.sh", verb]; - breakProc.running = false; - breakProc.running = true; - } - - // Seconds as m:ss. The daemon rewrites the remaining seconds every five - // seconds, its tick, so this counts down in five second steps and does - // not interpolate: a local one second timer would be a second clock - // drifting against the first, correcting itself with a visible jump, and - // it would keep ticking while the daemon is frozen outside the work - // window or paused. - function btCountdown() { - const s = Math.max(0, root.btRemain); - return Math.floor(s / 60) + ":" + String(s % 60).padStart(2, "0"); - } - - // breaktimer owns its own state file; this only calls its verbs. Two - // writers on that file would race with its daemon loop, which rewrites it - // on every phase change. - Process { - id: breakProc - onExited: code => { - if (code !== 0) - console.warn("status: breaktimer.sh " + breakProc.command[1] + " exited " + code); } } // --- game detection --------------------------------------------------- // // A game is a fullscreen app that already holds the screen, and the idle - // lock, DND and breaktimer are all unwanted while it runs, so presentation + // lock and DND are both unwanted while it runs, so presentation // is set automatically. This machine's games come from Steam and launch // either under gamescope or directly, and the DuckStation and PCSX2 emulators // run standalone, so all four are tested and any one is enough. @@ -269,56 +220,10 @@ Singleton { onLoadFailed: mf.value = false } - // A daemon file holding a word. Same watch and same missing-file rule as - // ModeFile, without a write path: this side only reads. - component WordFile: FileView { - id: wf - - property string value: "stopped" - - function reparse() { - const t = wf.text().trim(); - if (t !== wf.value) wf.value = t; - } - - watchChanges: true - printErrors: false - onFileChanged: wf.reload() - onLoaded: wf.reparse() - // No file means no daemon, which is the stopped state, not an error. - onLoadFailed: wf.value = "stopped" - } - - // The remaining seconds. Validated as an integer rather than trusted: - // the file is written every tick and a read can catch it mid-write, and - // an empty string coerces to 0 silently while NaN would propagate into - // the countdown as "NaN:aN". - component SecondsFile: FileView { - id: sf - - property int value: 0 - - function reparse() { - const n = parseInt(sf.text().trim(), 10); - const v = (isNaN(n) || n < 0) ? 0 : n; - if (v !== sf.value) sf.value = v; - } - - watchChanges: true - printErrors: false - onFileChanged: sf.reload() - onLoaded: sf.reparse() - onLoadFailed: sf.value = 0 - } - ModeFile { id: dndFile; path: root.dir + "/status.dnd" } ModeFile { id: presFile; path: root.dir + "/status.presentation" } ModeFile { id: nolockFile; path: root.dir + "/status.nolock" } ModeFile { id: quietFile; path: root.dir + "/status.quiet" } // Written only by the game detector above, never by statusctl. ModeFile { id: gamingFile; path: root.dir + "/status.gaming" } - - WordFile { id: btStateFile; path: root.dir + "/breaktimer.state" } - WordFile { id: btPhaseFile; path: root.dir + "/breaktimer.phase" } - SecondsFile { id: btRemainFile; path: root.dir + "/breaktimer.remain" } } -- cgit v1.2.3