mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 08:02:24 +00:00
fix(ui): show SSH state as a corner status dot in semantic colors
The SSH avatar drew a 2px border ring in theme tokens, which read as a second avatar shape next to the flat shell badge — and "connected" used theme.accent, the list-selection grey in this app, so the ring showed no state at all. Reuse the agent status_dot on the badge corner instead, colored from the same hardcoded palette as agent dots (amber connecting, green connected, red failed/disconnected, neutral for a foreground ssh); the tab strip's inline 6px dot picks up the same RGB values.
This commit is contained in:
+17
-12
@@ -2793,29 +2793,34 @@ impl Tty7App {
|
||||
}
|
||||
|
||||
/// The status-dot colour for a tab whose representative pane is an SSH
|
||||
/// session (PRD FR-E2): native panes are phase-coloured (connecting = warning,
|
||||
/// connected = accent, failed/disconnected = red); a foreground `ssh` typed
|
||||
/// into a shell gets a plain neutral dot. `None` for non-SSH tabs (no dot).
|
||||
pub(crate) fn tab_ssh_dot(&self, tab: &Tab, cx: &App) -> Option<gpui::Hsla> {
|
||||
/// session (PRD FR-E2), as an RGB value from the same hardcoded semantic
|
||||
/// palette as [`AgentStatus::dot_rgb`] — not the theme's UI tokens, which
|
||||
/// in this app are soft neutral fills (accent is the list-selection grey)
|
||||
/// and read as no state at all. Native panes are phase-coloured
|
||||
/// (connecting = amber, connected = green, failed/disconnected = red); a
|
||||
/// foreground `ssh` typed into a shell gets a plain neutral dot. `None`
|
||||
/// for non-SSH tabs (no dot).
|
||||
///
|
||||
/// [`AgentStatus::dot_rgb`]: crate::core::cli_agent::AgentStatus::dot_rgb
|
||||
pub(crate) fn tab_ssh_dot(&self, tab: &Tab, cx: &App) -> Option<u32> {
|
||||
use crate::daemon::protocol::SshPhase;
|
||||
let leaf = tab.pane.first_leaf()?;
|
||||
let v = leaf.read(cx);
|
||||
let theme = cx.theme();
|
||||
if let Some(phase) = v.ssh_phase() {
|
||||
// Native pane.
|
||||
let color = if v.ssh_disconnected() {
|
||||
theme.danger
|
||||
let rgb = if v.ssh_disconnected() {
|
||||
0xEF4444 // red: link lost
|
||||
} else {
|
||||
match phase {
|
||||
SshPhase::Connecting | SshPhase::Authenticating => theme.warning,
|
||||
SshPhase::Connected => theme.accent,
|
||||
SshPhase::Failed { .. } => theme.danger,
|
||||
SshPhase::Connecting | SshPhase::Authenticating => 0xF59E0B, // amber: in flight
|
||||
SshPhase::Connected => 0x22C55E, // green: link up
|
||||
SshPhase::Failed { .. } => 0xEF4444, // red: never made it
|
||||
}
|
||||
};
|
||||
Some(color)
|
||||
Some(rgb)
|
||||
} else if v.remote_context().is_some() {
|
||||
// A foreground `ssh` typed into a shell: a plain neutral dot.
|
||||
Some(theme.muted_foreground)
|
||||
Some(0x9CA3AF)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
+21
-9
@@ -147,7 +147,8 @@ impl Render for DragTab {
|
||||
}
|
||||
|
||||
impl Tty7App {
|
||||
/// The status dot pinned to an agent avatar's bottom-right corner: a solid
|
||||
/// The status dot pinned to a tab avatar's bottom-right corner (an agent's
|
||||
/// live status, or an SSH pane's connection phase): a solid
|
||||
/// `rgb` disc with a surface-colored separator ring so it reads as sitting
|
||||
/// on the badge. When `unread` (a finished turn you haven't looked at), the
|
||||
/// dot gains a crisp outer ring of the same hue — the dot's separator ring
|
||||
@@ -204,16 +205,17 @@ impl Tty7App {
|
||||
/// The leading avatar for a tab row/chip: a rounded badge that brands the
|
||||
/// tab by what's running in it — each session fronted with an icon. A
|
||||
/// recognized coding agent gets its brand mark — a white silhouette
|
||||
/// (gpui tints SVGs as an alpha mask) on the vendor accent; an SSH pane gets
|
||||
/// a terminal glyph ringed in its connection-status colour; a plain shell
|
||||
/// gets a neutral terminal glyph. An agent's live status rides the corner as
|
||||
/// a [`status_dot`](Self::status_dot). `size` is the badge's edge in px.
|
||||
/// (gpui tints SVGs as an alpha mask) on the vendor accent; a plain shell
|
||||
/// gets a neutral terminal glyph. Live status rides the corner as a
|
||||
/// [`status_dot`](Self::status_dot) — the agent's working/waiting/done, or
|
||||
/// an SSH pane's connection phase (`ssh`) — one corner-dot language for
|
||||
/// the whole avatar column. `size` is the badge's edge in px.
|
||||
pub(crate) fn tab_avatar(
|
||||
&self,
|
||||
agent: Option<crate::core::cli_agent::CLIAgent>,
|
||||
status: Option<crate::core::cli_agent::AgentStatus>,
|
||||
unread: bool,
|
||||
ssh: Option<gpui::Hsla>,
|
||||
ssh: Option<u32>,
|
||||
size: f32,
|
||||
cx: &App,
|
||||
) -> gpui::AnyElement {
|
||||
@@ -251,11 +253,11 @@ impl Tty7App {
|
||||
.into_any_element()
|
||||
}
|
||||
None => base
|
||||
.relative()
|
||||
.rounded_full()
|
||||
// A clearly-visible neutral disc (a neutral grey shell badge), not a
|
||||
// near-transparent tint — so the avatar column reads as a column.
|
||||
.bg(cx.theme().muted)
|
||||
.when_some(ssh, |d, c| d.border_2().border_color(c))
|
||||
.child(
|
||||
// A flush `>_` prompt (not the boxed `square-terminal`) so it
|
||||
// fills the badge at the same visual weight as a brand mark.
|
||||
@@ -264,6 +266,10 @@ impl Tty7App {
|
||||
.size(px(size * 0.56))
|
||||
.text_color(cx.theme().foreground.opacity(0.65)),
|
||||
)
|
||||
// SSH connection phase as a corner status dot — the same
|
||||
// element as an agent's, not a border ring around the badge
|
||||
// (a ring read as a second, differently-shaped avatar style).
|
||||
.when_some(ssh, |b, rgb| b.child(Self::status_dot(rgb, false, size, cx)))
|
||||
.into_any_element(),
|
||||
}
|
||||
}
|
||||
@@ -560,8 +566,14 @@ impl Tty7App {
|
||||
}),
|
||||
)
|
||||
// Leading SSH status dot when this tab hosts an SSH session.
|
||||
.when_some(ssh_dot, |c, color| {
|
||||
c.child(div().flex_shrink_0().size(px(6.)).rounded_full().bg(color))
|
||||
.when_some(ssh_dot, |c, rgb| {
|
||||
c.child(
|
||||
div()
|
||||
.flex_shrink_0()
|
||||
.size(px(6.))
|
||||
.rounded_full()
|
||||
.bg(gpui::rgb(rgb)),
|
||||
)
|
||||
})
|
||||
// Leading agent brand avatar, when a coding agent runs in this
|
||||
// tab — the vendor mark on its accent. Only agents get an avatar
|
||||
|
||||
Reference in New Issue
Block a user