Harden Panama launcher actions

This commit is contained in:
Gabriel Brown
2026-08-18 07:31:11 -04:00
parent b28edcd01f
commit ca64d4b9b6
11 changed files with 239 additions and 40 deletions
+63 -19
View File
@@ -7,18 +7,12 @@ 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}"
if command -v panama-osd >/dev/null 2>&1; then
osd_command=(panama-osd)
else
osd_command=("$script_dir/panama-osd")
fi
if command -v panama-prism-gallery >/dev/null 2>&1; then
gallery_command=(panama-prism-gallery)
else
gallery_command=("$script_dir/panama-prism-gallery")
fi
osd_command=("$helper_dir/panama-osd")
gallery_command=("$helper_dir/panama-prism-gallery")
report_failure() {
local status=$?
@@ -35,8 +29,8 @@ trap report_failure EXIT
show_state() {
local state="$1" on_icon="$2" off_icon="$3" label="$4"
case "$state" in
true) "${osd_command[@]}" message "$on_icon" "$label On" ;;
false) "${osd_command[@]}" message "$off_icon" "$label Off" ;;
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
@@ -44,12 +38,55 @@ show_state() {
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
}
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
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 ;;
@@ -69,23 +106,30 @@ case "$action" in
toggle_state night-light night-light-symbolic night-light-disabled-symbolic "Night Light"
;;
focus-start)
qs ipc call focus start
"${osd_command[@]}" message preferences-system-time-symbolic "Focus Session Started"
state="$(qs ipc call focus start)"
[[ $state == true ]]
PANAMA_OSD_STRICT=1 "${osd_command[@]}" message preferences-system-time-symbolic "Focus Session Started"
;;
focus-end)
qs ipc call focus end
"${osd_command[@]}" message media-playback-stop-symbolic "Focus Session Ended"
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) "${osd_command[@]}" microphone toggle ;;
microphone) PANAMA_OSD_STRICT=1 "${osd_command[@]}" microphone toggle ;;
gallery) "${gallery_command[@]}" ;;
restart-shell)
qs kill
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' \
+12 -2
View File
@@ -2,12 +2,22 @@
set -u
strict_delivery() {
[[ ${PANAMA_OSD_STRICT:-false} == true || ${PANAMA_OSD_STRICT:-false} == 1 ]]
}
show_progress() {
qs ipc call osd progress "$1" "$2" 100 "$3" >/dev/null 2>&1 || true
if ! qs ipc call osd progress "$1" "$2" 100 "$3" >/dev/null 2>&1; then
strict_delivery && return 1
fi
return 0
}
show_message() {
qs ipc call osd message "$1" "$2" >/dev/null 2>&1 || true
if ! qs ipc call osd message "$1" "$2" >/dev/null 2>&1; then
strict_delivery && return 1
fi
return 0
}
volume_state() {
+18 -1
View File
@@ -26,6 +26,7 @@ Singleton {
id: root
property bool initialized: false
property bool suppressStatusEvents: false
// The manual switch. Ignored while `automatic` is on.
property bool enabled: Settings.nightLightEnabledByDefault
@@ -53,6 +54,22 @@ Singleton {
}
}
// Launcher actions already provide immediate Prism OSD feedback. Keep the
// ambient Signal Glass channel quiet for that path so one choice produces
// one confirmation instead of two competing transients.
function toggleQuietly(): void {
root.suppressStatusEvents = true;
root.toggle();
root.suppressStatusEvents = false;
}
function restore(manualEnabled: bool, automaticEnabled: bool): void {
root.suppressStatusEvents = true;
root.enabled = manualEnabled;
root.automatic = automaticEnabled;
root.suppressStatusEvents = false;
}
// The window wraps midnight (17:00 → 10:00), so the comparison flips when
// `from` is later in the day than `to`.
function inWindow(hour: real): bool {
@@ -118,7 +135,7 @@ Singleton {
}
onActiveChanged: {
if (!root.initialized)
if (!root.initialized || root.suppressStatusEvents)
return;
StatusEvents.publish({
key: "display-night-light",
+22 -3
View File
@@ -114,7 +114,10 @@ ShellRoot {
IpcHandler {
target: "focus"
function start(): void { FocusSession.startDefault(); }
function start(): bool {
FocusSession.startDefault();
return FocusSession.active;
}
function reveal(): void { FocusSession.reveal(); }
function dismiss(): void { FocusSession.dismiss(); }
function pause(): void { FocusSession.pauseOrResume(); }
@@ -123,7 +126,12 @@ ShellRoot {
ShellState.openOverview(FocusSession.workspaceId);
FocusSession.dismiss();
}
function end(): void { FocusSession.end(false); }
function end(): bool {
if (!FocusSession.active)
return false;
FocusSession.end(false);
return !FocusSession.active;
}
function status(): string {
return JSON.stringify({
active: FocusSession.active,
@@ -272,10 +280,21 @@ ShellRoot {
IpcHandler {
target: "night-light"
function toggle(): bool {
NightLight.toggle();
NightLight.toggleQuietly();
return NightLight.active;
}
function status(): bool { return NightLight.active; }
function settings(): string {
return JSON.stringify({
enabled: NightLight.enabled,
automatic: NightLight.automatic,
active: NightLight.active
});
}
function restore(enabled: bool, automatic: bool): bool {
NightLight.restore(enabled, automatic);
return NightLight.active;
}
}
IpcHandler {