From 9cac4b863b1bec6db94de830fd3fceefc6146ddc Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Thu, 30 Jul 2026 00:37:26 +0800 Subject: [PATCH] refactor(ui): rename RemoteConnections to HostLinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purely mechanical, plus the doc sentences that carry the model: the table holds one control link per machine, and the local machine is a machine like any other — its link just lives in its own global (LocalLink) because it is in-process rather than wire-backed. The old name framed the table as remote-only plumbing, which the tree migration made false in spirit: local and remote windows speak the same operations over whichever link their machine answers on. --- src/core/session.rs | 2 +- src/terminal/pane_liveness.rs | 4 ++-- src/terminal/view.rs | 4 ++-- src/ui/app.rs | 2 +- src/ui/local_link.rs | 15 ++++++------ src/ui/remote_connect.rs | 45 +++++++++++++++++------------------ src/ui/remote_workspace.rs | 22 ++++++++--------- src/ui/switcher.rs | 6 ++--- src/ui/tree_sync.rs | 4 ++-- src/ui/windows.rs | 2 +- 10 files changed, 52 insertions(+), 54 deletions(-) diff --git a/src/core/session.rs b/src/core/session.rs index b21739f0..e3b16c7a 100644 --- a/src/core/session.rs +++ b/src/core/session.rs @@ -216,7 +216,7 @@ impl WorkspaceStore { let Some(host) = Self::remote_ref(cx, id) else { return true; }; - crate::ui::remote_connect::RemoteConnections::get(cx, host.host_id()).is_some() + crate::ui::remote_connect::HostLinks::get(cx, host.host_id()).is_some() } /// The client-side entry for `host` — the existing one if this machine has diff --git a/src/terminal/pane_liveness.rs b/src/terminal/pane_liveness.rs index 75ccc8d6..99fcbe89 100644 --- a/src/terminal/pane_liveness.rs +++ b/src/terminal/pane_liveness.rs @@ -308,10 +308,10 @@ fn probe_host(cx: &mut App, host: HostId, workspace: WorkspaceId) { // // Recorded as a landed failure rather than returned from: a bare `return` // would leave `needs_probe` true, so the next frame would re-decide this, - // and `RemoteConnections::get` reaches its global mutably — which notifies, + // and `HostLinks::get` reaches its global mutably — which notifies, // which repaints, which sweeps. Storing the answer puts the decision behind // the same TTL as every other one. - if !host.is_local() && crate::ui::remote_connect::RemoteConnections::get(cx, host).is_none() { + if !host.is_local() && crate::ui::remote_connect::HostLinks::get(cx, host).is_none() { cx.update_global::(|cache, _| cache.finish_probe(host, None)); return; } diff --git a/src/terminal/view.rs b/src/terminal/view.rs index 0c1f8062..4f34c672 100644 --- a/src/terminal/view.rs +++ b/src/terminal/view.rs @@ -1599,7 +1599,7 @@ impl TerminalView { /// machine.** The host id comes off the workspace's own `RemoteTarget`, /// through the same `connection_key` the connection was opened under — so /// the id resolves to the very host object - /// [`RemoteConnections::insert`](crate::ui::remote_connect::RemoteConnections::insert) + /// [`HostLinks::insert`](crate::ui::remote_connect::HostLinks::insert) /// registered, with no second source of truth to drift from it. Setting the /// route and setting the host is one operation because a pane that ran its /// shell on one machine and its `git` on another would be worse than @@ -8053,7 +8053,7 @@ mod tests { /// (which needs a window, a daemon and a pane): the derivation under test is /// the target → `HostId` one, and pinning it here is what catches a future /// `set_workspace` that forgets the host half. The ids must agree with what - /// `RemoteConnections::insert` registered — same `connection_key`, checked + /// `HostLinks::insert` registered — same `connection_key`, checked /// by `connection_keys_match_the_contract_table` in `tty7-core`. #[test] fn a_panes_host_is_its_workspaces_machine() { diff --git a/src/ui/app.rs b/src/ui/app.rs index 04b32c80..ad0aae49 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -5894,7 +5894,7 @@ impl Tty7App { if !host.is_connected() { return None; } - let home = crate::ui::remote_connect::RemoteConnections::home(cx, host_id)?; + let home = crate::ui::remote_connect::HostLinks::home(cx, host_id)?; Some((host, Some(home))) } diff --git a/src/ui/local_link.rs b/src/ui/local_link.rs index 6372500a..8a190f41 100644 --- a/src/ui/local_link.rs +++ b/src/ui/local_link.rs @@ -1,16 +1,15 @@ //! The GUI's control link to **this machine's own daemon**. //! //! Local and remote machines are the same thing seen from different distances: -//! one machine, one daemon, one workspace tree, served over the control -//! dialect. The remote half of that has always held a `ControlClient` per -//! machine ([`crate::ui::remote_connect::RemoteConnections`]); this module is -//! the local half — the link over which the GUI receives the local daemon's -//! pushes (`ControlEvent::Layout` deltas, `Preempted`) and sends its semantic -//! tree operations. +//! one machine, one daemon, one workspace tree, one control link. The remote +//! machines' links live in [`crate::ui::remote_connect::HostLinks`]; this +//! module is the local machine's — the link over which the GUI receives the +//! local daemon's pushes (`ControlEvent::Layout` deltas, `Preempted`) and +//! sends its semantic tree operations. //! -//! # Not a `RemoteConnections` entry +//! # Not a `HostLinks` entry //! -//! `RemoteConnections` doubles as the [`crate::ui::host_registry::HostRegistry`] +//! `HostLinks` doubles as the [`crate::ui::host_registry::HostRegistry`] //! feeder: inserting there would register a *wire-backed* `Host` for this //! machine, while the local file tree and git must keep going through the //! in-process [`LocalHost`](tty7_core::host::local::LocalHost) — a socket diff --git a/src/ui/remote_connect.rs b/src/ui/remote_connect.rs index d94a92a8..44a3621e 100644 --- a/src/ui/remote_connect.rs +++ b/src/ui/remote_connect.rs @@ -15,7 +15,7 @@ //! | 2 | Resolve one into a self-contained SSH spec | [`spec_for`] | //! | 3 | Open a routed control connection through the local daemon | [`connect_blocking`] | //! | 4 | Read the machine's own workspace list | [`rows_from_list`] | -//! | 5 | Hold the connection for the workspaces bound to it | [`RemoteConnections`] | +//! | 5 | Hold the connection for the workspaces bound to it | [`HostLinks`] | //! //! ## Machines are configured once //! @@ -471,16 +471,21 @@ pub fn rows_from_machine(machine: &tty7_core::core::machine::Machine) -> Vec>, /// Each machine's `$HOME`, as its handshake reported it. /// @@ -496,24 +501,18 @@ pub struct RemoteConnections { homes: HashMap, } -impl Global for RemoteConnections {} +impl Global for HostLinks {} -impl RemoteConnections { +impl HostLinks { /// The connection to `id`, if this process has one. pub fn get(cx: &mut App, id: HostId) -> Option> { - cx.default_global::() - .hosts - .get(&id) - .cloned() + cx.default_global::().hosts.get(&id).cloned() } /// Where a *new* workspace on `id` would start: that machine's own `$HOME`, /// never this client's. pub fn home(cx: &mut App, id: HostId) -> Option { - cx.default_global::() - .homes - .get(&id) - .cloned() + cx.default_global::().homes.get(&id).cloned() } /// Record a connection, and register the same object with the host registry @@ -525,14 +524,14 @@ impl RemoteConnections { pub fn insert(cx: &mut App, host: Arc, home: PathBuf) { let id = host.id(); crate::ui::host_registry::HostRegistry::insert(cx, Arc::clone(&host).into_shared()); - let table = cx.default_global::(); + let table = cx.default_global::(); table.hosts.insert(id, host); table.homes.insert(id, home); } /// Drop a machine's connection once nothing is using it. pub fn remove(cx: &mut App, id: HostId) { - let table = cx.default_global::(); + let table = cx.default_global::(); table.hosts.remove(&id); table.homes.remove(&id); crate::ui::host_registry::HostRegistry::remove(cx, id); @@ -540,7 +539,7 @@ impl RemoteConnections { /// Machines currently connected. Diagnostics and teardown. pub fn len(cx: &mut App) -> usize { - cx.default_global::().hosts.len() + cx.default_global::().hosts.len() } } @@ -721,7 +720,7 @@ pub fn register(cx: &mut App) { crate::daemon::router::set_route_auth_responder(Arc::new(GuiRouteAuth)); // Touch the globals so the first connect isn't also the first allocation of // the table it writes into, on a thread that is holding a socket open. - let _ = RemoteConnections::len(cx); + let _ = HostLinks::len(cx); } /// The oldest install waiting for an answer, if any. diff --git a/src/ui/remote_workspace.rs b/src/ui/remote_workspace.rs index 618494f3..e136e4b7 100644 --- a/src/ui/remote_workspace.rs +++ b/src/ui/remote_workspace.rs @@ -661,10 +661,10 @@ impl Tty7App { rows: rows.clone(), }, ); - remote_connect::RemoteConnections::insert(cx, connected.host, home.clone()); + remote_connect::HostLinks::insert(cx, connected.host, home.clone()); self.prompt_remote_daemon_mismatch_later(cx); // Nothing left to *show* about the attempt: the machine is now - // in `RemoteConnections` and its group in the switcher fills + // in `HostLinks` and its group in the switcher fills // itself from there and from the snapshot above. self.connect = None; } @@ -762,7 +762,7 @@ impl Tty7App { return; }; remote_connect::register(cx); - if remote_connect::RemoteConnections::get(cx, host.host_id()).is_some() { + if remote_connect::HostLinks::get(cx, host.host_id()).is_some() { // Another window on the same machine got there first. One connection // per machine is the point — D7's "connect immediately" is about the // *machine*, and a second link to it would be a second SSH session @@ -1038,7 +1038,7 @@ pub(crate) const PUMP_TICK: Duration = Duration::from_millis(250); /// One machine's link, as the supervisor sees it. /// /// Per **machine**, not per workspace, because that is the granularity a -/// connection actually has (`RemoteConnections` is keyed by [`HostId`], and two +/// connection actually has (`HostLinks` is keyed by [`HostId`], and two /// windows on one box share a link). Preemption is the one thing that is /// per-workspace, and it is kept separately for exactly that reason. struct MachineLink { @@ -1234,7 +1234,7 @@ impl RemoteLinks { .preempted .remove(&workspace); } - remote_connect::RemoteConnections::remove(cx, host); + remote_connect::HostLinks::remove(cx, host); cx.default_global::().machines.remove(&host); log::info!("disconnected from a machine at the user's request"); cx.refresh_windows(); @@ -1295,8 +1295,8 @@ fn pump_tick(cx: &mut gpui::App) -> bool { if suspended.contains(&host) { continue; } - let live = remote_connect::RemoteConnections::get(cx, host) - .is_some_and(|h| h.client().is_connected()); + let live = + remote_connect::HostLinks::get(cx, host).is_some_and(|h| h.client().is_connected()); let attempting = cx .try_global::() .and_then(|l| l.machines.get(&host)) @@ -1326,8 +1326,8 @@ fn pump_tick(cx: &mut gpui::App) -> bool { // The link is down. Drop the dead host object so nothing keeps calling // into it — a control connection that has gone is the whole // workspace's lifeline, not one failed request. - if remote_connect::RemoteConnections::get(cx, host).is_some() { - remote_connect::RemoteConnections::remove(cx, host); + if remote_connect::HostLinks::get(cx, host).is_some() { + remote_connect::HostLinks::remove(cx, host); log::info!("lost the control connection to {target}; reconnecting"); } @@ -1473,7 +1473,7 @@ fn reconnect_after_restart(origin: &str, cx: &mut gpui::App) { let Some(host) = remote_connect::origin_host(origin) else { return; }; - remote_connect::RemoteConnections::remove(cx, host); + remote_connect::HostLinks::remove(cx, host); for (workspace, _) in workspaces_on(cx, host) { RemoteLinks::retry_now(cx, workspace); } @@ -1569,7 +1569,7 @@ fn finish_attempt( // comes back on after a restart or a dropped link, and dropping it // here is what left "New Workspace" missing on a machine the panel // was quite happily calling connected. - remote_connect::RemoteConnections::insert(cx, connected.host, connected.home); + remote_connect::HostLinks::insert(cx, connected.host, connected.home); for (id, _key) in workspaces_on(cx, host) { cx.default_global::().preempted.remove(&id); if restarted { diff --git a/src/ui/switcher.rs b/src/ui/switcher.rs index b0960e3f..0669db59 100644 --- a/src/ui/switcher.rs +++ b/src/ui/switcher.rs @@ -218,7 +218,7 @@ pub(crate) struct HostSnapshot { /// it could never be given a group to appear in. pub target: RemoteTarget, /// What the remote said it had. The machine's `$HOME` is deliberately *not* - /// here — it lives in `RemoteConnections`, app-wide, because every window + /// here — it lives in `HostLinks`, app-wide, because every window /// needs it and only one of them ever did the connecting. pub rows: Vec, } @@ -454,7 +454,7 @@ impl Tty7App { // connect, and every reconnect, records the machine's `$HOME` — and // that row is the only way to make a workspace on a machine, so it // has no business depending on which window did the connecting. - group.home = remote_connect::RemoteConnections::home(cx, id); + group.home = remote_connect::HostLinks::home(cx, id); if let Some(snapshot) = self.host_snapshots.get(&id) { group.merge(&snapshot.rows, now); } @@ -489,7 +489,7 @@ impl Tty7App { } _ => {} } - match remote_connect::RemoteConnections::get(cx, target.host_id()) { + match remote_connect::HostLinks::get(cx, target.host_id()) { Some(_) => Link::Connected, None => Link::Offline, } diff --git a/src/ui/tree_sync.rs b/src/ui/tree_sync.rs index f22c6b88..9bd3683d 100644 --- a/src/ui/tree_sync.rs +++ b/src/ui/tree_sync.rs @@ -66,7 +66,7 @@ use crate::ui::pane::{Pane, PaneSlot}; /// /// The unification the whole design leans on: the local machine's link lives in /// [`LocalLink`](crate::ui::local_link::LocalLink), a remote machine's in -/// [`RemoteConnections`](crate::ui::remote_connect::RemoteConnections), and +/// [`HostLinks`](crate::ui::remote_connect::HostLinks), and /// everything above this function stops caring which. `None` is always /// transient (both holders have supervisors reconnecting), so callers treat it /// as "not now": mark dirty and let the re-pull that follows reconnection @@ -75,7 +75,7 @@ pub(crate) fn control_for(cx: &mut App, host: HostId) -> Option