Files
asepharyana 1cdb82a76f Sync config from arch
- hypr/apps.lua
- hypr/autostart.lua
- hypr/envs.lua
- hypr/hyprland.lua
- hypr/hyprsunset.conf
- hypr/input.lua
- hypr/looknfeel.lua
- hypr/omasettings.lua
- hypr/xdph.conf
- omarchy/branding/about.txt
- omarchy/branding/screensaver.txt
- omarchy/extensions/omarchy-menu.jsonc
- omarchy/hooks/battery-low.d/play-warning-sound.sample
- omarchy/hooks/font-set.d/show-font-notification.sample
- omarchy/hooks/post-boot.d/weather.sample
- omarchy/hooks/post-update.d/install-voxtype.hook
- omarchy/hooks/post-update.d/setup-agent.hook
- omarchy/hooks/post-update.d/setup-fingerprint.hook
- omarchy/hooks/post-update.d/show-update-notification.sample
- omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample
- omarchy/hooks/theme-set.d/show-theme-notification.sample
- omarchy/shell.json
- omarchy/shell.toml
- omarchy/theme.name
- omarchy/themes/azure-glow/README.md
- omarchy/themes/azure-glow/alacritty.toml
- omarchy/themes/azure-glow/btop.theme
- omarchy/themes/azure-glow/hyprland.conf
- omarchy/themes/azure-glow/hyprlock.conf
- omarchy/themes/azure-glow/icons.theme
- … 269 more
2026-09-23 15:19:12 +07:00

214 lines
7.8 KiB
Bash

#!/usr/bin/env bash
# Capture README screenshots against a fixture vault.
#
# Restarts the Omarchy shell with demo/bin ahead of it on PATH, so the plugin
# resolves `bw` to the shim and shows made-up data. Your real vault is never
# read, and the shell is restored on the way out -- including if this script
# is interrupted.
#
# ./demo/capture.sh [output-dir] (default: docs/screenshots)
set -euo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUT="${1:-$REPO/docs/screenshots}"
IPC=(qs -p /usr/share/omarchy/shell/shell.qml ipc call io.github.elevate08.qs-bitwarden-cli)
for tool in grim magick wtype hyprctl quickshell /usr/bin/python3; do
command -v "$tool" >/dev/null || { echo "missing required tool: $tool" >&2; exit 1; }
done
mkdir -p "$OUT"
restore() {
echo "restoring the real shell..."
# The fixture vault's SSH key gets projected to the same directory the real
# one uses. The real shell rewrites its own keys on the next load but will
# not remove a file it never wrote, so a demo key would sit there for good.
rm -f "${XDG_DATA_HOME:-$HOME/.local/share}/qs-bitwarden-cli/ssh/Demo Deploy Key.pub"
pkill -f "quickshell -n -p /usr/share/omarchy/shell" 2>/dev/null || true
sleep 1
omarchy restart shell >/dev/null 2>&1 || true
}
trap restore EXIT INT TERM
# start_shell <vault-state>
#
# The fixture shell is restarted per vault state rather than driven between
# them: the panel reads `bw status` once on open, so the logged-out screen
# cannot be reached from a running unlocked instance.
start_shell() {
echo "starting shell with the fixture vault ($1)..."
pkill -f "quickshell -n -p /usr/share/omarchy/shell" 2>/dev/null || true
sleep 1
PATH="$REPO/demo/bin:$PATH" QSBW_DEMO_STATUS="$1" \
nohup quickshell -n -p /usr/share/omarchy/shell >/dev/null 2>&1 &
sleep 6
# Park the pointer so hover states and tooltips stay out of the shots.
hyprctl dispatch movecursor 100 100 >/dev/null 2>&1 || true
}
# Crop to the panel itself rather than a fixed box. The panel resizes with its
# content, and -- more importantly -- a loose crop would put whatever is behind
# it (windows, filenames, terminal scrollback) into the published image.
shot() { # shot <name>
sleep 1
grim "$OUT/.raw.png"
local box err
# Keep the locator's own reason. Swallowing it turned a theme change into
# six identical "could not locate the panel border" lines and no clue why.
if box="$(/usr/bin/python3 "$REPO/demo/find_panel.py" "$OUT/.raw.png" 2>/tmp/find_panel.err)"; then
magick "$OUT/.raw.png" -crop "$box" +repage "$OUT/$1.png"
echo " wrote $1.png ($box)"
else
err="$(cat /tmp/find_panel.err)"
echo " SKIPPED $1: ${err:-could not locate the panel border}" >&2
fi
rm -f /tmp/find_panel.err
if [ -n "${QSBW_KEEP_RAW:-}" ]; then mv -f "$OUT/.raw.png" "$OUT/.raw-$1.png" 2>/dev/null || true
else rm -f "$OUT/.raw.png"; fi
}
# open_detail <search text>
#
# Narrows the list to one item and opens it. Typing the name is steadier than
# counting Down presses: the list is sorted favourites-first and then by name,
# so an added fixture would silently shift every offset.
#
# The Down is what hands focus back from the search field to the key catcher --
# with one result it clamps to the only row -- and `e` on the list opens the
# detail. (`e` again, on the detail, opens the form.)
open_detail() {
wtype "/" 2>/dev/null; sleep 1
wtype "$1" 2>/dev/null; sleep 2
wtype -k Down 2>/dev/null; sleep 1
wtype "e" 2>/dev/null; sleep 2
}
# Back to an empty list from wherever open_detail left us.
clear_search() {
wtype -k Escape 2>/dev/null; sleep 1
wtype "/" 2>/dev/null; sleep 1
wtype -M ctrl -k a -m ctrl 2>/dev/null
wtype -k BackSpace 2>/dev/null; sleep 1
wtype -k Down 2>/dev/null; sleep 1
}
# --- SSH signing approval ---------------------------------------------------
#
# The approval screen exists only while a real signing request is waiting, so
# it cannot be navigated to -- it has to be raised. `ssh-add -T` asks the agent
# to sign one challenge with one key and nothing else, which is the smallest
# request that produces this prompt.
#
# Everything here is the fixture vault: the key is the throwaway pair in
# fixtures.json, and the socket belongs to the fixture shell started above.
# The request is denied rather than approved, so no signature is ever made.
capture_ssh_approval() {
local sock="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/qs-bitwarden-cli/ssh-agent.sock"
local pub="${XDG_DATA_HOME:-$HOME/.local/share}/qs-bitwarden-cli/ssh/Demo Deploy Key.pub"
# The helper starts with the panel and projects its public keys after the
# vault loads, so wait for the file rather than guessing at a delay.
local waited=0
while [ ! -S "$sock" ] || [ ! -f "$pub" ]; do
sleep 1; waited=$((waited + 1))
if [ "$waited" -ge 30 ]; then
echo " skipped 13-ssh-approval: no agent socket or projected key after ${waited}s" >&2
echo " (is 'Act as your SSH agent' enabled in shell.json?)" >&2
return 0
fi
done
"${IPC[@]}" open >/dev/null 2>&1; sleep 2
# In the background: it blocks until the prompt is answered, which is the
# point -- the prompt has to still be on screen when the shot is taken.
SSH_AUTH_SOCK="$sock" ssh-add -T "$pub" >/dev/null 2>&1 &
local asker=$!
sleep "${QSBW_SSH_SETTLE:-4}"
shot 13-ssh-approval
# Deny it. Escape is the approval screen's own deny, so nothing is signed.
wtype -k Escape 2>/dev/null; sleep 1
wait "$asker" 2>/dev/null || true
"${IPC[@]}" close >/dev/null 2>&1 || true
}
# QSBW_ONLY_SSH=1 captures the approval shot alone. It is the only shot that
# depends on timing rather than on a keystroke, so it is the one that gets
# iterated on, and re-running the whole sequence to retake it costs a minute
# and five shells.
if [ -n "${QSBW_ONLY_SSH:-}" ]; then
start_shell unlocked
capture_ssh_approval
echo "done -> $OUT"
exit 0
fi
# --- logged out -------------------------------------------------------------
# No setup shot. The wizard appears only while a required tool is missing, and
# it watches for the install and moves on by itself the moment one lands. The
# fixture environment has every dependency -- that is what makes the rest of
# these shots work -- so the screen correctly advances straight past itself.
# Photographing it means deliberately hiding `jq` or `bw` from the shell's
# PATH, which breaks the vault reads every other shot depends on.
start_shell unauthenticated
"${IPC[@]}" open >/dev/null 2>&1; sleep 4
shot 12-login
"${IPC[@]}" close >/dev/null 2>&1 || true
# --- locked -----------------------------------------------------------------
start_shell locked
"${IPC[@]}" open >/dev/null 2>&1; sleep 4
shot 11-locked
"${IPC[@]}" close >/dev/null 2>&1 || true
# --- unlocked, populated vault ----------------------------------------------
start_shell unlocked
"${IPC[@]}" open >/dev/null 2>&1; sleep 4
shot 01-vault-list
# One of each item type the panel draws differently. A login has credentials
# and a TOTP; a card and an identity have the field blocks added in 1.7.0, and
# an identity is the one that shows the address as a single copyable block.
open_detail "GitHub"
shot 02-login-detail
wtype "e" 2>/dev/null; sleep 2
shot 03-edit-item
wtype -k Escape 2>/dev/null; sleep 1
clear_search
open_detail "Demo Card"
shot 04-card-detail
clear_search
open_detail "Dana Demo"
shot 05-identity-detail
clear_search
wtype "f" 2>/dev/null; sleep 2
shot 06-folder-drawer
wtype -k Escape 2>/dev/null; sleep 1
wtype "t" 2>/dev/null; sleep 2
shot 07-type-filter
wtype -k Escape 2>/dev/null; sleep 1
wtype "g" 2>/dev/null; sleep 5
shot 08-generator
wtype -k Escape 2>/dev/null; sleep 1
wtype -M alt -k s -m alt 2>/dev/null; sleep 3
shot 09-sends
wtype -k Escape 2>/dev/null; sleep 1
wtype -M alt -k comma -m alt 2>/dev/null; sleep 3
shot 10-settings
"${IPC[@]}" close >/dev/null 2>&1 || true
capture_ssh_approval
echo "done -> $OUT"