Ely Office: six offline-first desktop apps in Rust and GPUI
ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git), ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
This commit is contained in:
817 files changed
+143101
No files matched your search
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
# Side panels: narrower by default, dragged wider, kept on restart.
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")/../.." && pwd)
|
||||
[ "$(uname)" = Darwin ] || { echo "SKIP: macOS only"; exit 0; }
|
||||
work=$(mktemp -d)
|
||||
# Keeps the run's own status; the app's SIGTERM is expected.
|
||||
cleanup() {
|
||||
local status=$?
|
||||
if [ -n "${pid:-}" ]; then
|
||||
kill "$pid" 2>/dev/null || true
|
||||
wait "$pid" 2>/dev/null || true
|
||||
fi
|
||||
[ "$status" = 0 ] && rm -rf "$work" || echo "kept $work" >&2
|
||||
exit "$status"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
fail() {
|
||||
echo "FAIL: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cargo build -q -p ely-lok --bins -p ely-doc --manifest-path "$root/Cargo.toml"
|
||||
for tool in ax-values ax-press drag; do swiftc -O -o "$work/$tool" "$root/tests/scripts/$tool.swift"; done
|
||||
[ "$("$work/ax-values" $$ | head -n 1)" != untrusted ] || { echo "SKIP: needs Accessibility permission"; exit 0; }
|
||||
home="$work/home"
|
||||
mkdir -p "$home"
|
||||
prefs="$home/Library/Application Support/ElyOffice/ely-doc/settings.json"
|
||||
start() {
|
||||
ELY_SMOKE=hold ELY_LOCALE=en HOME="$home" perl -e 'alarm 120; exec @ARGV' "$root/target/debug/ely-doc" >"$work/out" 2>&1 &
|
||||
pid=$!
|
||||
for _ in $(seq 100); do "$work/ax-values" "$pid" | grep -q 'title=Back' && break; sleep 0.3; done
|
||||
osascript -e "tell application \"System Events\" to set frontmost of (first process whose unix id is $pid) to true" >/dev/null
|
||||
sleep 1
|
||||
}
|
||||
# The window's left edge and Back's center.
|
||||
edges() {
|
||||
local window back
|
||||
window=$(osascript -e "tell application \"System Events\" to get position of first window of (first process whose unix id is $pid)" | cut -d, -f1)
|
||||
back=$("$work/ax-values" "$pid" | grep -m 1 'title=Back' | sed 's/.*at=//' | cut -d, -f1)
|
||||
echo "$window $back"
|
||||
}
|
||||
start
|
||||
read -r left back <<<"$(edges)"
|
||||
# Back is centered in the left panel: half its width.
|
||||
[ $(( (back - left) * 2 )) -le 230 ] || fail "the left panel starts at $(( (back - left) * 2 )) points"
|
||||
y=$(( $(osascript -e "tell application \"System Events\" to get position of first window of (first process whose unix id is $pid)" | cut -d, -f2 | tr -d ' ') + 400 ))
|
||||
edge=$(( left + (back - left) * 2 - 1 ))
|
||||
keys() { osascript -e 'tell application "System Events"' -e "$1" -e 'end tell' >/dev/null; }
|
||||
quit() {
|
||||
keys 'keystroke "q" using command down'
|
||||
for _ in $(seq 40); do kill -0 "$pid" 2>/dev/null || break; sleep 0.25; done
|
||||
! kill -0 "$pid" 2>/dev/null || fail "Cmd+Q did not quit"
|
||||
wait "$pid" 2>/dev/null || true
|
||||
}
|
||||
# Waits until the app's AX tree holds $1.
|
||||
seen() {
|
||||
for _ in $(seq 40); do "$work/ax-values" "$pid" | grep -q -- "$1" && return 0; sleep 0.25; done
|
||||
return 1
|
||||
}
|
||||
# Dragged, then quit at once: the width is still kept.
|
||||
"$work/drag" "$edge" "$y" $(( edge + 80 )) "$y"
|
||||
read -r _ wide <<<"$(edges)"
|
||||
[ $(( wide - back )) -ge 30 ] || fail "the panel did not widen: Back moved $(( wide - back ))"
|
||||
quit
|
||||
grep -q '"left": [0-9]' "$prefs" || fail "a quit right after the drag lost the width: $(cat "$prefs" 2>/dev/null)"
|
||||
start
|
||||
read -r left again <<<"$(edges)"
|
||||
[ $(( again - wide )) -le 2 ] && [ $(( wide - again )) -le 2 ] || fail "the width did not come back: $again, not $wide"
|
||||
quit
|
||||
|
||||
# A bad stored width is shown, not silently replaced.
|
||||
python3 - "$prefs" <<'PY'
|
||||
import json, sys
|
||||
path = sys.argv[1]
|
||||
fields = json.load(open(path))
|
||||
fields["panels"] = {"left": "broken", "right": 320}
|
||||
open(path, "w").write(json.dumps(fields))
|
||||
PY
|
||||
start
|
||||
keys 'keystroke "," using command down'
|
||||
seen "settings cannot be read" || fail "the bad width is not shown"
|
||||
# A dragged width mends it; the message goes.
|
||||
osascript -e "tell application \"System Events\" to click button 1 of (first window of (first process whose unix id is $pid) whose name is \"Settings\")" >/dev/null
|
||||
sleep 0.5
|
||||
read -r left back <<<"$(edges)"
|
||||
edge=$(( left + (back - left) * 2 - 1 ))
|
||||
"$work/drag" "$edge" "$y" $(( edge + 30 )) "$y"
|
||||
for _ in $(seq 20); do grep -q '"left": [0-9]' "$prefs" 2>/dev/null && break; sleep 0.25; done
|
||||
grep -q '"left": [0-9]' "$prefs" || fail "the mending width is not kept"
|
||||
keys 'keystroke "," using command down'
|
||||
seen "title=Dark" || fail "the settings page did not load"
|
||||
! "$work/ax-values" "$pid" | grep -q "cannot be read" || fail "the mended width still shows as unreadable"
|
||||
quit
|
||||
|
||||
# A failed save is shown.
|
||||
printf '{"version":1}' >"$prefs"
|
||||
start
|
||||
read -r left back <<<"$(edges)"
|
||||
edge=$(( left + (back - left) * 2 - 1 ))
|
||||
rm "$prefs"
|
||||
mkdir "$prefs"
|
||||
"$work/drag" "$edge" "$y" $(( edge + 60 )) "$y"
|
||||
sleep 1
|
||||
keys 'keystroke "," using command down'
|
||||
seen "was not saved" || fail "the failed save is not shown"
|
||||
# Another kind of save succeeding leaves this failure shown.
|
||||
"$work/ax-press" "$pid" Dark >/dev/null
|
||||
sleep 1.5
|
||||
grep -q '"appearance": "dark"' "$home/Library/Application Support/ElyOffice/settings.json" || fail "Dark was not saved"
|
||||
seen "was not saved" || fail "the panel failure vanished on another save"
|
||||
# Once the panel save works again, the failure goes.
|
||||
rmdir "$prefs"
|
||||
# Out of the way: the settings window covers the edge.
|
||||
osascript -e "tell application \"System Events\" to click button 1 of (first window of (first process whose unix id is $pid) whose name is \"Settings\")" >/dev/null
|
||||
sleep 0.5
|
||||
read -r left back <<<"$(edges)"
|
||||
edge=$(( left + (back - left) * 2 - 1 ))
|
||||
"$work/drag" "$edge" "$y" $(( edge + 30 )) "$y"
|
||||
for _ in $(seq 20); do grep -q '"left": [0-9]' "$prefs" 2>/dev/null && break; sleep 0.25; done
|
||||
grep -q '"left": [0-9]' "$prefs" || fail "the retried width is not kept"
|
||||
keys 'keystroke "," using command down'
|
||||
# The page's own controls first: an empty tree proves nothing.
|
||||
seen "title=Dark" || fail "the settings page did not load"
|
||||
! "$work/ax-values" "$pid" | grep -q "was not saved" || fail "the fixed failure still shows"
|
||||
quit
|
||||
echo "ok: panels"
|
||||
Reference in new issue
Block a user