From d4d2fae4fd8699fac61a80905b7efbb594db03a2 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Tue, 07 Jul 2026 09:53:40 +0200
Subject: [PATCH] feat: deploy.sh iPad/multi-device targets, remote install docs, Pro-unlocked builds

---
 tools/deploy.sh |  103 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/tools/deploy.sh b/tools/deploy.sh
index d1a0801..b8bfc45 100755
--- a/tools/deploy.sh
+++ b/tools/deploy.sh
@@ -1,32 +1,107 @@
 #!/bin/bash
 # PAILot iOS Deploy Script
+#
+# Installs a personal (Pro-unlocked) PAILot build onto one or more iOS devices.
+#
+# ── Remote / "fully remote" targets ────────────────────────────────────────
+# Installation uses `xcrun devicectl device install`, which reaches the device
+# over Apple's CoreDevice tunnel — USB, local network, OR any routable network
+# path where the device is paired (e.g. across Tailscale). There is NO special
+# remote logic to add: once a device has been paired, `--device <id>` works
+# whether it sits on your desk or across the world, as long as it is awake and
+# reachable. That is exactly how the iPad here installs — it is a `localNetwork`
+# device, never plugged in. (First-time discovery of a NEW device uses .local /
+# mDNS, which does not cross networks, so a device must be paired at least once
+# on the local network before it can be driven fully remotely.)
+# Check reachability any time with:  bash tools/deploy.sh --check
+#
+# ── Usage ──────────────────────────────────────────────────────────────────
+#   bash tools/deploy.sh              # Matthias' iPhone (default)
+#   bash tools/deploy.sh -a           # Amelie's iPhone
+#   bash tools/deploy.sh -i           # Matthias' iPad
+#   bash tools/deploy.sh --all        # every known device (continues on failure)
+#   bash tools/deploy.sh --device ID  # explicit CoreDevice identifier (any remote device)
+#   bash tools/deploy.sh --build      # force a fresh Pro-unlocked build first
+#   bash tools/deploy.sh --check      # list devices devicectl can currently reach
 set -euo pipefail
 
 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
 APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
-
 cd "$APP_DIR"
 
-# Device UDIDs
-MATTHIAS="8708CADC-3330-50B6-AA0A-1655526A573A"
-DEVICE="$MATTHIAS"
+IPA="build/ios/ipa/pailot.ipa"
+
+# Known devices — CoreDevice identifiers from `xcrun devicectl list devices`.
+IPHONE_MATTHIAS="8708CADC-3330-50B6-AA0A-1655526A573A"
+IPHONE_AMELIE="E3F823F4-8DC8-5C88-948E-C7FA2B4C4C72"
+IPAD_MATTHIAS="8037E780-6BC0-5B9D-9ED4-D8F28DEEFD3F"
+
+TARGETS=()          # entries: "identifier|label"
+FORCE_BUILD=false
 
 while [[ $# -gt 0 ]]; do
   case "$1" in
-    -a) DEVICE="$AMELIE"; shift ;;
-    *) shift ;;
+    -a|--amelie) TARGETS+=("$IPHONE_AMELIE|Amelie's iPhone"); shift ;;
+    -i|--ipad)   TARGETS+=("$IPAD_MATTHIAS|Matthias' iPad"); shift ;;
+    --iphone)    TARGETS+=("$IPHONE_MATTHIAS|Matthias' iPhone"); shift ;;
+    --all)
+      TARGETS+=("$IPHONE_MATTHIAS|Matthias' iPhone" \
+                "$IPAD_MATTHIAS|Matthias' iPad" \
+                "$IPHONE_AMELIE|Amelie's iPhone")
+      shift ;;
+    --device)    TARGETS+=("$2|device $2"); shift 2 ;;
+    --build)     FORCE_BUILD=true; shift ;;
+    --check)     echo "=== Devices devicectl can reach ==="; xcrun devicectl list devices; exit 0 ;;
+    -h|--help)   sed -n '2,30p' "$0"; exit 0 ;;
+    *) echo "Unknown option: $1" >&2; exit 2 ;;
   esac
 done
 
-# Build first if no IPA exists
-if [[ ! -f build/ios/ipa/pailot.ipa ]]; then
-  echo "=== No IPA found, building first ==="
-  bash tools/build.sh
+# Default target: Matthias' iPhone.
+if [[ ${#TARGETS[@]} -eq 0 ]]; then
+  TARGETS+=("$IPHONE_MATTHIAS|Matthias' iPhone")
 fi
 
-echo "=== Installing on device $DEVICE ==="
-xcrun devicectl device install app --device "$DEVICE" build/ios/ipa/pailot.ipa
+# ── Build a Pro-unlocked personal IPA when needed ──────────────────────────
+# PAILOT_PRO unlocks Pro for personal / sideloaded installs ONLY. App Store
+# builds go through tools/build-appstore.sh / tools/release.sh, which do NOT
+# pass this define — paying users still see the paywall.
+if [[ "$FORCE_BUILD" == true || ! -f "$IPA" ]]; then
+  echo "=== Building Pro-unlocked IPA (PAILOT_PRO=true) ==="
+  flutter build ipa --release --no-pub --export-method development \
+    --no-tree-shake-icons --dart-define=PAILOT_PRO=true
+  ARCHIVE="build/ios/archive/Runner.xcarchive/Info.plist"
+  if [ -f "$ARCHIVE" ]; then
+    plutil -replace Name -string "PAILot" "$ARCHIVE" 2>/dev/null || true
+    plutil -replace SchemeName -string "PAILot" "$ARCHIVE" 2>/dev/null || true
+  fi
+else
+  echo "=== Using existing IPA: $IPA ==="
+  echo "    (Pro status depends on how it was built — use --build to force a fresh Pro build)"
+fi
+
+install_one() {
+  local id="$1" label="$2"
+  echo ""
+  echo "=== Installing on $label ($id) ==="
+  if xcrun devicectl device install app --device "$id" "$IPA"; then
+    echo "  OK: $label"
+  else
+    echo "  WARNING: install on $label failed — is it awake & reachable?"
+    echo "           Try: bash tools/deploy.sh --check"
+    return 1
+  fi
+}
+
+fail=0
+for t in "${TARGETS[@]}"; do
+  install_one "${t%%|*}" "${t#*|}" || fail=1
+done
 
 echo ""
-echo "=== Done ==="
-echo "Force-quit and reopen PAILot on your phone."
+if [[ $fail -eq 0 ]]; then
+  echo "=== Done — force-quit and reopen PAILot on the device(s). ==="
+else
+  echo "=== Done, with failures (see WARNINGs above). ==="
+  exit 1
+fi

--
Gitblit v1.3.1