Skip to content
Merged
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
16 changes: 12 additions & 4 deletions apps/web/src/components/ChatView.browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1461,21 +1461,24 @@ async function waitForProductionStyles(): Promise<void> {

async function waitForElement<T extends Element>(
query: () => T | null,
errorMessage: string,
errorMessage: string | (() => string),
): Promise<T> {
// Lazy messages read the DOM at failure time, so a timeout reports what
// actually rendered instead of only what was expected.
const resolveMessage = () => (typeof errorMessage === "string" ? errorMessage : errorMessage());
let element: T | null = null;
await vi.waitFor(
() => {
element = query();
expect(element, errorMessage).toBeTruthy();
expect(element, resolveMessage()).toBeTruthy();
},
{
timeout: 8_000,
interval: 16,
},
);
if (!element) {
throw new Error(errorMessage);
throw new Error(resolveMessage());
}
return element;
}
Expand Down Expand Up @@ -1928,7 +1931,12 @@ async function waitForCommandPaletteShortcutLabel(): Promise<void> {
async function waitForCommandPaletteInput(placeholder: string): Promise<HTMLInputElement> {
return waitForElement(
() => document.querySelector(`input[placeholder="${placeholder}"]`) as HTMLInputElement | null,
`Command palette input with placeholder "${placeholder}" did not render.`,
() => {
const palette = document.querySelector('[data-testid="command-palette"]');
const actual = palette?.querySelector("input")?.getAttribute("placeholder") ?? "<no input>";
const paletteState = palette ? "open" : "closed";
return `Command palette input with placeholder "${placeholder}" did not render (palette ${paletteState}, actual placeholder: "${actual}").`;
},
);
}

Expand Down
12 changes: 11 additions & 1 deletion apps/web/src/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -842,13 +842,13 @@
buildProjectActionItems({
projects,
valuePrefix: "project",
icon: (project) => (
<ProjectFavicon
environmentId={project.environmentId}
cwd={project.cwd}
className={ITEM_ICON_CLASS}
/>
),

Check warning on line 851 in apps/web/src/components/CommandPalette.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint, Typecheck, Test, Browser Test, Build

react(no-unstable-nested-components)

Do not define components during render.
runProject: openProjectFromSearch,
}),
[openProjectFromSearch, projects],
Expand All @@ -859,13 +859,13 @@
buildProjectActionItems({
projects,
valuePrefix: "new-thread-in",
icon: (project) => (
<ProjectFavicon
environmentId={project.environmentId}
cwd={project.cwd}
className={ITEM_ICON_CLASS}
/>
),

Check warning on line 868 in apps/web/src/components/CommandPalette.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint, Typecheck, Test, Browser Test, Build

react(no-unstable-nested-components)

Do not define components during render.
runProject: async (project) => {
await startNewThreadInProjectFromContext(
{
Expand Down Expand Up @@ -896,24 +896,24 @@
...(activeThreadId ? { activeThreadId } : {}),
projectTitleById,
sortOrder: settings.sidebarThreadSortOrder,
icon: (thread) => {
const project = projectByScopedKey.get(
scopedProjectKey(scopeProjectRef(thread.environmentId, thread.projectId)),
);
if (!project) {
return <MessageSquareIcon className={ITEM_ICON_CLASS} />;
}
if (project.kind === "general-chat") {
return <MessagesSquareIcon className={ITEM_ICON_CLASS} />;
}
return (
<ProjectFavicon
environmentId={project.environmentId}
cwd={project.cwd}
className={ITEM_ICON_CLASS}
/>
);
},

Check warning on line 916 in apps/web/src/components/CommandPalette.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint, Typecheck, Test, Browser Test, Build

react(no-unstable-nested-components)

Do not define components during render.
renderLeadingContent: (thread) => <ThreadRowLeadingStatus thread={thread} />,
renderTrailingContent: (thread) => <ThreadRowTrailingStatus thread={thread} />,
runThread: async (thread) => {
Expand Down Expand Up @@ -1312,9 +1312,19 @@
if (openIntent?.kind !== "add-project") {
return;
}
// Environments hydrate a beat after the palette can open, and this
// intent is one-shot: consuming it against an empty environment list
// turned an add-project click during startup into a dead end. Hold the
// intent until an environment exists (closing the palette clears it);
// this effect re-runs when the options arrive. Hosted-static tabs know
// immediately that no local environment is coming, so they proceed
// straight to the pairing guidance.
if (addProjectEnvironmentOptions.length === 0 && !isHostedStaticApp()) {
return;
}
clearOpenIntent();
openAddProjectFlow();
}, [clearOpenIntent, openAddProjectFlow, openIntent]);
}, [addProjectEnvironmentOptions.length, clearOpenIntent, openAddProjectFlow, openIntent]);

// Sidebar "Search all N threads" hands off here: a submenu view scoped to
// one logical project's threads, searchable with the usual palette ranking.
Expand Down
Loading