Commit Graph
8 Commits
Author SHA1 Message Date
saphidandClaude Opus 5.5 fe87a9d826 Keep the page clear of iOS safe areas everywhere; research typing, pointing and mirroring into the Frame
- Header, content, tab bar, status strip, drawer and toasts add the notch,
  Dynamic Island, rounded-corner and home-indicator insets on every side
  (zero on desktops). Phones on their side use the bottom tab bar layout.
- The phone tab bar hides while a text field has focus, instead of riding
  on the keyboard.
- DEBUG hook FRAME_TEST_LANDSCAPE for checking this in the Simulator.
- docs/streaming.md: iPhone mirroring (UxPlay, broadcast extension) and
  keyboard/mouse input (uinput needs no sudo on the Frame, verified).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 21:26:32 +10:00
saphidandClaude Opus 5.5 c711e136d4 iPhone app: a first screen that says exactly what to do
The app finds the Frame by itself (Valve's _steamos-devkit._tcp Bonjour
service, else the saved address or frame.local on port 22), so setup is two
numbered steps: wake your Frame (Looking… / Found ✓, and after a few seconds
exactly what to check), then the Developer Mode password and Connect. Manual
address and key options sit under Other ways to connect.

A paired Frame that doesn't answer is almost always asleep: instead of an
error, Waiting for your Frame says how to wake it and connects as soon as its
SSH port answers (checked every 3 s; 4 s after the stand-in came back).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 18:16:14 +10:00
saphidandClaude Opus 5.5 b1fa3afd40 Don't retry a pairing failure on returning to the app; README installs the docker client
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 15:48:43 +10:00
saphidandClaude Opus 5.5 aafd2dbda8 iPhone app: test pairing and power against a Holo Core stand-in
Valve publishes no Steam Frame OS image, so tests/frame-container builds the
Frame's SSH surface on Valve and Collabora's Holo Core aarch64 base: a
steamos user with a password and sudo, OpenSSH with keys and passwords,
Python, and a systemctl that only records requests.

Against it from the Simulator: password pairing, the host-key pin, the power
password check. Found and fixed: a changed host key or a refused login said
"Can't reach the Frame" and retried forever; they now say "Pair with the
Frame again" and offer that. The server's key rejection now says the header
may be wrong, not only missing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 15:44:42 +10:00
saphidandClaude Opus 5.5 db75d1ca71 iPhone app: verified against a Frame from the Simulator
Adds debug-only test hooks (open on a tab, run page JS, leave the tunnel URL in
Caches) used to drive the app in the Simulator, and records what was verified:
all four tabs with live data, capture and 31 fps live video in WKWebView, upload,
install jobs and the power password check through the app's tunnel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 15:26:23 +10:00
saphidandClaude Opus 5.5 14790ac768 Fix the follow-up review's findings
- Pairing saves nothing if it was cancelled while adding the key.
- The ssh stand-in runs under bash: dash refuses job control without a
  terminal, which cost stdin and the process group.
- A server that stops while the tunnel opens fails the attempt (and retries)
  instead of leaving it half-connected.
- The health probe answers within its deadline even when a dead link keeps
  the probe itself waiting.
- A cached version is deleted only if no server runs from it (servers now run
  by absolute path) and it's two weeks unused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 11:40:17 +10:00
saphidandClaude Opus 5.5 a910f83ac1 Fix the iPhone review's findings
- Cancelling (Change headset, Forget) invalidates the attempt in flight; a
  connection only becomes the app's once every step finished for it.
- A server that stops while the tunnel opens is noticed (exit callbacks are
  synchronised and replayed), and the app isn't left showing a dead page.
- The port is read only once the digits are complete, and range-checked.
- Other versions in ~/.cache/frame-control stay unless untouched for 14 days,
  so a second phone or iPad isn't cut off.
- The key is appended on its own line even if authorized_keys lacks a final
  newline.
- The app checks every 20 s, and on returning to the foreground, that the SSH
  session still answers, and reconnects if not.
- The ssh stand-in runs the command as its own process group and passes a
  TERM on to all of it, so a live-video ffmpeg stops with its stream.
- Touch screens show the library's Play buttons (the rule now follows the
  base one); the failure screen only says it's retrying when it is; the page
  says the app reconnects rather than naming a desktop menu.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 11:30:40 +10:00
saphidandClaude Opus 5.5 13187e8f6a iPhone and iPad app: the same features, served from the Frame
An iPhone can't run Python or ssh, but the Frame can. The app (ios/, SwiftUI)
connects with its own SSH key (Citadel), copies the server and helpers to
~/.cache/frame-control/<version> on the Frame once per version, starts
ui/server.py there with FRAME_LOCAL=1 on the Frame's 127.0.0.1, and shows the
page through an SSH tunnel. The server exits when the phone disconnects.

Server: FRAME_LOCAL=1 puts ui/local-bin on PATH, whose ssh stand-in runs each
`ssh frame COMMAND` locally (and serves as rsync's transport), so desktop and
phone share one code path. Android display goes through podman exec there, as
the Frame has no adb. FRAME_UI_KEY replaces the fixed X-Frame-UI value with a
per-session key. Power actions take the Developer Mode password via sudo -S.
--port 0 now prints the port it took.

Page: a bottom tab bar and safe areas on phones, Play buttons visible on touch
screens, saving through the share sheet, SSH/SFTP/Steam Link/remote desktop
opening in their iOS apps, and a password dialog for power.

App: pairing with the Developer Mode password once (never stored) or with a
key the user adds; host key pinned on first use; plain-language connection
errors with quiet retries; frame-control://install links; alerts and confirms.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 11:18:15 +10:00