fix(app): show project name in command center workspace search (#2345)

Searching the command center for a branch name like "master" returned a
Workspaces list where every row looked identical: the title was the
branch and the subtitle read "<hostname> · <branch>". On a single-host
machine the hostname repeats on every row, so there was no way to tell
which project each "master" workspace belonged to.

Add the project name to the workspace subtitle (host · project · branch)
and gate the host label behind multi-host, matching the Agents section.
The host is dropped on single-host setups, so the subtitle reads
"project · branch" and rows are distinguishable. Because searchText is
derived from the subtitle, typing a project name now matches its
workspaces too.

Extract the shared join into joinSubtitleParts() and route both the
workspace and agent subtitles through it, removing the duplicated
filter/join the Agents section hand-rolled.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Christoph Leiter
2026-07-24 21:15:50 +08:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 055db7454d
commit 19565f6605
4 changed files with 99 additions and 12 deletions
@@ -52,6 +52,7 @@ import type { CommandCenterContribution, CommandCenterIconProps } from "./contri
import { useCommandCenterActions, useCommandCenterContributions } from "./provider";
import {
buildContributionSections,
joinSubtitleParts,
moveActiveResultId,
preserveActiveResultId,
projectCommandCenterRows,
@@ -203,7 +204,7 @@ function useBuiltInSections(open: boolean, query: string): CommandCenterResultSe
const { t } = useTranslation();
const { agents } = useAggregatedAgents();
const { projects } = useProjects({ enabled: open });
const showAgentHost = useHosts().length > 1;
const showHost = useHosts().length > 1;
return useMemo(() => {
if (!open) return [];
@@ -213,9 +214,11 @@ function useBuiltInSections(open: boolean, query: string): CommandCenterResultSe
for (const workspace of host.workspaces) {
if (workspace.archivingAt) continue;
const title = workspace.title ?? workspace.name;
const subtitle = workspace.currentBranch
? `${host.serverName} · ${workspace.currentBranch}`
: host.serverName;
const subtitle = joinSubtitleParts([
showHost ? host.serverName : null,
project.projectName,
workspace.currentBranch,
]);
const searchText = `${title} ${subtitle}`.toLowerCase();
allWorkspaces.push({
kind: "workspace",
@@ -251,13 +254,11 @@ function useBuiltInSections(open: boolean, query: string): CommandCenterResultSe
? workspaceTitleByKey.get(`${agent.serverId}:${agent.workspaceId}`)
: undefined;
const location = workspaceTitle ?? shortenPath(agent.cwd);
const subtitle = [
showAgentHost ? agent.serverLabel : null,
const subtitle = joinSubtitleParts([
showHost ? agent.serverLabel : null,
location,
formatTimeAgo(agent.lastActivityAt),
]
.filter((part): part is string => Boolean(part))
.join(" · ");
]);
return {
kind: "agent",
id: `agent:${agent.serverId}:${agent.id}`,
@@ -282,7 +283,7 @@ function useBuiltInSections(open: boolean, query: string): CommandCenterResultSe
},
{ id: "agents", rank: 3, title: t("shell.commandCenter.agents"), results: agentResults },
];
}, [agents, open, projects, query, showAgentHost, t]);
}, [agents, open, projects, query, showHost, t]);
}
interface CommandCenterState {
@@ -461,7 +462,11 @@ function ResultContent({ result }: { result: CommandCenterResult }) {
<Text style={styles.title} numberOfLines={1}>
{result.title}
</Text>
<Text style={styles.subtitle} numberOfLines={1}>
<Text
style={styles.subtitle}
numberOfLines={1}
testID="command-center-workspace-subtitle"
>
{result.subtitle}
</Text>
</View>