fix(file_handlers): use keystroke Cmd+Return to start pptx slideshow

Replace unreliable AppleScript PowerPoint API (run slide show of settings)
with System Events keystroke approach, matching proven behavior from the
old MasterKey app. Opens the file, waits 3s for load, then sends Cmd+Return
to start the slideshow from slide 1.
This commit is contained in:
Scott Idem
2026-04-20 17:01:04 -04:00
parent 3feaf1bbc3
commit 002c27e73c
5 changed files with 56 additions and 33 deletions

View File

@@ -2,14 +2,16 @@
# deploy.sh — Deploy Aether Native Launcher to onsite Mac laptops
#
# USAGE:
# ./deploy.sh <num> [num ...] Deploy to one or more laptops (e.g. 03 04 05)
# ./deploy.sh all Deploy to all laptops in devices.conf
# ./deploy.sh --seed-only <num> Update seed.json only — skip .app copy
# ./deploy.sh <num> [num ...] Deploy to one or more laptops (e.g. 03 04 05)
# ./deploy.sh all Deploy to all laptops in devices.conf
# ./deploy.sh --seed-only <num> Update seed.json only — skip .app copy
# ./deploy.sh --seed-only all
# ./deploy.sh --build <num> [num ...] Build first (npm run package:mac), then deploy
# ./deploy.sh --build all
#
# REQUIRES:
# event.env — copy from event.env.example and fill in AETHER_API_KEY
# builds/ — run "npm run package:mac" first if .app is missing
# builds/ — pre-built, or use --build to build before deploying
#
# SSH keys must already be installed on each target (run ssh-copy-id once per laptop).
@@ -24,6 +26,7 @@ BUILD_DIR="$SCRIPT_DIR/../builds"
# ── Argument parsing ──────────────────────────────────────────────────────────
SEED_ONLY=false
BUILD_FIRST=false
TARGETS=()
usage() {
@@ -36,6 +39,7 @@ if [[ $# -eq 0 ]]; then usage; fi
while [[ $# -gt 0 ]]; do
case "$1" in
--seed-only) SEED_ONLY=true ;;
--build) BUILD_FIRST=true ;;
--help|-h) usage ;;
all) TARGETS+=("all") ;;
*) TARGETS+=("$1") ;;
@@ -75,8 +79,8 @@ fi
# Returns "ip device_id" for a laptop number, or empty if not found
lookup_device() {
local num="$1"
grep -E "^[[:space:]]*${num}[[:space:]]" "$DEVICES_FILE" \
| grep -v '^[[:space:]]*#' \
grep -v '^[[:space:]]*#' "$DEVICES_FILE" \
| grep -E "^[[:space:]]*${num}[[:space:]]" \
| awk '{print $2, $3}' \
| head -1
}
@@ -134,12 +138,14 @@ deploy_laptop() {
return 1
fi
echo " Arch: $archcopying $(basename "$bundle")..."
scp -r "$bundle" "$SSH_USER@$ip:/Applications/aether_launcher.app" || {
echo " ERROR: scp failed."
echo " Arch: $archsyncing $(basename "$bundle")..."
# rsync --delete syncs contents in-place without removing the top-level .app dir.
# This preserves the inode so macOS Aliases and Desktop shortcuts keep working.
rsync -a --delete -e ssh "$bundle/" "$SSH_USER@$ip:/Applications/aether_launcher.app/" || {
echo " ERROR: rsync failed."
return 1
}
echo " .app copied."
echo " .app synced."
else
echo " (--seed-only: skipping .app copy)"
fi
@@ -168,6 +174,19 @@ EOF
return 0
}
# ── Build if requested ───────────────────────────────────────────────────────
if [[ "$BUILD_FIRST" == "true" ]]; then
echo "══════════════════════════════════════════════"
echo " Building: npm run package:mac"
echo "══════════════════════════════════════════════"
(cd "$SCRIPT_DIR/.." && npm run package:mac) || {
echo "ERROR: Build failed. Aborting deploy."
exit 1
}
echo ""
fi
# ── Expand "all" target ───────────────────────────────────────────────────────
EXPANDED_TARGETS=()

View File

@@ -9,20 +9,20 @@
# num ip event_device_id notes
01 192.168.32.101 tFLL1fLQfnk
02 192.168.32.102 rpbfunVPEzw
03 192.168.32.103 1EPfPX8kfw8
04 192.168.32.104 zvgyLM5yieU
05 192.168.32.105 QOc046GoeSc
06 192.168.32.106 2o8j6eb0L6s
# 03 192.168.32.103 1EPfPX8kfw8
# 04 192.168.32.104 zvgyLM5yieU
# 05 192.168.32.105 QOc046GoeSc
# 06 192.168.32.106 2o8j6eb0L6s
07 192.168.32.107 Oa1tlxPEVSQ
08 192.168.32.108 fY4yznpUZ48
09 192.168.32.109 YlgGCyjo9bY
10 192.168.32.110 GcTnFsp1mHI
11 192.168.32.111 6z88m9oEZio
12 192.168.32.112 EggJqL2kWkA
13 192.168.32.113 O11eckHFdVE
14 192.168.32.114 reI0SecUEhI
15 192.168.32.115 crozxT8mA44
16 192.168.32.116 0nP4VZsvr2Q
17 192.168.32.117 Gm2gNqPGzLA
19 192.168.32.119 6tpukvRVugU
x20 192.168.32.120 rwLYnKUNd1M old 04, spare/retired
# 11 192.168.32.111 6z88m9oEZio
# 12 192.168.32.112 EggJqL2kWkA
# 13 192.168.32.113 O11eckHFdVE
# 14 192.168.32.114 reI0SecUEhI
# 15 192.168.32.115 crozxT8mA44
# 16 192.168.32.116 0nP4VZsvr2Q
# 17 192.168.32.117 Gm2gNqPGzLA
# 19 192.168.32.119 6tpukvRVugU
# x20 192.168.32.120 rwLYnKUNd1M old 04, spare/retired

View File

@@ -174,8 +174,10 @@ function registerFileHandlers() {
tell application "Microsoft PowerPoint"
activate
open (POSIX file "${target}")
delay 1
run slide show of active presentation
delay 3
end tell
tell application "System Events"
keystroke return using command down
end tell
`;
}

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,7 @@ export function registerFileHandlers() {
ipcMain.handle('native:check-cache', async (event, { cache_root, hash, hash_prefix_length = 2, verify_hash = false }) => {
const full_path = get_organized_hashed_path(cache_root, hash, hash_prefix_length);
if (!fs.existsSync(full_path)) return false;
if (verify_hash) {
@@ -42,7 +42,7 @@ export function registerFileHandlers() {
const tmp_path = `${full_path}.tmp`;
if (endpoints_in_progress.includes(url)) return { success: true, status: 'in_progress' };
// 1. If final file exists, skip
if (fs.existsSync(full_path)) return { success: true, path: full_path, status: 'exists' };
@@ -106,14 +106,14 @@ export function registerFileHandlers() {
const source = get_organized_hashed_path(cache_root, hash, hash_prefix_length);
const expanded_temp = expandPath(temp_root);
const target = path.join(expanded_temp, filename);
console.log(`Native: Launching from Cache -> ${filename}`);
if (!fs.existsSync(expanded_temp)) fs.mkdirSync(expanded_temp, { recursive: true });
// 1. Copy the file to temp folder with original name
fs.copyFileSync(source, target);
// 2. Determine file type
const ext = path.extname(filename).toLowerCase().replace('.', '');
const is_pres = ['pptx', 'ppt', 'key', 'pdf', 'odp'].includes(ext);
@@ -146,8 +146,10 @@ export function registerFileHandlers() {
tell application "Microsoft PowerPoint"
activate
open (POSIX file "${target}")
delay 1
run slide show of active presentation
delay 3
end tell
tell application "System Events"
keystroke return using command down
end tell
`;
}