Settings had a search index and the launcher had script commands, and neither knew about the other: finding a setting meant opening Settings first and searching there. One command per page is now generated from the same sources the in-app search reads -- the sidebar page list, the group routing, and the schema labels -- so a setting searchable inside Settings is searchable from the launcher without a second list to maintain. Generating it surfaced a gap in the in-app search as well. Six pages had no vocabulary at all, because their contents come from the system rather than our schema, so searching "volume" found nothing in Settings either. They now carry entries, which improves both surfaces. The product prefix is dropped from every hand-written command title. The generated ones are qualified "Settings: <page>" instead: a bare page label collides with the feature of the same name, and two commands sharing a title are indistinguishable in a launcher. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
169 lines
6.0 KiB
Bash
Executable File
169 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# One stable command boundary for launcher actions. Vicinae scripts stay tiny,
|
|
# while the actual mapping to Quickshell IPC remains testable in one place.
|
|
|
|
set -euo pipefail
|
|
|
|
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
action="${1:-}"
|
|
helper_dir="${PANAMA_ACTION_HELPER_DIR:-$script_dir}"
|
|
confirm_attempts="${PANAMA_ACTION_CONFIRM_ATTEMPTS:-20}"
|
|
confirm_delay="${PANAMA_ACTION_CONFIRM_DELAY:-0.1}"
|
|
kill_command="${PANAMA_ACTION_KILL_COMMAND:-/usr/bin/kill}"
|
|
|
|
osd_command=("$helper_dir/panama-osd")
|
|
gallery_command=("$helper_dir/panama-prism-gallery")
|
|
|
|
report_failure() {
|
|
local status=$?
|
|
trap - EXIT
|
|
if (( status != 0 )) && command -v notify-send >/dev/null 2>&1; then
|
|
notify-send -a Panama -i dialog-error-symbolic \
|
|
"Panama action failed" \
|
|
"The “${action//-/ }” action could not be completed." || true
|
|
fi
|
|
exit "$status"
|
|
}
|
|
trap report_failure EXIT
|
|
|
|
show_state() {
|
|
local state="$1" on_icon="$2" off_icon="$3" label="$4"
|
|
case "$state" in
|
|
true) PANAMA_OSD_STRICT=1 "${osd_command[@]}" message "$on_icon" "$label On" ;;
|
|
false) PANAMA_OSD_STRICT=1 "${osd_command[@]}" message "$off_icon" "$label Off" ;;
|
|
*)
|
|
printf 'Panama action returned an invalid state: %s\n' "$state" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
state_is_active() {
|
|
local target="$1"
|
|
case "$target" in
|
|
caffeine)
|
|
systemd-inhibit --list --no-pager --no-legend 2>/dev/null \
|
|
| awk '$1 == "Panama" && $(NF - 1) == "Caffeine" && $NF == "block" { found = 1 } END { exit !found }'
|
|
;;
|
|
night-light)
|
|
pgrep -u "$(id -u)" -x hyprsunset >/dev/null 2>&1
|
|
;;
|
|
*) return 2 ;;
|
|
esac
|
|
}
|
|
|
|
release_caffeine_inhibitors() {
|
|
local inhibitors pid uid
|
|
uid="$(id -u)"
|
|
inhibitors="$(systemd-inhibit --list --no-pager --no-legend 2>/dev/null \
|
|
| awk -v uid="$uid" '$1 == "Panama" && $2 == uid && $(NF - 1) == "Caffeine" && $NF == "block" { print $4 }')"
|
|
while IFS= read -r pid; do
|
|
[[ $pid =~ ^[0-9]+$ ]] || continue
|
|
"$kill_command" "$pid" 2>/dev/null || true
|
|
done <<<"$inhibitors"
|
|
}
|
|
|
|
wait_for_confirmed_state() {
|
|
local target="$1" expected="$2" attempt
|
|
for ((attempt = 0; attempt < confirm_attempts; attempt++)); do
|
|
if [[ $expected == true ]] && state_is_active "$target"; then
|
|
return 0
|
|
fi
|
|
if [[ $expected == false ]] && ! state_is_active "$target"; then
|
|
return 0
|
|
fi
|
|
sleep "$confirm_delay"
|
|
done
|
|
printf 'Panama action could not confirm %s reached state %s\n' "$target" "$expected" >&2
|
|
return 1
|
|
}
|
|
|
|
toggle_state() {
|
|
local target="$1" on_icon="$2" off_icon="$3" label="$4" state
|
|
state="$(qs ipc call "$target" toggle)"
|
|
case "$state" in true|false) ;; *) show_state "$state" "$on_icon" "$off_icon" "$label"; return ;; esac
|
|
if [[ $target == caffeine && $state == false ]]; then
|
|
release_caffeine_inhibitors
|
|
fi
|
|
wait_for_confirmed_state "$target" "$state"
|
|
show_state "$state" "$on_icon" "$off_icon" "$label"
|
|
}
|
|
|
|
wait_for_shell() {
|
|
local attempt
|
|
for ((attempt = 0; attempt < confirm_attempts; attempt++)); do
|
|
if qs ipc show >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep "$confirm_delay"
|
|
done
|
|
printf 'Panama shell did not become ready after restart\n' >&2
|
|
return 1
|
|
}
|
|
|
|
case "$action" in
|
|
control-center) qs ipc call quicksettings open ;;
|
|
notifications) qs ipc call notifications open ;;
|
|
calendar) qs ipc call calendar-agenda open ;;
|
|
clipboard) qs ipc call clipboard open ;;
|
|
overview) qs ipc call overview open ;;
|
|
settings) qs ipc call settings open ;;
|
|
|
|
# Jump straight to one settings page. The launcher's per-page commands are
|
|
# the only caller, and they are generated from the page list itself, so the
|
|
# pattern below is a boundary check rather than a whitelist: an unknown page
|
|
# would leave the settings window showing nothing at all.
|
|
settings-page)
|
|
page="${2:-}"
|
|
if [[ ! "$page" =~ ^[a-z][a-z-]*$ ]]; then
|
|
printf 'Usage: panama-action settings-page PAGE\n' >&2
|
|
exit 2
|
|
fi
|
|
qs ipc call settings page "$page"
|
|
;;
|
|
health) qs ipc call health open ;;
|
|
|
|
dnd)
|
|
state="$(qs ipc call notifications dnd)"
|
|
show_state "$state" notifications-disabled-symbolic notifications-symbolic "Do Not Disturb"
|
|
;;
|
|
caffeine)
|
|
toggle_state caffeine weather-clear-symbolic weather-clear-night-symbolic Caffeine
|
|
;;
|
|
night-light)
|
|
toggle_state night-light night-light-symbolic night-light-disabled-symbolic "Night Light"
|
|
;;
|
|
focus-start)
|
|
state="$(qs ipc call focus start)"
|
|
[[ $state == true ]]
|
|
PANAMA_OSD_STRICT=1 "${osd_command[@]}" message preferences-system-time-symbolic "Focus Session Started"
|
|
;;
|
|
focus-end)
|
|
state="$(qs ipc call focus end)"
|
|
if [[ $state == true ]]; then
|
|
PANAMA_OSD_STRICT=1 "${osd_command[@]}" message media-playback-stop-symbolic "Focus Session Ended"
|
|
else
|
|
PANAMA_OSD_STRICT=1 "${osd_command[@]}" message dialog-information-symbolic "No Focus Session Running"
|
|
fi
|
|
;;
|
|
|
|
capture) qs ipc call capture open ;;
|
|
intelligence) qs ipc call screen-intelligence open ;;
|
|
screenshot) qs ipc call capture screenNow ;;
|
|
microphone) PANAMA_OSD_STRICT=1 "${osd_command[@]}" microphone toggle ;;
|
|
|
|
gallery) "${gallery_command[@]}" ;;
|
|
restart-shell)
|
|
qs kill >/dev/null 2>&1 || true
|
|
quickshell --daemonize
|
|
wait_for_shell
|
|
PANAMA_OSD_STRICT=1 "${osd_command[@]}" message view-refresh-symbolic "Panama Restarted"
|
|
;;
|
|
*)
|
|
printf 'Usage: panama-action {%s}\n' \
|
|
'control-center|notifications|calendar|clipboard|overview|settings|settings-page PAGE|health|dnd|caffeine|night-light|focus-start|focus-end|capture|intelligence|screenshot|microphone|gallery|restart-shell' >&2
|
|
exit 2
|
|
;;
|
|
esac
|