mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 19:27:03 +01:00
Put the screen-locker status back on the i3 bar
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
The GTK tray icon was the only status surface, and it had been commented out of ~/.config/i3/config since 2026-08-21. With nothing in the bar, the locker miscounted the week for a fortnight and the machine never said so. Shows "<count>/<minimum> · <gaming budget>", read from the local status API (screen-locker-web.service on 127.0.0.1:8770); clicking opens the full UI. Three things it deliberately will not do quietly: - a dead status server renders "status server down" in red, or the last known value marked (stale) in orange -- never a blank block. That server is what the gaming budget reads, so its absence costs two hours; - a disarmed or unscheduled timer overrides the compliance colour entirely and shows "DISARMED" in red. A locker that cannot fire is the worse problem and the one that hides; - clicking only opens the UI. There is no bar action that can clear a lock. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fcwu78wk17FWMHbbfbyicc
This commit is contained in:
parent
334c0cd904
commit
2713ae9d66
@ -0,0 +1,40 @@
|
||||
{
|
||||
"intent": "Put the screen-locker status back on the i3 bar, so a miscounting or disarmed locker is visible without being asked. The GTK tray icon it replaces had been commented out of ~/.config/i3/config since 2026-08-21, and in that window the locker counted one workout twice, believed the week met at 5/5 when the real total was 3, and skipped enforcement for two ISO weeks with nothing on the machine saying so.",
|
||||
"scope": [
|
||||
"linux_configuration/i3blocks/screen_locker.sh (new block script)",
|
||||
"linux_configuration/i3blocks/config (register the block before shutdown_countdown)",
|
||||
"Non-goal: the block never mutates locker state; clicking only opens the read-only UI",
|
||||
"Depends on screen-locker-web.service (127.0.0.1:8770) from the screen-locker repo"
|
||||
],
|
||||
"changes": [
|
||||
"New block renders '<count>/<minimum> · <gaming budget>' from GET /api/status, coloured by compliance_state (green ok / yellow warn / red lock).",
|
||||
"Arming from GET /api/health overrides the compliance colour: a timer that is disabled or has no next trigger shows 'DISARMED' in red, because a locker that cannot fire is the worse failure and the one that hides.",
|
||||
"A dead status server renders the last known value marked '(stale)' in orange, or 'status server down' in red when there is no cache — never a blank block.",
|
||||
"Missing curl/jq degrades to a visible marker rather than an empty block or a bash error."
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "~/.config/i3blocks/screen_locker.sh",
|
||||
"result": "pass",
|
||||
"evidence": "Prints '💪 3/5 · 6h' / '💪 3/5' / '#F1FA8C' — 3/5 is the corrected weekly count, 6h the cut gaming budget for a day with no workout."
|
||||
},
|
||||
{
|
||||
"command": "systemctl --user stop screen-locker-web.service && ~/.config/i3blocks/screen_locker.sh",
|
||||
"result": "pass",
|
||||
"evidence": "With cache: '💪 3/5 · 6h (stale)' in orange. After rm of the cache: '💪 status server down' in red. Restored to '💪 3/5 · 6h' once the unit was started again."
|
||||
},
|
||||
{
|
||||
"command": "i3-msg reload && scrot",
|
||||
"result": "pass",
|
||||
"evidence": "Block visible in the HDMI-0 bar between PC:warn and the 23:00 shutdown countdown, rendering '💪 3/5 · 6h' in yellow. i3blocks does not re-read its config on i3-msg reload alone; the running process had to exit first."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"Two curl calls every 30s. Both are loopback with --max-time 2, so a hung server delays the block by at most 4s rather than wedging the bar.",
|
||||
"The block reports the gaming budget using its own 8h/6h constants. If steam-backlog-enforcer's configured values change, this display drifts from the enforcer until updated."
|
||||
],
|
||||
"rollback": [
|
||||
"Remove the [screen_locker] stanza from linux_configuration/i3blocks/config, delete linux_configuration/i3blocks/screen_locker.sh and the ~/.config/i3blocks symlink, then i3-msg reload and kill the running i3blocks so it re-reads the config.",
|
||||
"After rollback, confirm the bar still renders the remaining blocks (cpu, gpu, memory, disk, volume, ethernet, claude_usage, pc_startup, shutdown_countdown, time)."
|
||||
]
|
||||
}
|
||||
@ -51,6 +51,10 @@ interval=30
|
||||
color=#FFFFFF
|
||||
|
||||
|
||||
[screen_locker]
|
||||
command=~/.config/i3blocks/screen_locker.sh
|
||||
interval=30
|
||||
|
||||
[shutdown_countdown]
|
||||
command=~/.config/i3blocks/shutdown_countdown.sh
|
||||
interval=60
|
||||
|
||||
84
linux_configuration/i3blocks/screen_locker.sh
Executable file
84
linux_configuration/i3blocks/screen_locker.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Screen-locker status for i3blocks.
|
||||
#
|
||||
# Replaces the GTK tray icon that sat commented out in ~/.config/i3/config from
|
||||
# 2026-08-21, during which the locker miscounted the week and nothing on the
|
||||
# machine said so. The point of this block is that a broken or disarmed locker
|
||||
# is visible without being asked: it is never blank and never silently green.
|
||||
#
|
||||
# Reads the local status API (screen-locker-web.service). Click opens the UI.
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly API='http://127.0.0.1:8770/api/status'
|
||||
readonly HEALTH='http://127.0.0.1:8770/api/health'
|
||||
readonly UI='http://127.0.0.1:8770/'
|
||||
readonly CACHE="${XDG_RUNTIME_DIR:-/tmp}/i3blocks-screen-locker.cache"
|
||||
|
||||
# Dracula-ish palette, matching the other blocks in this bar.
|
||||
readonly RED='#FF5555'
|
||||
readonly YELLOW='#F1FA8C'
|
||||
readonly GREEN='#50FA7B'
|
||||
readonly ORANGE='#FFB86C'
|
||||
|
||||
emit() {
|
||||
# full_text, short_text, color — the three lines i3blocks reads.
|
||||
printf '%s\n%s\n%s\n' "$1" "$2" "$3"
|
||||
}
|
||||
|
||||
# A click opens the web UI rather than doing anything destructive; there is no
|
||||
# action here that could clear a lock.
|
||||
if [[ ${BLOCK_BUTTON:-0} -ne 0 ]]; then
|
||||
xdg-open "$UI" >/dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1 || ! command -v jq >/dev/null 2>&1; then
|
||||
emit '💪 no curl/jq' '💪 ?' "$ORANGE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
status_json=$(curl -fsS --max-time 2 "$API" 2>/dev/null || true)
|
||||
if [[ -z $status_json ]]; then
|
||||
# The server being down is itself news: it is what the gaming budget reads,
|
||||
# and it failing closed costs two hours. Say so instead of showing nothing.
|
||||
if [[ -r $CACHE ]]; then
|
||||
emit "$(cat "$CACHE") (stale)" '💪 ?' "$ORANGE"
|
||||
else
|
||||
emit '💪 status server down' '💪 ?' "$RED"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
count=$(jq -r '.snapshot.week.counted_count' <<<"$status_json")
|
||||
minimum=$(jq -r '.snapshot.week.minimum' <<<"$status_json")
|
||||
state=$(jq -r '.compliance_state' <<<"$status_json")
|
||||
workout_today=$(jq -r '.gaming.workout_today' <<<"$status_json")
|
||||
|
||||
if [[ $workout_today == 'true' ]]; then
|
||||
hours='8h'
|
||||
else
|
||||
hours='6h'
|
||||
fi
|
||||
|
||||
health_json=$(curl -fsS --max-time 2 "$HEALTH" 2>/dev/null || true)
|
||||
armed=$(jq -r '.armed' <<<"${health_json:-{\}}" 2>/dev/null || echo 'unknown')
|
||||
|
||||
text="💪 ${count}/${minimum} · ${hours}"
|
||||
case $state in
|
||||
lock) color=$RED ;;
|
||||
warn) color=$YELLOW ;;
|
||||
*) color=$GREEN ;;
|
||||
esac
|
||||
|
||||
# Arming beats compliance: a locker that cannot fire is the worse problem, and
|
||||
# it is the one that hides. Never render it as a green tick.
|
||||
if [[ $armed != 'true' ]]; then
|
||||
text="$text ⚠ DISARMED"
|
||||
color=$RED
|
||||
fi
|
||||
|
||||
printf '%s' "$text" >"$CACHE"
|
||||
emit "$text" "💪 ${count}/${minimum}" "$color"
|
||||
Loading…
Reference in New Issue
Block a user