mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 12:00:37 +02:00
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>
27 lines
1.4 KiB
JavaScript
27 lines
1.4 KiB
JavaScript
// Lets the page read this computer's clipboard through Electron, so sending it
|
|
// to the Frame needs no pbpaste, PowerShell, xclip or wl-clipboard. Also tells
|
|
// the page where a dropped file or folder lives, so a folder can be sideloaded
|
|
// as a title without zipping it (the local server reads it from there).
|
|
// It can open Set Up Connection when the headset can't be reached, and keeps the
|
|
// Frame menu's list of headsets up to date.
|
|
// It also receives frame-control://install links (docs/web-install.md): only
|
|
// what the link asked for, never an install; the page asks the user first.
|
|
const { contextBridge, ipcRenderer, webUtils } = require("electron");
|
|
|
|
contextBridge.exposeInMainWorld("frameApp", {
|
|
readClipboard: () => ipcRenderer.invoke("clipboard:read"),
|
|
setUpConnection: () => ipcRenderer.invoke("connection:setup"),
|
|
// The Frame menu's headset switcher: the page tells it the headsets, and hears picks.
|
|
devicesChanged: (list) => ipcRenderer.send("devices:changed", list),
|
|
onUseDevice: (cb) => {
|
|
ipcRenderer.removeAllListeners("use-device");
|
|
ipcRenderer.on("use-device", (_e, id) => cb(String(id)));
|
|
},
|
|
pathForFile: (file) => { try { return webUtils.getPathForFile(file) || ""; } catch { return ""; } },
|
|
onInstallLink: (cb) => {
|
|
ipcRenderer.removeAllListeners("install-link");
|
|
ipcRenderer.on("install-link", (_e, req) => cb({ kind: req.kind, target: req.target }));
|
|
ipcRenderer.send("install-link:ready");
|
|
},
|
|
});
|