Commit Graph
108 Commits
Author SHA1 Message Date
saphidandClaude Opus 5.5 c3ceea9bcd Merge main into analytics-and-updates: keep APK alternatives alongside Report a problem
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 19:39:38 +10:00
Alex Southwell dcf9689f64 Merge pull request #11 from saphid/apk-alternatives
Offer older APK versions that fit when Lepton refuses an app
kdeconnect-frame-24.02.2-1
2026-09-28 17:38:35 +10:00
saphidandClaude Opus 5.5 97d70d0c80 Merge origin/main: background install jobs and tabbed pages
Flatpak installs record their outcome inside main's background job; failed
jobs are diagnostics too. The Privacy panel lives on the Tools page (#privacy
opens it), tab analytics use the four page names, and "Test it now?" reads the
install job's result.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:37:28 +10:00
saphidandClaude Opus 5.5 9eeca79b5d Analytics, self-update and Report a problem
- Anonymous PostHog analytics (ui/frame_telemetry.py): usage on by default
  after a first-run notice; compatibility results and error details opt-in,
  offered together by the notice's "Share more to help fix problems" button.
  Random id, no person profiles or GeoIP, scrubbed text, an offline outbox,
  and "Show what's been sent" in the new Privacy panel. Inert without a
  project key, from a source checkout, or with DO_NOT_TRACK=1.
- APK installs now record install_failed when the APK itself won't install,
  and offer a 20-second test after installing. Opted-in reports reach the
  shared database through PostHog and `frame_compat_db.py sync`.
- The desktop app updates itself from published releases (app/updater.js):
  update.json from releases/latest/download, SHA-256 checked, no downgrades;
  macOS bundle swap, Windows NSIS, Linux AppImage, otherwise the release page.
  scripts/publish-release.sh publishes a tested draft with its manifest.
- Report a problem (header button, Privacy panel, Help menu) files a GitHub
  issue through the website's feedback API, with a previewed, scrubbed
  diagnostics snapshot; activity and logs only when asked for.

Reviewed by GPT-6 Astra (xhigh, read-only) three times; all findings fixed.
Docs: docs/privacy.md, docs/releasing.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:34:21 +10:00
saphidandClaude Opus 5.5 224340edc9 APK alternatives: refresh the catalogue after an install job; pin the test's premise
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:29:29 +10:00
saphidandClaude Opus 5.5 c814cb95d0 Merge main into apk-alternatives: install other versions as background jobs
Main now runs Android installs as background jobs and maps SSH failures to
one offline message. Alternative-version installs go through the same job,
the alternatives dialog waits on it with runJob, and send_error_json keeps
the apk blocker that opens the dialog.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:21:55 +10:00
Alex Southwell ff2c4ebfe0 Merge pull request #8 from fbl100/mac-mirror-verified
Mac → Frame mirror: verified, with fixes for scaling, login and the cursor
2026-09-28 17:20:22 +10:00
Alex Southwell 03322d3166 Merge pull request #5 from saphid/iphone-app
iPhone and iPad app: the same features, served from the Frame
2026-09-28 17:20:18 +10:00
Alex Southwell 2d08486278 Merge pull request #4 from saphid/ui-tabs-reliability
Tabs, one offline banner, background installs, drop anywhere
2026-09-28 17:19:46 +10:00
Alex Southwell f780ab2c6a Merge pull request #14 from saphid/site-polish
Website: crop the Tools screenshot and tighten the phone footer
2026-09-28 16:43:21 +10:00
saphidandClaude Opus 5.5 396f2a830a Website: crop the empty half off the Tools screenshot; tighten wrapped footer links
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:39:01 +10:00
Alex Southwell 59761ae015 Merge pull request #12 from saphid/website-kofi
Website: Ko-fi donate buttons and visual fixes
2026-09-28 16:34:18 +10:00
saphidandClaude Opus 5.5 48eedbc2eb Website: let the hero platform list wrap on phones so large text isn't clipped
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:31:39 +10:00
saphidandClaude Opus 5.5 2b89eeba1d Website: fix visual bugs found in a page-by-page review
- Gradient buttons showed a dark sliver on the right: the background shorthand reset
  background-origin, so the gradient repeated under the transparent border.
- Phone header: keep the brand on one line and drop the GitHub button under 480px.
- Hero pill: put the platform list on its own line on phones instead of orphaning one item.
- Privacy page: plain sections instead of open accordions whose x looked like a close button.
- Same header (GitHub button) and footer links on every page; legend spacing on the form.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:26:43 +10:00
saphidandClaude Opus 5.5 75e92db2fa Website: point the donate buttons at ko-fi.com/alexsouthwell; add FUNDING.yml
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:18:12 +10:00
Alex Southwell 10f96656e3 Merge pull request #10 from saphid/website
Website, feedback form that opens issues, and pi's contributor gate
2026-09-28 16:07:23 +10:00
saphidandClaude Opus 5.5 a1fa4ce140 Fix the cross-provider review's findings on APK alternatives
One malformed or unreachable repo no longer hides the others; skip bad
index entries; a refreshed raw index outdates its reduced copy; style the
dialog like the others; validate package ids with PKG_RE.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 15:15:11 +10:00
saphidandClaude Opus 5.5 a7663b3a5e Website feedback: double backslashes so escapes can't rebuild references; queue every approval
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:51:18 +10:00
saphidandClaude Opus 5.5 a6fff434a4 Website feedback: attribution first, escape <, wait out the fill timer; maintainers only in the approval queue
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:45:54 +10:00
saphidandClaude Opus 5.5 cd40a194ed Website feedback: escape & so entities can't rebuild mentions; queue only lgtm comments
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:39:54 +10:00
saphidandClaude Opus 5.5 0037b1ef4b Website feedback: fixes from review
- Rate limiting fails open on KV errors instead of dropping feedback
- Break owner/repo#1, GH-1 and github.com references in user text
- Time the form with the browser's monotonic clock, not wall-clock
- Serialize lgtm approvals and rebase before pushing

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:33:42 +10:00
saphidandClaude Opus 5.5 50405ccf88 Add IzzyOnDroid to APK alternatives; keep the catalogue's index file
Reducing an index no longer deletes apk-catalog/data/index-v2.json, which
the catalogue build reads. Drop the measurement log from docs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:30:15 +10:00
saphid 32196b4260 Reduce F-Droid indexes and fetch APK alternatives asynchronously 2026-09-28 14:26:40 +10:00
saphidandClaude Opus 5.5 7d328e20a5 Website with a feedback form that opens GitHub issues, and pi's contributor gate
- site/: landing page, /feedback/ and /privacy/ on Cloudflare Pages
  (frame-control.pages.dev). POST /api/feedback validates the form and opens
  a labelled issue with a fine-grained token; honeypot, minimum fill time and
  KV rate limits keep spam out. Ko-fi donate buttons appear once the page
  name is set in site/public/js/site.js.
- .github: the issue and PR gate from badlogic/pi-mono. New contributors'
  issues and PRs are auto-closed; a maintainer replying lgtmi/lgtm approves
  them via APPROVED_CONTRIBUTORS. Issue templates and CONTRIBUTING.md.
- CI runs the website tests; README points feedback at the form.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 14:26:33 +10:00
saphid fbe7ba9575 Find installable APK alternatives in F-Droid main and archive 2026-09-28 14:16:43 +10:00
Frank LevineandClaude Opus 5.5 5e12245932 Streaming doc: Mac → Frame mirror verified; move answered open questions
Tested on Frame BUILD_ID 20260925.6191901 with macOS 27.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:49:12 -04:00
Frank LevineandClaude Opus 5.5 df1810bae3 Add mac-cursor-ring.lua: show the Mac pointer in the VNC mirror
macOS leaves the pointer out of the Screen Sharing framebuffer, and neither Remmina showcursor setting brings it back. A Hammerspoon ring around the pointer is a real window, so it gets mirrored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:49:12 -04:00
Frank LevineandClaude Opus 5.5 3f0e7b198a install-apps: scale the Mac screen profile to fit; warn about the Mac login
Without scale-to-fit a Retina Mac shows 1:1 as a zoomed-in corner. macOS offers Apple auth ahead of plain VNC auth, so Remmina asks for the Mac account login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:49:12 -04:00
saphidandClaude Opus 5.5 9110557e23 README: link the Frame Control trailer
A thumbnail under the screenshot opens the 66-second trailer, which is attached to the 'trailer' release.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
v0.3.1
2026-09-27 22:07:44 +10:00
saphid 0016d9200c Merge remote-tracking branch 'origin/iphone-app' into iphone-app 2026-09-27 21:27:10 +10:00
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
Alex Southwell 1b26c4f92c Merge pull request #7 from saphid/fake-frame-tests
Regression tests against a fake Frame, plus a headset smoke test
2026-09-27 21:25:36 +10:00
saphidandClaude Opus 5.5 3db311da13 iPhone app: declare photo saving so Save Image appears; record what was tested
The share sheet only offers Save Image when the app declares
NSPhotoLibraryAddUsageDescription; without it screenshots couldn't be saved to
Photos. docs/iphone.md now lists what was verified against the Frame (Bonjour
discovery, waiting and reconnecting, upload, share sheet, install links,
opening Steam Link) and the two permission prompts iOS shows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 18:49:25 +10:00
saphidandClaude Opus 5.5 e1d138470f Fake Frame on arm64: use Valve's Holo Core image, and show failed builds
The menci/archlinuxarm base failed `pacman -Syu` on GitHub's arm64 runner.
Valve's Holo Core aarch64 preview is the base the Frame's SteamOS is built on,
the iPhone app's frame-container already uses it, and its repos carry every
package the fake needs. A failed image build now reruns with the full log.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 18:16:20 +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 19b9bc2dbe E2E: follow background jobs for Flatpak installs
The tabs UI (#4) runs Flatpak installs as server.start_job jobs, so a failed
install answers 200 with a job id and reports the error on /api/job. The test
now waits for the job instead of expecting an immediate 502.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:43:49 +10:00
saphidandClaude Opus 5.5 b768162139 Smoke test: read Steam's binary compat log with grep -a
On the Frame, compat_log.txt has binary bytes in it, so plain grep only said
"binary file matches" and the x86-64 launch check missed Steam's "is not
installed" line. The fake now writes that line to a compat_log.txt that starts
with a NUL, and the end-to-end test finds it the way the smoke test does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:40:09 +10:00
saphidandClaude Opus 5.5 56bbac4ddb Smoke test: wait for the evidence a launch needs; check the shortcut sync
A launch that needs the program running kept looking after Steam's
"started" line, rather than failing on it before the process showed up.
Cleanup reads steamos-delete's log, which reports a failed sync but exits
0, and runs it twice to check Steam no longer lists our titles; until then
they stay tracked and the cleanup step fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:40:09 +10:00
saphidandClaude Opus 5.5 93aebb5019 Fix the review's findings in the test harness
Headset smoke test: drop the paired key from authorized_keys with a
same-mode copy swapped in, so a failed write can't truncate it; check the
throwaway key with no ssh_config or agent; clean up idempotently (tracked
and leftover titles, their json files, Steam's shortcuts via steamos-delete,
and ~/devkit-utils if it wasn't there before), with a failed cleanup a
failed step; count a launch only with fresh evidence (the process, Steam's
log, or the known missing-runtime line), matching with [d]evkit-game so
pgrep doesn't find its own shell. The test programs sleep 10 s.

Fake Frame: log a launch before its reaper can look for it. e2e: kill a
pairing client's process group when a test ends; accept an aarch64 program
running under QEMU on x86 hosts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:40:09 +10:00
saphidandClaude Opus 5.5 0181071b83 Tests against a fake Frame, and a headset smoke test
tests/fakeframe: a container that stands in for the Frame (Arch Linux, or
Arch Linux ARM on arm64) with sshd, rsync, Valve's steamos-devkit-service
and hooks (vendored unmodified), a fake Steam client for the devkit pipe and
the DevTools port (the app's JavaScript runs in Node against stand-in
SteamClient/appStore objects), stubs for steam, wpctl, flatpak, podman,
Lepton and friends, battery and thermal files under /sys, and fault
switches (fakeframe-ctl): pairing mode, approve/deny/timeout, Steam not
running, headset asleep, sshd off, disk full, runtimes missing. A second
container is the computer running Frame Control.

tests/e2e: 29 tests driving the real ui/server.py, frame_connect.py and
frame_titles.py against it; skipped unless FRAME_E2E=1. scripts/e2e.sh
builds, runs and tears down; CI runs it on ubuntu-24.04-arm.

tests/smoke + scripts/frame-smoke.sh: the core cases against a real Frame,
recorded with its BUILD_ID, cleaning up after itself; --pair to pair a
throwaway key. docs/testing.md describes the layers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:40:09 +10:00
saphidandClaude Opus 5.5 ca2a991f03 Sideloaded titles: use ids Steam's create-shortcut accepts
On the Frame, Steam refused to register titles whose id had a hyphen
(fc-smoke-exe) with "missing/invalid arguments", and registered the same
program as FCSmokeProbe (headset smoke test, 2026-09-27, BUILD_ID
20260922.6101926). Valve's client only allows ^[A-Za-z_][A-Za-z0-9_.]+$.

title_id now makes ids of letters, digits and _, not starting with a
digit, 2 to 64 long; new installs are checked against that, while titles
already on the Frame are still listed, launched and removed. Steam's error
text is trimmed before it's quoted, and the "install it again with Steam
running" hint only follows a Steam-not-running error.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:40:09 +10:00
saphidandClaude Opus 5.5 10bf18fd50 Document the Frame's recovery images and what we learnt about the device
- docs/recovery-and-images.md: where Valve's Frame images are (not linked from
  the SteamOS download page), file names, sizes and our checksums, the GPT
  layout with exact start sectors, what's in rootfs-A (btrfs, SteamOS 0.3.0
  build 20260922.5152327, users, sudo and sshd config), extracting it, running
  it without the headset, and Valve/Collabora's Holo Core aarch64 preview.
- how-the-frame-works.md: correct the recovery image file names; add verified
  facts on the SSH server, tools on the image (no adb), Lepton instances as
  podman containers, going off the network when asleep, and the battery
  reading at full charge.
- ssh.md: pairing from an iPhone and why devkit RSA pairing doesn't fit it.
- open-questions.md, README.md and the steam-frame skill point to the new pages.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 17:25:01 +10:00
saphidandClaude Opus 5.5 d65f7130d5 Test against Valve's own Steam Frame OS from its recovery image
tests/frame-container/frame-image.sh extracts rootfs-A from Valve's Frame
recovery image (steamdeck-images.steamos.cloud/recovery), mounts it read-only
with a throwaway writable layer and starts the image's own sshd, so the iPhone
app can pair with and run its server on the real SteamOS for Frame userland.
Verified: password pairing then key login in the image's sshd log, the power
password check through the image's sudo, status reading SteamOS 0.3.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 16:59:01 +10:00
saphidandClaude Opus 5.5 13f629af35 WebXR doc: drop the stale not-verified list
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
trailer
2026-09-27 16:55:09 +10:00
saphidandClaude Opus 5.5 7efce19f4c WebXR doc: measured frame rate and controller input
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 16:54:48 +10:00
saphidandClaude Opus 5.5 623ce683d4 Document testing VR without wearing the headset; Steam-launched WebXR verified
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 16:47:57 +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 fd3a25434d iOS build: create the derived-files folder before packing the Frame bundle
A clean build (as in CI) hasn't made it yet.

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