* feat(app): expand command center actions Keep command center navigation stable by revealing only clipped rows without smooth centering. Prioritize a concise default list while making workspace, Git, pane, and creation actions searchable through the existing contribution and action-policy paths. * test(app): search for query-only command action Add project is intentionally absent from the unfiltered command center. Exercise the overlay flow through search before selecting it.
176 lines
5.1 KiB
TypeScript
176 lines
5.1 KiB
TypeScript
import type { GitAction, GitActions } from "@/git/policy";
|
|
import type { KeyboardActionDefinition } from "@/keyboard/keyboard-action-dispatcher";
|
|
import type { ShortcutKey } from "@/utils/format-shortcut";
|
|
import type { CommandCenterContribution, CommandCenterIcon } from "./contributions";
|
|
|
|
export interface WorkspaceCommandCenterLabels {
|
|
section: string;
|
|
newAgent: string;
|
|
newTerminal: string;
|
|
newBrowser: string;
|
|
splitRight: string;
|
|
splitDown: string;
|
|
}
|
|
|
|
export interface WorkspaceCommandCenterIcons {
|
|
newAgent?: CommandCenterIcon;
|
|
newTerminal?: CommandCenterIcon;
|
|
newBrowser?: CommandCenterIcon;
|
|
splitRight?: CommandCenterIcon;
|
|
splitDown?: CommandCenterIcon;
|
|
git?(action: GitAction): CommandCenterIcon | undefined;
|
|
}
|
|
|
|
export interface WorkspaceCommandCenterShortcuts {
|
|
newAgent?: ShortcutKey[][];
|
|
newTerminal?: ShortcutKey[][];
|
|
splitRight?: ShortcutKey[][];
|
|
splitDown?: ShortcutKey[][];
|
|
archiveWorkspace?: ShortcutKey[][];
|
|
}
|
|
|
|
export interface WorkspaceCommandCenterSource {
|
|
gitActions: GitActions;
|
|
labels: WorkspaceCommandCenterLabels;
|
|
icons: WorkspaceCommandCenterIcons;
|
|
shortcuts: WorkspaceCommandCenterShortcuts;
|
|
capabilities: {
|
|
canSplitPanes: boolean;
|
|
canOpenBrowserTabs: boolean;
|
|
};
|
|
dispatch(action: KeyboardActionDefinition): void;
|
|
runGitAction(action: GitAction): void;
|
|
}
|
|
|
|
function buildGitContribution(
|
|
source: WorkspaceCommandCenterSource,
|
|
action: GitAction,
|
|
rank: number,
|
|
visibility: "always" | "query",
|
|
): CommandCenterContribution {
|
|
return {
|
|
id: `git:${action.id}`,
|
|
group: "workspace",
|
|
groupRank: -1,
|
|
rank,
|
|
keywords: [action.id, "git"],
|
|
visibility,
|
|
run: () => source.runGitAction(action),
|
|
presentation: {
|
|
kind: "action",
|
|
title: action.label,
|
|
sectionTitle: source.labels.section,
|
|
icon: source.icons.git?.(action),
|
|
shortcutKeys:
|
|
action.id === "archive-workspace" ? source.shortcuts.archiveWorkspace : undefined,
|
|
},
|
|
};
|
|
}
|
|
|
|
function buildWorkspaceAction(input: {
|
|
source: WorkspaceCommandCenterSource;
|
|
id: string;
|
|
rank: number;
|
|
title: string;
|
|
keywords: readonly string[];
|
|
icon?: CommandCenterIcon;
|
|
shortcutKeys?: ShortcutKey[][];
|
|
action: KeyboardActionDefinition;
|
|
visibility: "always" | "query";
|
|
}): CommandCenterContribution {
|
|
return {
|
|
id: input.id,
|
|
group: "workspace",
|
|
groupRank: -1,
|
|
rank: input.rank,
|
|
keywords: input.keywords,
|
|
visibility: input.visibility,
|
|
run: () => input.source.dispatch(input.action),
|
|
presentation: {
|
|
kind: "action",
|
|
title: input.title,
|
|
sectionTitle: input.source.labels.section,
|
|
icon: input.icon,
|
|
shortcutKeys: input.shortcutKeys,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function buildWorkspaceCommandCenterContributions(
|
|
source: WorkspaceCommandCenterSource,
|
|
): CommandCenterContribution[] {
|
|
const contributions: CommandCenterContribution[] = [
|
|
buildWorkspaceAction({
|
|
source,
|
|
id: "tab:new-agent",
|
|
rank: 0,
|
|
title: source.labels.newAgent,
|
|
keywords: ["tab", "new", "agent", "chat"],
|
|
icon: source.icons.newAgent,
|
|
shortcutKeys: source.shortcuts.newAgent,
|
|
action: { id: "workspace.tab.new", scope: "workspace" },
|
|
visibility: "always",
|
|
}),
|
|
];
|
|
const primary = source.gitActions.primary;
|
|
if (primary) contributions.push(buildGitContribution(source, primary, 1, "always"));
|
|
contributions.push(
|
|
buildWorkspaceAction({
|
|
source,
|
|
id: "tab:new-terminal",
|
|
rank: 2,
|
|
title: source.labels.newTerminal,
|
|
keywords: ["terminal", "shell", "console"],
|
|
icon: source.icons.newTerminal,
|
|
shortcutKeys: source.shortcuts.newTerminal,
|
|
action: { id: "workspace.terminal.new", scope: "workspace" },
|
|
visibility: "query",
|
|
}),
|
|
);
|
|
if (source.capabilities.canOpenBrowserTabs) {
|
|
contributions.push(
|
|
buildWorkspaceAction({
|
|
source,
|
|
id: "tab:new-browser",
|
|
rank: 3,
|
|
title: source.labels.newBrowser,
|
|
keywords: ["browser", "web", "preview"],
|
|
icon: source.icons.newBrowser,
|
|
action: { id: "workspace.browser.new", scope: "workspace" },
|
|
visibility: "query",
|
|
}),
|
|
);
|
|
}
|
|
if (source.capabilities.canSplitPanes) {
|
|
contributions.push(
|
|
buildWorkspaceAction({
|
|
source,
|
|
id: "pane:split-right",
|
|
rank: 4,
|
|
title: source.labels.splitRight,
|
|
keywords: ["split", "pane", "vertical"],
|
|
icon: source.icons.splitRight,
|
|
shortcutKeys: source.shortcuts.splitRight,
|
|
action: { id: "workspace.pane.split.right", scope: "workspace" },
|
|
visibility: "query",
|
|
}),
|
|
buildWorkspaceAction({
|
|
source,
|
|
id: "pane:split-down",
|
|
rank: 5,
|
|
title: source.labels.splitDown,
|
|
keywords: ["split", "pane", "horizontal"],
|
|
icon: source.icons.splitDown,
|
|
shortcutKeys: source.shortcuts.splitDown,
|
|
action: { id: "workspace.pane.split.down", scope: "workspace" },
|
|
visibility: "query",
|
|
}),
|
|
);
|
|
}
|
|
for (const [index, action] of source.gitActions.secondary.entries()) {
|
|
if (action.id === primary?.id) continue;
|
|
contributions.push(buildGitContribution(source, action, 10 + index, "query"));
|
|
}
|
|
return contributions;
|
|
}
|