aboutsummaryrefslogtreecommitdiff
path: root/src/client/shell/aggregate_navigation.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-19 15:43:47 +0300
committerGitHub <noreply@github.com>2026-09-19 15:43:47 +0300
commite0507237ad8d41f60aece10d00ef29ce2339ca34 (patch)
tree829503bc869cf76285953866367b74a90927a19d /src/client/shell/aggregate_navigation.rs
parentcc7c696cd0772e466da403eb4e3f00f4e8d8ae1e (diff)
feat: show every agent and terminal in the go to picker (#4384)
Diffstat (limited to 'src/client/shell/aggregate_navigation.rs')
-rw-r--r--src/client/shell/aggregate_navigation.rs143
1 files changed, 83 insertions, 60 deletions
diff --git a/src/client/shell/aggregate_navigation.rs b/src/client/shell/aggregate_navigation.rs
index c0195f93..9d3108cc 100644
--- a/src/client/shell/aggregate_navigation.rs
+++ b/src/client/shell/aggregate_navigation.rs
@@ -299,49 +299,92 @@ pub(super) fn navigator_rows(
let endpoint_query_matches = !query.is_empty() && text(&endpoint.label);
let mut endpoint_rows = Vec::new();
if let Some(snapshot) = endpoint.snapshot.as_deref() {
+ let agents = snapshot
+ .agents
+ .iter()
+ .map(|agent| (agent.pane_id.as_str(), agent))
+ .collect::<HashMap<_, _>>();
for workspace in &snapshot.workspaces {
- let workspace_meta = workspace.branch.clone().unwrap_or_default();
+ let workspace_matches = endpoint_query_matches
+ || text(&workspace.label)
+ || workspace.branch.as_deref().is_some_and(text);
let mut children = Vec::new();
- for tab in snapshot
+ let workspace_tabs = snapshot
.tabs
.iter()
- .filter(|tab| tab.workspace_id == workspace.workspace_id)
- {
- let mut panes = Vec::new();
- for (index, pane) in snapshot
+ .filter(|tab| tab.workspace_id == workspace.workspace_id);
+ let multiple_tabs = workspace_tabs.clone().nth(1).is_some();
+ for tab in workspace_tabs {
+ let tab_matches = workspace_matches || text(&tab.label);
+ let tab_panes = snapshot
.panes
.iter()
.filter(|pane| pane.tab_id == tab.tab_id)
- .enumerate()
- {
- let agent = snapshot
- .agents
- .iter()
- .find(|agent| agent.pane_id == pane.pane_id);
+ .collect::<Vec<_>>();
+ for (index, pane) in tab_panes.iter().enumerate() {
+ let agent = agents.get(pane.pane_id.as_str()).copied();
let status = agent
.map_or(crate::api::schema::AgentStatus::Unknown, |agent| {
agent.agent_status
});
- let label = pane
+ let agent_kind = agent.and_then(|agent| {
+ agent.agent.as_deref().or(agent.display_agent.as_deref())
+ });
+ let name = pane
.label
- .clone()
- .or_else(|| agent.and_then(|agent| agent.name.clone()))
- .or_else(|| agent.and_then(|agent| agent.display_agent.clone()))
- .or_else(|| agent.and_then(|agent| agent.title.clone()))
- .unwrap_or_else(|| format!("pane {}", index + 1));
+ .as_deref()
+ .or_else(|| agent.and_then(|agent| agent.name.as_deref()));
+ let title = agent.and_then(|agent| {
+ agent
+ .title
+ .as_deref()
+ .or(agent.terminal_title_stripped.as_deref())
+ });
+ let tab_name = (tab.custom_label || tab.label.parse::<usize>().is_err())
+ .then_some(tab.label.as_str());
+ let label = if tab_panes.len() == 1 {
+ match name.or(tab_name).or(title) {
+ Some(label) => label.to_owned(),
+ None if multiple_tabs => {
+ format!("{} · {}", agent_kind.unwrap_or("terminal"), tab.label)
+ }
+ None => workspace.label.clone(),
+ }
+ } else {
+ let pane_name = name.or(title).or(agent_kind).unwrap_or("terminal");
+ match tab_name {
+ Some(tab_name) if tab_name != pane_name => {
+ format!("{tab_name} · {pane_name} · {}", index + 1)
+ }
+ _ => format!("{pane_name} · {}", index + 1),
+ }
+ };
let meta = pane
.foreground_cwd
- .clone()
- .or_else(|| pane.cwd.clone())
+ .as_deref()
+ .or(pane.cwd.as_deref())
.unwrap_or_default();
- if !filtering
- || filter(status)
- && (endpoint_query_matches || text(&label) || text(&meta))
+ if filter(status)
+ && (tab_matches
+ || text(&label)
+ || text(meta)
+ || pane.cwd.as_deref().is_some_and(text)
+ || agent_kind.is_some_and(text)
+ || title.is_some_and(text)
+ || agent
+ .and_then(|agent| agent.display_agent.as_deref())
+ .is_some_and(text)
+ || text(&pane.pane_id))
{
- panes.push(ClientNavigatorRow {
- depth: 2 + depth_offset,
+ children.push(ClientNavigatorRow {
+ depth: 1 + depth_offset,
label,
- meta,
+ meta: meta.to_owned(),
+ detail: format!(
+ "{} / {} / {}",
+ workspace.label, tab.label, pane.pane_id
+ ),
+ agent: agent_kind.map(str::to_owned),
status: Some(status),
stale,
current: endpoint.endpoint_id == *active_endpoint_id
@@ -353,40 +396,17 @@ pub(super) fn navigator_rows(
});
}
}
- if !filtering
- || filter(tab.agent_status) && (endpoint_query_matches || text(&tab.label))
- || !panes.is_empty()
- {
- children.push(ClientNavigatorRow {
- depth: 1 + depth_offset,
- label: tab.label.clone(),
- meta: format!(
- "{} panes",
- snapshot
- .panes
- .iter()
- .filter(|pane| pane.tab_id == tab.tab_id)
- .count()
- ),
- status: None,
- stale,
- current: false,
- target: ClientNavigatorTarget::Tab {
- endpoint_id: endpoint.endpoint_id.clone(),
- tab_id: tab.tab_id.clone(),
- },
- });
- children.extend(panes);
- }
}
- let workspace_matches = filter(workspace.agent_status)
- && (endpoint_query_matches || text(&workspace.label) || text(&workspace_meta));
- if !filtering || workspace_matches || !children.is_empty() {
- let key = (endpoint.endpoint_id.clone(), workspace.workspace_id.clone());
+ if !filtering
+ || !children.is_empty()
+ || (navigator.filter.is_none() && !query.is_empty() && workspace_matches)
+ {
endpoint_rows.push(ClientNavigatorRow {
depth: depth_offset,
label: workspace.label.clone(),
- meta: workspace_meta,
+ meta: workspace.branch.clone().unwrap_or_default(),
+ detail: workspace.new_workspace_cwd.clone(),
+ agent: None,
status: None,
stale,
current: false,
@@ -395,9 +415,7 @@ pub(super) fn navigator_rows(
workspace_id: workspace.workspace_id.clone(),
},
});
- if navigator.expanded_workspaces.contains(&key) || filtering {
- endpoint_rows.extend(children);
- }
+ endpoint_rows.extend(children);
}
}
}
@@ -407,6 +425,8 @@ pub(super) fn navigator_rows(
depth: 0,
label: endpoint.label.to_owned(),
meta: String::new(),
+ detail: String::new(),
+ agent: None,
status: None,
stale,
current: false,
@@ -427,7 +447,10 @@ pub(super) fn navigator_selected_index(
) -> Option<usize> {
match navigator.selected.as_ref() {
Some(target) => rows.iter().position(|row| row.target == *target),
- None => (!rows.is_empty()).then_some(0),
+ None => rows
+ .iter()
+ .position(|row| matches!(row.target, ClientNavigatorTarget::Pane { .. }))
+ .or_else(|| (!rows.is_empty()).then_some(0)),
}
}