diff --git a/packages/app/src/components/worktree-setup-callout-source.tsx b/packages/app/src/components/worktree-setup-callout-source.tsx index 12d5957ea..b566c643b 100644 --- a/packages/app/src/components/worktree-setup-callout-source.tsx +++ b/packages/app/src/components/worktree-setup-callout-source.tsx @@ -53,6 +53,9 @@ export function WorktreeSetupCalloutSource() { if (!activeProject || !shouldShowWorktreeSetupCallout(readQuery.data)) { return null; } + if (importAvailability.status === "loading") { + return null; + } if (importAvailability.status === "one" && importAvailability.source) { return buildProjectConfigImportCalloutPolicy(activeProject, { status: "one", diff --git a/packages/app/src/project-config-import/availability.ts b/packages/app/src/project-config-import/availability.ts new file mode 100644 index 000000000..13f59a520 --- /dev/null +++ b/packages/app/src/project-config-import/availability.ts @@ -0,0 +1,14 @@ +export type ProjectConfigImportAvailabilityStatus = "loading" | "none" | "one" | "many"; + +export function projectConfigImportAvailabilityStatus(input: { + availableCount: number; + isLoading: boolean; +}): ProjectConfigImportAvailabilityStatus { + if (input.isLoading) { + return "loading"; + } + if (input.availableCount === 0) { + return "none"; + } + return input.availableCount === 1 ? "one" : "many"; +} diff --git a/packages/app/src/project-config-import/project-config-import-model.test.ts b/packages/app/src/project-config-import/project-config-import-model.test.ts index a24e0a62d..df65c91a3 100644 --- a/packages/app/src/project-config-import/project-config-import-model.test.ts +++ b/packages/app/src/project-config-import/project-config-import-model.test.ts @@ -18,6 +18,7 @@ import { stripProjectConfigImportSearchParams, } from "./route"; import { projectConfigImportApplyFailureRetryAction } from "./retry"; +import { projectConfigImportAvailabilityStatus } from "./availability"; import { createProjectConfigImportSourceRegistry, type ProjectConfigImportSourceDescriptor, @@ -290,3 +291,14 @@ describe("project config import preview cache keys", () => { expect(calls).toEqual([protocolSource, protocolSource]); }); }); + +describe("project config import availability", () => { + it("waits for advertised source previews before reporting no imports", () => { + expect(projectConfigImportAvailabilityStatus({ availableCount: 0, isLoading: true })).toBe( + "loading", + ); + expect(projectConfigImportAvailabilityStatus({ availableCount: 0, isLoading: false })).toBe( + "none", + ); + }); +}); diff --git a/packages/app/src/project-config-import/use-project-config-import-model.ts b/packages/app/src/project-config-import/use-project-config-import-model.ts index cb8688c6d..53d718c23 100644 --- a/packages/app/src/project-config-import/use-project-config-import-model.ts +++ b/packages/app/src/project-config-import/use-project-config-import-model.ts @@ -33,6 +33,7 @@ import { projectConfigImportApplyFailureRetryAction, type ProjectConfigImportRetryAction, } from "./retry"; +import { projectConfigImportAvailabilityStatus } from "./availability"; const EMPTY_IMPORT_SOURCES: readonly ProjectConfigImportAdvertisedSource[] = []; type ProjectConfigImportPreviewSuccess = Extract; @@ -309,9 +310,13 @@ export function useProjectConfigImportAvailability(input: { const availableSourceKeys = new Set( availableSources.map((source) => stableProjectConfigImportSourceKey(source.source)), ); + const isLoading = previews.some((preview) => preview.isLoading || preview.isPending); return { - status: projectConfigImportAvailabilityStatus(availableSources.length), + status: projectConfigImportAvailabilityStatus({ + availableCount: availableSources.length, + isLoading, + }), source: availableSources.length === 1 ? availableSources[0] : null, sources: availableSources, availableKinds, @@ -319,13 +324,6 @@ export function useProjectConfigImportAvailability(input: { }; } -function projectConfigImportAvailabilityStatus(count: number): "none" | "one" | "many" { - if (count === 0) { - return "none"; - } - return count === 1 ? "one" : "many"; -} - function isRouteIntentCapabilityMissing(input: { intent: ProjectConfigImportIntent | null; routeIntent: ProjectConfigImportIntent | null;