mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 05:02:50 +02:00
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>
This commit is contained in:
1 parent
2e9bc8624b
commit
98ef6944c9
3 files changed
+34
-2
No files matched your search
+24
-1
@@ -258,6 +258,29 @@ ipcMain.on("devices:changed", (e, list) => {
|
||||
buildMenu();
|
||||
});
|
||||
const activeAlias = () => (devices.find(d => d.active) || {}).alias || FRAME;
|
||||
|
||||
// SSH through the server, so it goes to the headset and address the app is using
|
||||
// (with its own pinned identity), and refuses when there's none.
|
||||
function openSsh() {
|
||||
if (!url) return dialog.showErrorBox("Couldn't open SSH", "Frame Control's server isn't running.");
|
||||
const body = JSON.stringify({ what: "terminal" });
|
||||
const req = http.request(new URL("/api/open", url), {
|
||||
method: "POST", timeout: 15000,
|
||||
headers: { "Content-Type": "application/json", "X-Frame-UI": "1", "Content-Length": Buffer.byteLength(body) },
|
||||
}, (res) => {
|
||||
let data = "";
|
||||
res.on("data", (c) => { data += c; });
|
||||
res.on("end", () => {
|
||||
if (res.statusCode === 200) return;
|
||||
let why = `HTTP ${res.statusCode}`;
|
||||
try { why = JSON.parse(data).error || why; } catch {}
|
||||
dialog.showErrorBox("Couldn't open SSH", why);
|
||||
});
|
||||
});
|
||||
req.on("error", (e) => dialog.showErrorBox("Couldn't open SSH", e.message));
|
||||
req.on("timeout", () => req.destroy(new Error("the server didn't answer")));
|
||||
req.end(body);
|
||||
}
|
||||
function showDevices() {
|
||||
if (win && url) win.webContents.executeJavaScript('location.hash = "devices"').catch(() => {});
|
||||
}
|
||||
@@ -362,7 +385,7 @@ function buildMenu() {
|
||||
label: "Frame",
|
||||
submenu: [
|
||||
{ label: "Set Up Connection…", click: () => setUpConnection() },
|
||||
{ label: IS_MAC ? "Open SSH in Terminal" : "Open SSH in a Terminal", click: () => runInTerminal(["ssh", activeAlias()]) },
|
||||
{ label: IS_MAC ? "Open SSH in Terminal" : "Open SSH in a Terminal", click: openSsh },
|
||||
{ type: "separator" },
|
||||
...(devices.length > 1 ? [{
|
||||
label: "Headset",
|
||||
|
||||
@@ -278,6 +278,8 @@ class Connecting(unittest.TestCase):
|
||||
self.link.config_mtime = None
|
||||
self.link.watch_config()
|
||||
self.assertEqual(len(self.routes), routes) # an install is running: not yet
|
||||
self.link.connect(["dropped"]) # a reconnect meanwhile keeps the login it started with
|
||||
self.assertIn("User=steamos", self.routes[-1][1])
|
||||
running[0] = 0
|
||||
self.link.watch_config()
|
||||
self.assertIn("User=deck", self.routes[-1][1])
|
||||
|
||||
+8
-1
@@ -413,6 +413,7 @@ class Link:
|
||||
if before.get("transient") and not before.get("none") and self.routed is not None:
|
||||
# A bare alias is in use: a headset set up now doesn't take over by itself.
|
||||
self.override = self.override or before["alias"]
|
||||
self.session_alias = self.session_alias or before["alias"] # and stays on the list
|
||||
if self.reg.sync_from_config():
|
||||
self.devices_changed()
|
||||
after = self.active_device()
|
||||
@@ -435,9 +436,15 @@ class Link:
|
||||
why = self.describe(reasons)
|
||||
self.last_attempt = now()
|
||||
self.close_master()
|
||||
with self.route_lock:
|
||||
with self.work_lock, self.route_lock:
|
||||
gen = self.attempt_gen = self.gen
|
||||
device = self.active_device()
|
||||
if self.routed and self.routed[0] == device["id"] and self.route_key(device) != self.routed \
|
||||
and self.work():
|
||||
# Its login changed in ~/.ssh/config while an install runs: reconnect with the
|
||||
# one it started with; the change applies once it's done (see watch_config).
|
||||
device = dict(device, user=self.routed[1], port=self.routed[2])
|
||||
self.deferred = True
|
||||
if self.route_key(device) != self.routed:
|
||||
# Another headset, or a new user or port: nothing may go on using the old
|
||||
# route, even if this attempt fails.
|
||||
|
||||
Reference in new issue
Block a user