mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 10:00:34 +02:00
Each screenshot card and the viewer get a Copy button that puts the image on the clipboard (natively in the desktop app, as PNG in a browser). Right-click a screenshot to open, copy, save, show it in Finder, or copy its path or name; right-click the viewer to copy or save. The shelf re-lists the Frame's screenshots every 8 s while the window is visible and connected, redraws only when something changed, and keeps thumbnails it already has. Switching headsets clears the list and ignores answers still on their way. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
47 lines
2.5 KiB
JavaScript
47 lines
2.5 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 put a screenshot on the clipboard as an image, 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.
|
|
// And it passes update state both ways: see app/updater.js.
|
|
const { contextBridge, ipcRenderer, webUtils } = require("electron");
|
|
|
|
contextBridge.exposeInMainWorld("frameApp", {
|
|
notify: (message, request) => ipcRenderer.invoke("comfort:notify", message, request),
|
|
readClipboard: () => ipcRenderer.invoke("clipboard:read"),
|
|
writeImage: (bytes) => ipcRenderer.invoke("clipboard:writeImage", bytes),
|
|
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)));
|
|
},
|
|
// While the keyboard-and-trackpad panel holds the keyboard, ⌘W, ⌘R and the rest go to the Frame.
|
|
captureKeys: (on) => ipcRenderer.send("keys:capture", !!on),
|
|
pathForFile: (file) => { try { return webUtils.getPathForFile(file) || ""; } catch { return ""; } },
|
|
// Updates (app/updater.js): the page shows a banner and an Update button.
|
|
update: {
|
|
get: () => ipcRenderer.invoke("update:get"),
|
|
check: () => ipcRenderer.invoke("update:check"),
|
|
install: () => ipcRenderer.invoke("update:install"),
|
|
onState: (cb) => {
|
|
ipcRenderer.removeAllListeners("update:state");
|
|
ipcRenderer.on("update:state", (_e, s) => cb(s));
|
|
},
|
|
},
|
|
// Help → Report a Problem… opens the page's report dialog (ui/frame_report.py).
|
|
onReportProblem: (cb) => {
|
|
ipcRenderer.removeAllListeners("report:open");
|
|
ipcRenderer.on("report:open", () => cb());
|
|
},
|
|
onInstallLink: (cb) => {
|
|
ipcRenderer.removeAllListeners("install-link");
|
|
ipcRenderer.on("install-link", (_e, req) => cb({ kind: req.kind, target: req.target }));
|
|
ipcRenderer.send("install-link:ready");
|
|
},
|
|
});
|