Commit Graph
128 Commits
Author SHA1 Message Date
saphidandClaude Opus 5.5 42b51afc5a Devices: fixes from review round 20
- A jump host's own "Authenticated to" line no longer counts as the headset's,
  and a master that logs in but doesn't start lets the next address be tried.
- Devices tab changes refresh through the ordered list load, so a late answer
  can't undo a newer selection.
- A probe's time out starts after the name lookup: macOS can take 5 s to look
  up a .local name (found on the real Frame once its USB link went away).
- An attempt's ending is published from a method, not a return in finally.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 00:35:29 +10:00
saphidandClaude Opus 5.5 6597a90059 Devices: fixes from review round 19
- A switch the server refuses no longer drops answers the page is waiting for
  (an install's job id): only an actual change of headset does.
- Test now goes through a jump host when the alias uses one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 00:25:10 +10:00
saphidandClaude Opus 5.5 c3e3f2629c Devices: fixes from review round 18
- A set-up headset whose alias goes through a jump host (ProxyJump or
  ProxyCommand in ~/.ssh/config) is reached through it, address by address,
  still pinned per headset.
- A refused switch puts the header's switcher back on the headset in use.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 00:17:29 +10:00
saphidandClaude Opus 5.5 90fd2684ba Devices: fixes from review round 17
- A command that fails after a switch doesn't make the connector drop the new
  headset's connection.
- On first import, the app keeps using the `frame` headset even when Set Up
  Connection put another block above it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 00:08:36 +10:00
saphidandClaude Opus 5.5 fa05a4b310 Devices: fixes from review round 16
- Terminals, power and a reconnect's probes use the route commands have now
  (a pinned bare-alias destination, a login change still deferred).
- Saving port 22 keeps an explicit Port line where there was one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 00:00:00 +10:00
saphidandClaude Opus 5.5 93ebd34f2c Devices: fixes from review round 15
- A bare alias's route is pinned to where ~/.ssh/config sent it when it was
  routed (HostName, Port, User), so editing that file can't move an install.
- Renaming during an install is allowed: only a real user or port change waits.
- The Devices tab follows a network change even while the headset is offline.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 23:51:12 +10:00
saphidandClaude Opus 5.5 34e91988b1 Devices: fixes from review round 14
- Retry now (while connected) and Forget identity wait for running installs.
- Terminal windows get the headset's address by name, so a link-local IPv6
  zone never has to pass through Windows' console.
- Renaming the headset in use shows at once in the header.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 23:40:10 +10:00
saphidandClaude Opus 5.5 5874fe33f6 Devices: fixes from review round 13
- Every command to a set-up headset checks its pinned key
  (StrictHostKeyChecking=yes, whatever ~/.ssh/config says); only the
  connector's first handshake may save one.
- A reconnect during an install keeps the whole route it started with, also
  when a bare alias is set up meanwhile.
- Removing the headset FRAME_ALIAS named doesn't bring it back as a bare alias.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 23:31:22 +10:00
saphidandClaude Opus 5.5 98ef6944c9 Devices: fixes from review round 12
- A reconnect while an install runs keeps the login it started with; a new
  one from ~/.ssh/config applies after.
- Frame > Open SSH goes through the server, so it uses the same headset and
  address as the app and refuses when there's none.
- A bare frame alias in use when a headset is set up stays selectable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 23:21:19 +10:00
saphidandClaude Opus 5.5 2e9bc8624b Devices: fixes from review round 11
- A headset set up while a bare alias is in use doesn't take over by itself;
  a login change from ~/.ssh/config waits for running installs.
- Saving a headset writes only the login fields that changed, and only if the
  block still holds the old ones.
- SSH, SFTP, power and remote desktop open with the same headset and address
  as every other command, and refuse when there's no address.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 23:12:41 +10:00
saphidandClaude Opus 5.5 c69ea6266f Devices: fixes from review round 10
- Removing or moving the active headset's address waits for running installs,
  like switching.
- A volume change still waiting to be sent goes to the headset whose slider
  it was, and a switch cancels it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 23:03:27 +10:00
saphidandClaude Opus 5.5 43e19d17f6 Devices: fixes from review round 9
- A title waiting its turn to be read stays with the headset it was dropped
  on, and is dropped if the app switches meanwhile.
- Probes still finishing from an earlier attempt can't overwrite the rows of
  a newer one.
- The FRAME_ALIAS the server started with stays on the list after switching
  away, so it can be picked again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:55:14 +10:00
saphidandClaude Opus 5.5 175c39a2b0 Devices: fixes from review round 8
- A batch of dropped files stays with the headset it was dropped on, and
  stops if the app switches.
- Removing or moving the address in use reroutes at once; a headset with no
  addresses reaches nothing rather than whatever ~/.ssh/config says.
- A late answer to an older device-list request is ignored.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:45:34 +10:00
saphidandClaude Opus 5.5 51ef5d8283 Devices: fixes from review round 7
- Removing every headset leaves none in use (commands fail at once) instead of
  falling back to the `frame` alias.
- ssh goes to the IP that answered for IPv6 too, with a link-local address's
  interface (verified: frame.local over fe80::…%en9 on the real Frame).
- Find results only show in the panel of the headset they were for.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:35:43 +10:00
saphidandClaude Opus 5.5 ba33d2ff40 Devices: fixes from review round 6
- The headset a change is meant for is checked and the work counted in one
  step, so a switch can't slip in between (uploads too).
- A sideloaded title read on one headset can't be installed on another; open
  confirmations close on a switch.
- The only headset can't be removed while its ssh alias stays behind.
- Answers about the previous headset are dropped without touching panels; the
  catalogue's Installed tags are rebuilt for the new headset.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:24:46 +10:00
saphidandClaude Opus 5.5 41ac28248a Devices: fixes from review round 5
- A switch publishes the new headset at once, so the page clears the old one's
  panels and the lists behind them (games, store, Android apps, screenshots).
- The page names the headset its changes are for (X-Frame-Device); the server
  refuses one meant for a headset it has switched away from (409).
- A rejected address edit changes nothing.
- Test now goes to the IPv4 address that answered, like the connection.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:14:25 +10:00
saphidandClaude Opus 5.5 9dd57cde4e Devices: connector tests follow ssh to the IPv4 address that answered
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:01:49 +10:00
saphidandClaude Opus 5.5 d383a26746 Devices: fixes from review round 4
- A switch clears every headset-specific list and its buttons at once.
- SSH goes to the IPv4 address that answered the probe, not the name again.
- A rejected headset edit changes nothing.
- The SteamOS/Lepton builds recorded in reports are read again per headset.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:00:09 +10:00
saphidandClaude Opus 5.5 318bc3b84f Devices: make the pin folder before ssh saves a first-seen key into it
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:49:43 +10:00
saphidandClaude Opus 5.5 cb182dbce5 Devices: fixes from review round 3
- Attempts carry a generation: one overtaken by a switch, a removal or a login
  change routes nothing back to the old headset and can't report connected.
- Removing the active headset or changing its user/port reroutes at once,
  before anything that can fail.
- One known_hosts file per headset (~/.ssh/frame-control-hosts/<id>):
  forgetting one headset's key can't drop another's, whoever else writes.
- learn() checks, under the config lock, that the block is still what the
  attempt started from before writing to it.
- A switch stops live video and drops captures from the previous headset.
- A probe shares its time between the addresses a name resolves to.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:48:39 +10:00
saphidandClaude Opus 5.5 18334b5989 Devices: fixes from review round 2
- Switching headsets is serialized with the start of any install; background
  work counts as running from before its thread starts. use() reroutes every
  command at once and makes ensure() wait for the new headset.
- A new user or port reroutes commands even if the attempt then fails.
- ~/.ssh/config edits take a lock file shared with Set Up Connection
  (frame_connect.py and connect.sh, which now also writes atomically).
- A finished attempt no longer writes its older settings over a change Set
  Up Connection made meanwhile.
- Pin edits are locked and swapped atomically.
- A bare alias behind ProxyJump/ProxyCommand is left to ssh to reach.
- The page drops answers about the previous headset after a switch; the
  header switcher takes clicks in the macOS title bar.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:38:41 +10:00
saphidandClaude Opus 5.5 13eb65603b Devices: fixes from review round 1
- No switching headsets (or changing the active one's user/port, or removing
  it) while installs run: they read the ssh settings step by step.
- Switching reroutes every command to the new headset at once, even if it
  never answers.
- ~/.ssh/config edits are serialized, use unique temp files, and back off if
  another program wrote the file meanwhile.
- stop() ends a handshake in progress and joins the connector.
- Pinned keys are written unhashed (HashKnownHosts=no); hashed ones are still
  found and forgotten via ssh-keygen.
- Set Up Connection changing a headset's user or port updates the registry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 21:25:41 +10:00
saphidandClaude Opus 5.5 a954fc83c9 Devices: several headsets, several addresses each, and live connection status
Frame Control can now manage more than one Steam Frame, and reach each at any
of several addresses (LAN IPs per network, its .local name, Tailscale). A
connector in the server tries them all at once, picks the best one that
answers, follows ssh -v through each stage (network, finding, SSH, identity,
login) and streams that to the page. The header shows it live; a new Devices
tab (key 5) manages headsets, addresses and network names.

- ui/frame_devices.py: registry in devices.json, imported from the managed
  ~/.ssh/config blocks; per-headset host key pinning; config block updates.
- ui/frame_network.py: gateway IP+MAC fingerprint, Wi-Fi name, Tailscale.
- ui/frame_link.py: the connector, Test now, Tailscale/mDNS discovery, API.
- server.py: ensure_master delegates to the connector; /api/connection,
  /api/connection/events (SSE), /api/devices.
- Electron: headset switcher and Devices item in the Frame menu.
- frame_connect.py --alias; FRAME_CONTROL_DATA_DIR / FRAME_CONTROL_SSH_DIR
  keep tests off real data.

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