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
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# ElyPDF: a locked file keeps sealed points past engine ends.
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")/../.." && pwd)
|
||||
[ "$(uname)" = Darwin ] || { echo "SKIP: macOS only"; exit 0; }
|
||||
work=$(mktemp -d)
|
||||
cleanup() {
|
||||
local status=$?
|
||||
if [ -n "${pid:-}" ]; then
|
||||
pkill -9 -P "$pid" 2>/dev/null || true
|
||||
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-pdf-engine --bins -p ely-pdf --manifest-path "$root/Cargo.toml"
|
||||
for tool in ax-values ax-press; 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"
|
||||
data="$home/Library/Application Support/ElyOffice/ely-pdf"
|
||||
mkdir -p "$home"
|
||||
cp "$root/tests/fixtures/pdf/aes128.pdf" "$work/locked.pdf"
|
||||
keys() { osascript -e 'tell application "System Events"' -e "$1" -e 'end tell' >/dev/null; }
|
||||
seen() {
|
||||
for _ in $(seq 80); do "$work/ax-values" "$pid" | grep -q -- "$1" && return 0; sleep 0.25; done
|
||||
return 1
|
||||
}
|
||||
opened() { { grep -c "ely-pdf: opened" "$data/ely.log" 2>/dev/null || true; } | head -n 1; }
|
||||
start() {
|
||||
ELY_SMOKE=hold ELY_LOCALE=en ELY_NO_DIALOG=1 HOME="$home" perl -e 'alarm 300; exec @ARGV' \
|
||||
"$root/target/debug/ely-pdf" "$@" >"$work/out" 2>&1 &
|
||||
pid=$!
|
||||
for _ in $(seq 40); do "$work/ax-values" "$pid" | grep -q AXWindow && break; sleep 0.25; 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 open-password dialog, answered; then the tab is there.
|
||||
unlock() {
|
||||
local before
|
||||
before=$(opened)
|
||||
seen "is locked" || fail "no password asked ($1)"
|
||||
keys 'keystroke "owner"'
|
||||
keys 'key code 36'
|
||||
for _ in $(seq 80); do [ "$(opened)" -gt "${before:-0}" ] && break; sleep 0.25; done
|
||||
[ "$(opened)" -gt "${before:-0}" ] || fail "the locked file did not open ($1)"
|
||||
}
|
||||
# A new sealed point, and never a plain one.
|
||||
sealed() {
|
||||
touch "$work/mark"
|
||||
for _ in $(seq 100); do
|
||||
find "$data/recovery" -name '*.enc' -newer "$work/mark" 2>/dev/null | grep -q . && break
|
||||
sleep 0.25
|
||||
done
|
||||
find "$data/recovery" -name '*.enc' -newer "$work/mark" | grep -q . || fail "no sealed point ($1)"
|
||||
[ -z "$(find "$data/recovery" -name '*.bin')" ] || fail "a plain point of a locked file ($1)"
|
||||
}
|
||||
start "$work/locked.pdf"
|
||||
unlock "the file"
|
||||
osascript -e "tell application \"System Events\" to tell (first process whose unix id is $pid) to click menu item \"Rotate Pages Right\" of menu \"Pages\" of menu bar 1" >/dev/null
|
||||
sealed "while editing"
|
||||
# The idle engine ends: told; the copy asks again.
|
||||
pkill -9 -P "$pid" -f ely-pdf-worker || fail "no worker to stop"
|
||||
seen "The document engine stopped" || fail "an idle engine's end is not told"
|
||||
"$work/ax-press" "$pid" "Reopen documents" >/dev/null
|
||||
unlock "the copy after the engine ended"
|
||||
[ -n "$(find "$data/recovery" -name '*.enc')" ] || fail "the old points went before a new one"
|
||||
grep -q "the engine is back, 0 tab(s) lost" "$data/ely.log" || fail "a tab is lost"
|
||||
sealed "for the reopened copy"
|
||||
echo "ok: pdf recovery"
|
||||
Reference in new issue
Block a user