Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions apps/web/src/components/CommandPalette.logic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
buildLinkedThreadActionItems,
filterPinnedBrowseEntries,
filterCommandPaletteGroups,
resolveNewThreadProjectGroups,
reduceCommandPaletteUiState,
resolveAddProjectEntry,
createCommandPaletteSearchState,
Expand Down Expand Up @@ -920,6 +921,48 @@ describe("returning from file and content search", () => {
});
});

describe("open new-thread project choices", () => {
it("uses current choices and actions while preserving other submenus", async () => {
const staleRun = vi.fn(async () => undefined);
const currentRun = vi.fn(async () => undefined);
const action = (value: string, run = staleRun) => ({
kind: "action" as const,
value,
title: value,
searchTerms: [value],
icon: null,
run,
});
const stored = [
{
value: "new-thread-in",
label: "Projects",
items: [action("scratch"), action("checkout-a"), action("checkout-b")],
},
];
const current = [action("grouped-repository"), action("arriving-project", currentRun)];
const groups = resolveNewThreadProjectGroups(stored, current);
const visible = filterCommandPaletteGroups({
activeGroups: groups,
query: "",
isInSubmenu: true,
projectSearchItems: [],
threadSearchItems: [],
});
expect(visible.flatMap((group) => group.items.map((item) => item.title))).toEqual([
"grouped-repository",
"arriving-project",
]);
const arriving = visible[0]!.items[1]!;
if (arriving.kind !== "action") throw new Error("Expected a project action");
await arriving.run();
expect(currentRun).toHaveBeenCalledOnce();
expect(staleRun).not.toHaveBeenCalled();
const other = [{ ...stored[0]!, value: "projects" }];
expect(resolveNewThreadProjectGroups(other, current)).toBe(other);
});
});

it("resolves project metadata and browse roots within the active environment", () => {
const local = { title: "Local project", workspaceRoot: "/local/repo" };
const remote = { title: "Remote project", workspaceRoot: "/remote/repo" };
Expand Down
7 changes: 7 additions & 0 deletions apps/web/src/components/CommandPalette.logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,13 @@ export interface CommandPaletteGroup {
readonly items: ReadonlyArray<CommandPaletteActionItem | CommandPaletteSubmenuItem>;
}

export function resolveNewThreadProjectGroups(
groups: ReadonlyArray<CommandPaletteGroup>,
items: ReadonlyArray<CommandPaletteActionItem>,
): ReadonlyArray<CommandPaletteGroup> {
return groups[0]?.value === "new-thread-in" ? [{ ...groups[0], items }] : groups;
}

export interface CommandPaletteView {
readonly addonIcon: ReactNode;
readonly groups: ReadonlyArray<CommandPaletteGroup>;
Expand Down
17 changes: 8 additions & 9 deletions apps/web/src/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ import {
type CommandPaletteSubmenuItem,
type CommandPaletteView,
filterCommandPaletteGroups,
resolveNewThreadProjectGroups,
buildNestedSearchItems,
filterPinnedBrowseEntries,
getCommandPaletteInputPlaceholder,
Expand Down Expand Up @@ -244,7 +245,7 @@ import { threadRecentUse } from "@t3tools/shared/paletteSearch";

const EMPTY_BROWSE_ENTRIES: FilesystemBrowseResult["entries"] = [];
const ADD_PROJECT_ENTRY_GROUP = "add-project";
const NEW_THREAD_IN_GROUP = "projects";
const NEW_THREAD_IN_GROUP = "new-thread-in";

/** The submenu an open intent starts in; its groups resolve while rendering. */
function openIntentView(intent: CommandPaletteOpenIntent | null): CommandPaletteView | null {
Expand Down Expand Up @@ -1607,18 +1608,16 @@ function OpenCommandPaletteDialog(props: {
)
: currentView?.groups[0]?.value === ADD_PROJECT_ENTRY_GROUP
? addProjectEntryGroups()
: currentView?.groups[0]?.value === NEW_THREAD_IN_GROUP
? [{ value: NEW_THREAD_IN_GROUP, label: "Projects", items: projectThreadItems }]
: currentView?.groups[0]?.value === "themes"
? changeThemeItem.groups
: currentView?.groups[0]?.value === "appearance"
? changeAppearanceItem.groups
: (currentView?.groups ?? rootGroups);
: currentView?.groups[0]?.value === "themes"
? changeThemeItem.groups
: currentView?.groups[0]?.value === "appearance"
? changeAppearanceItem.groups
: (currentView?.groups ?? rootGroups);

const isLinkedThreadSearch =
linkedThreadSearch?.linkedThreads !== undefined && deferredQuery === linkedThreadSearch.query;
const filteredGroups = filterCommandPaletteGroups({
activeGroups,
activeGroups: resolveNewThreadProjectGroups(activeGroups, projectThreadItems),
query: deferredQuery,
isInSubmenu: currentView !== null,
...(deferredQuery.trim().length > 0
Expand Down
Loading