156 lines
5.4 KiB
Bash
Executable File
156 lines
5.4 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 ;;
|
|
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|health|dnd|caffeine|night-light|focus-start|focus-end|capture|intelligence|screenshot|microphone|gallery|restart-shell' >&2
|
|
exit 2
|
|
;;
|
|
esac
|