#!/usr/bin/env bash # A settings button that calls a target the backend does not handle is a dead # control: it looks identical to a working one until someone presses it and # nothing happens. Two dispatch maps in SystemSettings.qml decide whether a # button lands -- openApplication(id) and openGnomePanel(panel) -- and both # silently return false on an unknown name. This pins every id and panel a QML # button passes to being present in those maps. # # It exists because two such buttons shipped: "Start Orca" called # openApplication("orca") with no "orca" in the map, and the dictation card # called a helper subcommand that did not exist. This catches the first shape; # the helper-subcommand shape is caught by each service's own contract. set -uo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" qs="$repo_dir/config/dot/quickshell" sysset="$qs/services/SystemSettings.qml" fail() { printf 'settings buttons contract: %s\n' "$1" >&2; exit 1; } [[ -r "$sysset" ]] || fail "missing $sysset" python3 - "$qs" "$sysset" <<'PY' import re, sys, pathlib qs, sysset = pathlib.Path(sys.argv[1]), pathlib.Path(sys.argv[2]) text = sysset.read_text() # openApplication's command map keys. m = re.search(r'function openApplication.*?const commands = \{(.*?)\};', text, re.S) app_ids = set(re.findall(r'"([a-z0-9-]+)"\s*:', m.group(1))) if m else set() # openGnomePanel's allow-list. m = re.search(r'isGnomePanelAllowed.*?return \[(.*?)\]\.indexOf', text, re.S) panels = set(re.findall(r'"([a-z-]+)"', m.group(1))) if m else set() problems = [] for page in sorted((qs/'modules').rglob('*.qml')): t = page.read_text() for app_id in re.findall(r'openApplication\("([^"]+)"\)', t): if app_id not in app_ids: problems.append(f'{page.name}: openApplication("{app_id}") -- not in the command map, so the button does nothing') for panel in re.findall(r'openGnomePanel\("([a-z-]+)"', t): if panel not in panels: problems.append(f'{page.name}: openGnomePanel("{panel}") -- not allow-listed, so the handoff opens nothing') if problems: print(f"settings buttons contract: {len(problems)} dead button(s)") for p in problems: print(" -", p) sys.exit(1) print(f"settings buttons contract: ok ({len(app_ids)} app ids, {len(panels)} panels, every button resolves)") PY