Complete the Panama theme system

This commit is contained in:
Gabriel Brown
2026-08-20 22:03:08 -04:00
parent 69ecec7ecf
commit ed428e87c4
17 changed files with 1370 additions and 41 deletions
+133
View File
@@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -euo pipefail
repo_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
settings="$repo_dir/config/dot/quickshell/modules/settings"
theme="$repo_dir/config/dot/quickshell/config/Theme.qml"
scheme="$repo_dir/config/dot/quickshell/services/ColorScheme.qml"
search="$repo_dir/config/dot/quickshell/services/SettingsSearch.qml"
fail() {
printf 'accent controls contract: %s\n' "$1" >&2
exit 1
}
for component in AccentPicker AccentEditor ThemeProfilePicker; do
[[ -f "$settings/$component.qml" ]] || fail "$component is missing"
rg -Fq "$component 1.0 $component.qml" "$settings/qmldir" \
|| fail "$component is not registered in the settings module"
done
for label in \
'Primary hue' 'Primary saturation' 'Primary value' \
'Secondary hue' 'Secondary saturation' 'Secondary value'; do
rg -Fq "$label" "$settings/AccentEditor.qml" \
|| fail "HSV control is missing the visible label $label"
done
rg -Fq 'ValueSlider {' "$settings/AccentEditor.qml" \
|| fail 'advanced accents do not reuse ValueSlider'
rg -Fq 'Accessible.role: Accessible.Slider' "$settings/AccentEditor.qml" \
|| fail 'HSV controls do not expose slider semantics'
rg -Fq 'Accessible.name: root.label' "$settings/AccentEditor.qml" \
|| fail 'HSV controls are not programmatically labelled'
rg -Fq 'Accessible.description:' "$settings/AccentEditor.qml" \
|| fail 'HSV controls do not expose their numeric value as a non-hue signal'
rg -Fq 'activeFocusOnTab: true' "$settings/AccentEditor.qml" \
|| fail 'HSV controls cannot receive keyboard focus'
rg -Fq 'Keys.onPressed:' "$settings/AccentEditor.qml" \
|| fail 'HSV controls cannot be adjusted from the keyboard'
rg -Fq 'activeFocus ? Theme.accentSecondary' "$settings/AccentEditor.qml" \
|| fail 'HSV controls have no visible keyboard focus treatment'
rg -Fq '["hyprpicker", "--format=hex", "--lowercase-hex", "--quiet", "--no-fancy"]' \
"$settings/AccentEditor.qml" \
|| fail 'screen picking does not use the validated hyprpicker hex invocation'
for target in 'Pick primary from screen' 'Pick secondary from screen'; do
rg -Fq "$target" "$settings/AccentEditor.qml" \
|| fail "screen picker action is missing $target"
done
rg -Fq 'model: Object.keys(Theme.accents)' "$settings/AccentPicker.qml" \
|| fail 'curated swatches are no longer the fast path'
rg -Fq 'ThemeProfiles.useCuratedAccent(entry.modelData)' "$settings/AccentPicker.qml" \
|| fail 'curated swatches do not select a profile-backed accent'
rg -Fq 'readonly property string current: ThemeProfiles.activeAccentName' "$settings/AccentPicker.qml" \
|| fail 'swatch selection does not follow the active profile'
rg -Fq 'Accessible.name: entry.pair.label + " accent"' "$settings/AccentPicker.qml" \
|| fail 'swatches rely on hue without a programmatic name'
rg -Fq 'activeFocusOnTab: true' "$settings/AccentPicker.qml" \
|| fail 'swatches cannot receive keyboard focus'
rg -Fq 'Keys.onReturnPressed:' "$settings/AccentPicker.qml" \
|| fail 'swatches cannot be selected from the keyboard'
rg -Fq 'model: ThemeProfiles.profiles' "$settings/ThemeProfilePicker.qml" \
|| fail 'profile picker does not show shipped and saved profiles'
rg -Fq 'ThemeProfiles.selectProfile(' "$settings/ThemeProfilePicker.qml" \
|| fail 'profile switching is not wired'
rg -Fq 'ThemeProfiles.saveProfile(' "$settings/ThemeProfilePicker.qml" \
|| fail 'profile saving is not wired'
rg -Fq 'maximumLength: 40' "$settings/ThemeProfilePicker.qml" \
|| fail 'profile names are not visibly bounded to the model limit'
rg -Fq 'ThemeProfiles.deleteProfile(' "$settings/ThemeProfilePicker.qml" \
|| fail 'custom profile deletion is not wired'
rg -Fq 'activeFocusOnTab:' "$settings/ThemeProfilePicker.qml" \
|| fail 'profile actions cannot receive keyboard focus'
rg -Fq 'Keys.onReturnPressed:' "$settings/ThemeProfilePicker.qml" \
|| fail 'profile actions cannot be triggered from the keyboard'
for component in ThemeProfilePicker AccentPicker AccentEditor; do
rg -Fq "$component {" "$settings/AppearancePage.qml" \
|| fail "Appearance does not include $component"
done
rg -Fq 'ThemeProfiles.activeProfile' "$theme" \
|| fail 'Theme roles do not react to the selected profile'
rg -Fq 'root.hyprColor(Theme.accent)' "$scheme" \
|| fail 'the focused border start does not follow Theme.accent'
rg -Fq 'root.hyprColor(Theme.accentSecondary)' "$scheme" \
|| fail 'the focused border end does not follow Theme.accentSecondary'
for term in 'Theme profiles' 'Advanced accent' 'Pick colour from screen'; do
rg -Fq "$term" "$search" || fail "Settings search is missing $term"
done
if rg -n 'NumberAnimation|ColorAnimation|SequentialAnimation|ParallelAnimation|loops:[[:space:]]*Animation\.Infinite' \
"$settings/AccentEditor.qml" "$settings/AccentPicker.qml" "$settings/ThemeProfilePicker.qml"; then
fail 'theme controls introduce continuously repainting or decorative animation'
fi
state_home="$(mktemp -d /tmp/panama-accent-controls.XXXXXX)"
harness="$repo_dir/config/dot/quickshell/accent-controls-harness.qml"
qs_for_test() {
XDG_CONFIG_HOME="$state_home/config" XDG_STATE_HOME="$state_home/state" \
QS_DISABLE_CRASH_HANDLER=1 qs -p "$harness" "$@"
}
cleanup() {
qs_for_test kill >/dev/null 2>&1 || true
rm -rf "$state_home"
}
trap cleanup EXIT
qs_for_test --daemonize >/dev/null
for _ in $(seq 1 40); do
qs_for_test ipc show 2>/dev/null | rg -q '^target accent-controls-test$' && break
sleep 0.1
done
qs_for_test ipc show 2>/dev/null | rg -q '^target accent-controls-test$' \
|| fail 'headless AccentEditor harness did not start'
before="$(qs_for_test ipc call accent-controls-test status)"
jq -e '.id == "moon" and .shipped == true' <<<"$before" >/dev/null \
|| fail 'headless editor did not begin on Moon'
after="$(qs_for_test ipc call accent-controls-test adjust primary h 0)"
jq -e '.shipped == false and .accent != "#82aaff" and .secondary == "#b172b0"' \
<<<"$after" >/dev/null \
|| fail 'an HSV adjustment did not create a custom profile with the unchanged secondary colour'
trap - EXIT
cleanup
printf 'accent controls contract: PASS\n'