Commit Graph
184 Commits
Author SHA1 Message Date
saphidandClaude Opus 5.5 038dcd48cd Treat bare activity names as package-relative when matching the alias target
Third review follow-up (PackageParser.buildClassName). Confirmed the
targetActivity resource id 0x01010202 in Open Saber Plus's manifest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:04:55 +10:00
saphidandClaude Opus 5.5 71200c5179 Merge origin/main into mac-in-headset
Brings in #4, #5, #8 (fbl100's verified Remmina/VNC mirror), APK
alternatives and the website. docs/streaming.md: Mac in the headset stays
the recommendation (now verified on the Frame); Remmina keeps #8's verified
evidence as the whole-screen fallback. docs/mac-in-headset.md cites #8's
lag finding.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:03:34 +10:00
saphidandClaude Opus 5.5 00b45bafc5 Mac in the headset: final benchmark numbers; relay delay is a delay line
Review round 8 (GPT-6 Astra xhigh): --delay paused upstream reads, so busy
streams saw 30-60 ms instead of 30. Verified locally: 60-62 ms round trip
with 30 ms each way under load. No saved result used --delay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:02:26 +10:00
saphidandClaude Opus 5.5 9e4dcdd147 Mac in the headset: measure every frame, adapt to the network, separate windows
- Per-frame timing on the Mac's clock (capture, encode, network, decode,
  draw), viewer clock sync and reports, input echo, /stats and a HUD.
- scripts/macview-bench.py: repeatable runs on the real Frame, a shaping
  relay (no sudo), interleaved A/B between agent settings; results in
  bench/results/.
- Adaptive controller: ack-based send gate with jitter-aware slack, AIMD
  bitrate that knows when a stream is app-limited, fps then size tiers.
  On a 50->3->50 Mbit/s step, scroll p95 went from 4.7 s to 72 ms; no cost
  on a clean link.
- Separate mode: real AppKit event loop (HiDPI and NSScreen now work),
  cropped capture for fixed-size windows, windows kept on their display,
  graceful quit restores windows; stop/start races fixed.
- Encoder timeline clamp (no oversized frame after a pause).
- Frame Control shows each live stream's fps, delay, bitrate and tier.

Reviewed by GPT-6 Astra xhigh (read-only), 7 rounds; findings fixed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:56:14 +10:00
saphidandClaude Opus 5.5 9e9e5950d0 Patch the activity the launcher alias targets, not the first MAIN filter
Second review follow-up: with several activities (e.g. a splash activity ahead
of the game), the alias fallback now prefers the real activity named by the
alias's android:targetActivity. Reads targetActivity by resource id, updates
the error text and docs/vr-apks.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:55:56 +10:00
saphidandClaude Opus 5.5 268afccf05 APK sources: shared interface for source modules
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:52:30 +10:00
saphidandClaude Opus 5.5 e1c0ac983c Repair alias-only launchers for flat apps too; never fail on a VR alias
Review follow-up. inspect() now returns 'repairable' and the filters it can
patch: the real activity's VR MAIN filter, or, when LAUNCHER/VR sits only on an
<activity-alias>, any real MAIN filter with a category to copy. install() and
patch() repair on 'repairable' instead of 'vr_activity', so a flat Godot 4
export is fixed and a VR category only on the alias no longer aborts install.
Tests cover both shapes, an already-launchable activity with an alias, and an
end-to-end patch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:40:16 +10:00
saphidandClaude Opus 5.5 33a92a2e1d Tests: run in a sandbox that can't touch real app data, telemetry or the shared database
On a maintainer's Mac the compatibility-database key is in the Keychain, so a
test that reached install reporting published fake reports. Every test module
now imports tests/sandbox.py first, which points app data at a throwaway
directory (new FRAME_CONTROL_DATA_DIR), turns telemetry off and sends the
database nowhere.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:20:27 +10:00
saphidandClaude Opus 5.5 077eab2b79 Add LAUNCHER to the real VR activity when only an activity-alias has it
Lepton's apk-info-extractor ignores <activity-alias>, and Godot 4 exports put
LAUNCHER only on an alias (com.godot.game.GodotAppLauncher). Open Saber Plus
0.7.67 installed but Lepton exited with 'APP_ACTIVITY is empty'. Count only
real activities as launchable and patch the activity's VR intent filter.
Verified on the Frame: Open Saber Plus launches and renders.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:19:38 +10:00
saphidandClaude Opus 5.5 f076527722 Send analytics to the existing PostHog project; make bug reports private
- Analytics go to the maintainer's PostHog US project 343535, tagged
  $lib = frame-control. Every event carries $ip 0.0.0.0, since PostHog
  stores the sender's address otherwise (checked live), including events
  queued by earlier versions.
- Report a problem sends a private problem_report event to PostHog instead
  of a public GitHub issue, with its own random id so a contact address
  can't be linked to analytics. The dialog asks how to reach the person and
  shows a reference. Maintainers read reports on the PostHog dashboard or
  with `python3 ui/frame_report.py inbox`.
- Community sync pages by timestamp in UTC: PostHog refuses OFFSET for
  personal API keys.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:14:36 +10:00
saphidandClaude Opus 5.5 e67802f15d Tests: keep the blocked-upload test from reaching real install reporting
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:11:48 +10:00
saphidandClaude Opus 5.5 73eef14ecd Report APKs refused before install; offer a compatibility test after installing an alternative
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 19:44:44 +10:00
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
saphid 35ef3af54b Merge remote-tracking branch 'origin/main' into vr-apks
# Conflicts:
#	ui/frame_android.py
#	ui/index.html
2026-09-28 17:49:47 +10:00
saphidandClaude Opus 5.5 f10282294d Fix the cross-provider review's findings on VR APK support
patch() turns corrupt-manifest struct/index errors into FrameError; a missing
layer build says so; the signing key falls back to a rename where hard links
aren't supported and explains how to recover from a bad cached key; the layer
nulls an instance it can't destroy and logs xrLocateSpaces once.

Not changed: the 1.1 Meta profile names match xr.xml's promoted names
(meta/touch_pro_controller, meta/touch_plus_controller), and grip_surface is
palm_ext renamed, so the rewrite stays (now commented).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:47:35 +10:00
saphid 6217b5f2fa Merge remote-tracking branch 'origin/main' into frame-input 2026-09-28 17:43:27 +10:00
saphidandClaude Opus 5.5 b9e31178f3 Keyboard and trackpad for the Frame, through its own KDE Connect
Home → Keyboard and trackpad, in every version of Frame Control (Mac,
Windows, Linux, iPhone, iPad) with nothing to install on the device in
your hand. On a phone: a trackpad (drag, tap, two-finger scroll and
right-click) and a field that types on the Frame. On a computer: click
the pad to pass the mouse and keyboard through; Esc to stop.

First-party route: ui/frame_input_agent.py runs on the Frame and talks
KDE Connect's LAN protocol (v7) to kdeconnectd as if it were a phone.
KDE Connect isn't on the image, but Valve's package repository has it;
the agent fetches it and four libraries into ~ (no root, survives
updates), starts it, pairs by itself (accepting over D-Bus), and stops
it again when the last device disconnects. Each device has its own
identity; a stuck KDE Connect is restarted once.

Verified against the real Frame (SteamOS 0.4.1): first-time install,
pairing, pointer moves from the Mac's server and the iPhone app
(Simulator), Mac and iPhone at once, two installs at once, a frozen
daemon replaced, and the daemon stopping when the app quits.

Reviewed by GPT-6 Astra (xhigh) over seven rounds; all findings fixed
except per-event delivery acknowledgement (documented known limit).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:42:19 +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 b393e90854 Keep the Frame awake during agent work
Steam's own idle timer (60 min on AC, 15 on battery) suspends the Frame,
and SSH work doesn't count as activity. scripts/keep-awake.sh on sets both
timers to Never through Steam's DevTools (reusing ui/frame_steam.py) and
holds a logind sleep inhibitor as a user unit; off releases the inhibitor
and restores the saved timers. Findings recorded in how-the-frame-works.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:23:06 +10:00
saphidandClaude Opus 5.5 45f720883a Docs: house style for announcing features and fixes
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:22:55 +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 50d5e14539 Inject the OpenXR compatibility layer into VR APKs on install
VR apps with an arm64 OpenXR loader get frame/openxr-compat's layer unless
--no-xr-compat; the app bundle ships the layer. Verified on the Frame: Wolvic's
Quest build gets through OpenXR start-up, Open Brush still reaches FOCUSED.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:33:14 +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
saphid fd15f1de4c Merge branch 'openxr-compat' into vr-apks 2026-09-28 16:29:11 +10:00
saphidandClaude Opus 5.5 064cf95f6d VR APK notes: Lepton's missing clipboard also stops the Godot XR Tools demo
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:29:11 +10:00
saphidandClaude Opus 5.5 8d75ede0ab OpenXR compat layer: keep the current refresh rate when SteamVR refuses a request
Quest apps ask for 72/90/120/144 Hz; SteamVR offers only the current rate and
Wolvic aborted on XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB. Verified on
the Frame: Wolvic's Quest build now reaches XR_SESSION_STATE_SYNCHRONIZED.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 16:29:06 +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
saphid 0dbe18d824 Add APK-local OpenXR 1.1 compatibility layer for Frame 2026-09-28 16:24:27 +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
saphid a1bc6522c3 Detect VR APKs and repair launchers with pure Python v2 signing 2026-09-28 16:16:56 +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 724b020e93 Document what it takes to run VR and Quest APKs in Lepton
Verified on the headset: hello_xr and Open Brush's Quest build run
immersively unmodified; Wolvic's Quest build needs a LAUNCHER category
and fails on SteamVR's Android runtime being OpenXR 1.0 only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 15:56:53 +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