|
#!/usr/bin/env bash |
|
set -euo pipefail |
|
|
|
log() { |
|
printf 'wayscriber-workspace-page: %s\n' "$*" >&2 |
|
} |
|
|
|
get_workspace_number() { |
|
local ws_json ws_id ws_name |
|
ws_json="$(hyprctl -j activeworkspace 2>/dev/null || true)" |
|
if [[ -z "$ws_json" ]]; then |
|
return 1 |
|
fi |
|
|
|
ws_id="$(jq -r '.id // empty' <<<"$ws_json")" |
|
if [[ "$ws_id" =~ ^[0-9]+$ ]] && (( ws_id > 0 )); then |
|
printf '%s\n' "$ws_id" |
|
return 0 |
|
fi |
|
|
|
ws_name="$(jq -r '.name // empty' <<<"$ws_json")" |
|
if [[ "$ws_name" =~ ^[0-9]+$ ]] && (( ws_name > 0 )); then |
|
printf '%s\n' "$ws_name" |
|
return 0 |
|
fi |
|
|
|
return 1 |
|
} |
|
|
|
get_session_file() { |
|
local info |
|
info="$(wayscriber --session-info 2>/dev/null || true)" |
|
printf '%s\n' "$info" \ |
|
| sed -n 's/^ Session file[[:space:]]*:[[:space:]]*//p' \ |
|
| head -n 1 |
|
} |
|
|
|
sync_session_page() { |
|
local session_file target_page target_index active_board tmp_file compressed tmp_out |
|
session_file="$1" |
|
target_page="$2" |
|
target_index=$((target_page - 1)) |
|
|
|
if [[ ! -f "$session_file" ]]; then |
|
log "session file not found ($session_file), skipping page sync" |
|
return 0 |
|
fi |
|
|
|
if gzip -t "$session_file" >/dev/null 2>&1; then |
|
compressed=1 |
|
else |
|
compressed=0 |
|
fi |
|
|
|
if (( compressed )); then |
|
active_board="$(gzip -dc "$session_file" | jq -r '.active_board_id // empty' 2>/dev/null || true)" |
|
else |
|
active_board="$(jq -r '.active_board_id // empty' "$session_file" 2>/dev/null || true)" |
|
fi |
|
|
|
if [[ -z "$active_board" || "$active_board" == "null" ]]; then |
|
if (( compressed )); then |
|
active_board="$(gzip -dc "$session_file" | jq -r '.boards[0].id // "transparent"' 2>/dev/null || printf 'transparent')" |
|
else |
|
active_board="$(jq -r '.boards[0].id // "transparent"' "$session_file" 2>/dev/null || printf 'transparent')" |
|
fi |
|
fi |
|
|
|
tmp_file="$(mktemp "${session_file}.tmp.XXXXXX")" |
|
|
|
if (( compressed )); then |
|
if ! gzip -dc "$session_file" | jq \ |
|
--arg board_id "$active_board" \ |
|
--argjson target "$target_index" \ |
|
' |
|
def empty_page: {shapes: [], undo_stack: [], redo_stack: []}; |
|
|
|
.boards = (.boards // []) |
|
| if ((.boards | map(.id) | index($board_id)) == null) then |
|
.boards += [{id: $board_id, pages: [empty_page], active_page: 0}] |
|
else |
|
. |
|
end |
|
| (.boards[] | select(.id == $board_id)) |= ( |
|
.pages = (.pages // []) |
|
| if (.pages | length) == 0 then .pages = [empty_page] else . end |
|
| .pages += [range((.pages | length); ($target + 1)) | empty_page] |
|
| .active_page = $target |
|
) |
|
| .active_board_id = $board_id |
|
' > "$tmp_file"; then |
|
rm -f "$tmp_file" |
|
log "failed to update session JSON ($session_file), skipping page sync" |
|
return 0 |
|
fi |
|
else |
|
if ! jq \ |
|
--arg board_id "$active_board" \ |
|
--argjson target "$target_index" \ |
|
' |
|
def empty_page: {shapes: [], undo_stack: [], redo_stack: []}; |
|
|
|
.boards = (.boards // []) |
|
| if ((.boards | map(.id) | index($board_id)) == null) then |
|
.boards += [{id: $board_id, pages: [empty_page], active_page: 0}] |
|
else |
|
. |
|
end |
|
| (.boards[] | select(.id == $board_id)) |= ( |
|
.pages = (.pages // []) |
|
| if (.pages | length) == 0 then .pages = [empty_page] else . end |
|
| .pages += [range((.pages | length); ($target + 1)) | empty_page] |
|
| .active_page = $target |
|
) |
|
| .active_board_id = $board_id |
|
' "$session_file" > "$tmp_file"; then |
|
rm -f "$tmp_file" |
|
log "failed to update session JSON ($session_file), skipping page sync" |
|
return 0 |
|
fi |
|
fi |
|
|
|
if (( compressed )); then |
|
tmp_out="$(mktemp "${session_file}.tmp.XXXXXX")" |
|
if ! gzip -n -c "$tmp_file" > "$tmp_out"; then |
|
rm -f "$tmp_file" "$tmp_out" |
|
log "failed to re-compress session JSON ($session_file), skipping page sync" |
|
return 0 |
|
fi |
|
rm -f "$tmp_file" |
|
mv "$tmp_out" "$session_file" |
|
else |
|
mv "$tmp_file" "$session_file" |
|
fi |
|
|
|
} |
|
|
|
launch_wayscriber() { |
|
if pgrep -af 'wayscriber --daemon' >/dev/null 2>&1; then |
|
pkill -SIGUSR1 wayscriber |
|
else |
|
if ! setsid -f wayscriber --active >/dev/null 2>&1; then |
|
wayscriber --active >/dev/null 2>&1 & |
|
fi |
|
fi |
|
} |
|
|
|
main() { |
|
local workspace session_file |
|
|
|
if ! workspace="$(get_workspace_number)"; then |
|
log "could not read active Hyprland workspace, launching without page sync" |
|
launch_wayscriber |
|
return 0 |
|
fi |
|
|
|
session_file="$(get_session_file)" |
|
if [[ -n "$session_file" ]]; then |
|
sync_session_page "$session_file" "$workspace" |
|
else |
|
log "could not resolve Wayscriber session file, launching without page sync" |
|
fi |
|
|
|
if [[ "${WAYSCRIBER_SYNC_ONLY:-0}" == "1" ]]; then |
|
return 0 |
|
fi |
|
|
|
launch_wayscriber |
|
} |
|
|
|
main "$@" |