Review everything shipped this weekend, and fix what the reviewers caught

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 13:29:42 -04:00
parent ffce48964e
commit 07db1068f1
42 changed files with 959 additions and 219 deletions
+5 -1
View File
@@ -92,7 +92,11 @@ resolve_wallpaper_path() {
# A video wallpaper cannot play on the lock screen; VideoWallpaper.qml
# grabs a still frame when one is selected, and that frame stands in.
# A video with no cached frame falls through to the shipped image.
if [[ "$candidate" =~ \.(mp4|mkv|webm)$ ]]; then
#
# Lowercased first, because panama-video-wallpaper scans with -iname: a
# HOLIDAY.MP4 it happily offers would otherwise be handed to the lock screen
# as an image and render as nothing at all.
if [[ "${candidate,,}" =~ \.(mp4|mkv|webm)$ ]]; then
local frame="${XDG_STATE_HOME:-$HOME/.local/state}/panama/video-wallpaper-frame.png"
if valid_path "$frame"; then
resolved_wallpaper="$frame"
+56 -24
View File
@@ -15,25 +15,41 @@ settings_file() {
printf '%s/panama/settings.json\n' "${XDG_CONFIG_HOME:-$HOME/.config}"
}
setting_bool() {
local key="$1" fallback="$2" file value
# Both switches the volume keys care about, read in a single jq. A held-down
# volume key repeats about twenty times a second, and each repeat used to spawn
# jq twice -- once for the ceiling, once for the click. Prints them as
# "<overAmplification> <volumeChangeBlip>", falling back to the schema defaults
# whenever the file cannot be read or does not carry the key.
volume_settings() {
local file value over=false blip=true
file="$(settings_file)"
[[ -r $file ]] || { printf '%s\n' "$fallback"; return 0; }
command -v jq >/dev/null 2>&1 || { printf '%s\n' "$fallback"; return 0; }
value="$(jq -r --arg key "$key" '
if type == "object" and (.[$key] | type) == "boolean" then .[$key] else empty end
' "$file" 2>/dev/null)" || value=""
[[ $value == true || $value == false ]] || value="$fallback"
printf '%s\n' "$value"
if [[ -r $file ]] && command -v jq >/dev/null 2>&1; then
value="$(jq -r '
def flag($key; $fallback):
if type == "object" and (.[$key] | type) == "boolean"
then (.[$key] | tostring)
else $fallback
end;
[flag("overAmplification"; "false"), flag("volumeChangeBlip"; "true")]
| join(" ")
' "$file" 2>/dev/null)" || value=""
read -r over blip <<<"$value"
[[ $over == true || $over == false ]] || over=false
[[ $blip == true || $blip == false ]] || blip=true
fi
printf '%s %s\n' "$over" "$blip"
}
# wpctl clamps to 1.0 by default, and it clamps the *result* -- so the ceiling
# has to be passed on the way down as well. Without it, stepping down from 130%
# would snap to 100% instead of 124%, which reads as the slider jumping on its
# own. The microphone never gets this: gain past 100% on a capture device buys
# noise, not signal, and the Sound page's input slider stays 0-100 to match.
volume_limit() {
if [[ $(setting_bool overAmplification false) == true ]]; then
# `wpctl set-volume -l` caps the *result*, and without it wpctl does not cap at
# all -- 100% is not a ceiling it enforces on its own. So the limit is passed on
# the way down too, deliberately: with over-amplification off, stepping down
# from a volume that is somehow already above 100% lands under the ceiling
# rather than merely one step lower, which is what having the switch off means.
# The microphone never gets the raised ceiling: gain past 100% on a capture
# device buys noise, not signal, and the Sound page's input slider stays 0-100
# to match.
volume_ceiling() {
if [[ $1 == true ]]; then
printf '1.5\n'
else
printf '1\n'
@@ -42,14 +58,28 @@ volume_limit() {
# The click that says the volume moved. Backgrounded and never waited on: it is
# feedback about something that has already happened, so it must not sit between
# the key press and the OSD. A distribution without the freedesktop sound theme
# has no file to play, which is a silent desktop rather than a broken key.
# the key press and the OSD.
#
# Under a non-blocking lock, in the same runtime directory the DDC lock lives in,
# because key repeat would otherwise start a fresh pw-play over the top of the
# last one twenty times a second. The first press clicks; the repeats that
# arrive while it is still sounding are dropped rather than stacked.
#
# A distribution without the freedesktop sound theme has no file to play, which
# is a silent desktop rather than a broken key.
play_blip() {
local enabled="$1"
local sound="${PANAMA_OSD_BLIP_SOUND:-$PANAMA_OSD_BLIP_DEFAULT}"
[[ $(setting_bool volumeChangeBlip true) == true ]] || return 0
local runtime_dir="${PANAMA_OSD_RUNTIME_DIR:-${XDG_RUNTIME_DIR:-/tmp}/panama-osd-${UID}}"
[[ $enabled == true ]] || return 0
[[ -f $sound ]] || return 0
pw-play "$sound" >/dev/null 2>&1 &
disown 2>/dev/null || true
mkdir -p "$runtime_dir" 2>/dev/null || return 0
chmod 700 "$runtime_dir" 2>/dev/null || true
(
exec {blip_fd}>"$runtime_dir/blip.lock" || exit 0
flock -n "$blip_fd" || exit 0
pw-play "$sound" >/dev/null 2>&1
) &
}
strict_delivery() {
@@ -96,15 +126,17 @@ show_volume() {
}
adjust_volume() {
local action="${1:-}" step="${2:-6}" target="@DEFAULT_AUDIO_SINK@" limit
limit="$(volume_limit)"
local action="${1:-}" step="${2:-6}" target="@DEFAULT_AUDIO_SINK@"
local over blip limit
read -r over blip <<<"$(volume_settings)"
limit="$(volume_ceiling "$over")"
case "$action" in
up) wpctl set-volume -l "$limit" "$target" "${step}%+" || return ;;
down) wpctl set-volume -l "$limit" "$target" "${step}%-" || return ;;
toggle) wpctl set-mute "$target" toggle || return ;;
*) printf 'Usage: panama-osd volume up|down|toggle [step]\n' >&2; return 2 ;;
esac
play_blip
play_blip "$blip"
show_volume "$target" volume
}
@@ -139,10 +139,23 @@ def read_entries():
return (found.group(2) if found.group(2) is not None
else found.group(1).strip())
def default_value():
"""The default, or None when the literal is a block rather than a value.
A "json" setting's `def:` opens an array or an object that runs for
twenty lines, and the scalar reader above captures only the bracket
that opened it. A Default column reading "[" documents nothing and
looks like a parsing bug, which is what it was mistaken for. None
renders as an em dash instead, and the schema stays the place to read
the shape.
"""
value = scalar("def")
return None if value in ("[", "{") else value
entry = {
"key": name,
"type": scalar("type"),
"default": scalar("def"),
"default": default_value(),
"group": scalar("group"),
"label": scalar("label"),
"detail": scalar("detail"),
@@ -103,8 +103,14 @@ for token in black red green yellow blue magenta cyan white \
[[ -n "${!name:-}" ]] || ansi_ok=false
done
# Every token render_vicinae reads, in both schemes. The renderer runs under
# `set -u` in a subshell, so a token missing from one side is not a slightly
# duller launcher theme -- it aborts that render and the file is left as it was.
# The gate has to cover what the renderer actually reads, or it passes and the
# render fails anyway.
both_schemes_ok=true
for token in bg bgDark bgHighlight bgPanel bgPopover fg fgDim fgMuted gutter red; do
for token in bg bgDark bgHighlight bgPanel bgPopover fg fgDim fgMuted gutter red \
accentAlt green magenta orange pink yellow cyan; do
for side in dark light; do
name="${side}_pal_$token"
[[ -n "${!name:-}" ]] || both_schemes_ok=false