From 0ff63012ecf81b27a6c0109c6928b224a568c9f0 Mon Sep 17 00:00:00 2001 From: Peter Kirkham Date: Mon, 4 May 2026 10:54:15 +0100 Subject: [PATCH] feat(code): cleaner GitHub integration onboarding step --- .../components/GitIntegrationStep.tsx | 167 ++++++++++++------ 1 file changed, 116 insertions(+), 51 deletions(-) diff --git a/apps/code/src/renderer/features/onboarding/components/GitIntegrationStep.tsx b/apps/code/src/renderer/features/onboarding/components/GitIntegrationStep.tsx index a1548d96e4..a790be1f39 100644 --- a/apps/code/src/renderer/features/onboarding/components/GitIntegrationStep.tsx +++ b/apps/code/src/renderer/features/onboarding/components/GitIntegrationStep.tsx @@ -18,7 +18,14 @@ import { GearSix, GitBranch, } from "@phosphor-icons/react"; -import { Box, Button, Callout, Flex, Skeleton, Text } from "@radix-ui/themes"; +import { + Box, + Button, + DropdownMenu, + Flex, + Skeleton, + Text, +} from "@radix-ui/themes"; import builderHog from "@renderer/assets/images/hedgehogs/builder-hog-03.png"; import { trpcClient } from "@renderer/trpc/client"; import { IS_DEV } from "@shared/constants/environment"; @@ -95,12 +102,25 @@ export function GitIntegrationStep({ const { repositories, isLoadingRepos } = useUserRepositoryIntegration(); const githubIntegration = githubUserIntegrations[0] ?? null; - const alternativeConnectedProject = useMemo(() => { - if (hasGitIntegration) return null; - if (!projectsWithGithub.length) return null; - return projectsWithGithub.find((p) => p.id !== selectedProjectId) ?? null; + const alternativeConnectedProjects = useMemo(() => { + if (hasGitIntegration) return []; + if (!projectsWithGithub.length) return []; + return projectsWithGithub.filter((p) => p.id !== selectedProjectId); }, [hasGitIntegration, projectsWithGithub, selectedProjectId]); + const [selectedAlternativeId, setSelectedAlternativeId] = useState< + number | null + >(null); + + const selectedAlternative = useMemo(() => { + if (!alternativeConnectedProjects.length) return null; + return ( + alternativeConnectedProjects.find( + (p) => p.id === selectedAlternativeId, + ) ?? alternativeConnectedProjects[0] + ); + }, [alternativeConnectedProjects, selectedAlternativeId]); + const repoSummary = useMemo(() => { if (repositories.length === 0) return null; const names = repositories.map((r) => r.split("/").pop() ?? r); @@ -364,33 +384,6 @@ export function GitIntegrationStep({ - {alternativeConnectedProject && selectedProject && ( - - - GitHub is already connected on{" "} - - {alternativeConnectedProject.name} - {" "} - ({alternativeConnectedProject.organization.name}). Switch to - that project, or click{" "} - Connect GitHub below to - install a new integration on{" "} - {selectedProject.name}. - - - - - - )} - {/* GitHub integration */} ) : !isLoading && !githubUserIntegrationsLoading ? ( - - - {timedOut - ? "We didn't hear back from GitHub. If the browser tab was closed, click Connect again." - : isConnecting - ? "Waiting for GitHub... You'll return here automatically once the install completes." - : "Optional. Unlocks cloud agents and pull request workflows."} - - - + selectedAlternative && + selectedProject && + !isConnecting && + !timedOut ? ( + + + GitHub is already connected on{" "} + {alternativeConnectedProjects.length > 1 ? ( + + + + + + {alternativeConnectedProjects.map((p) => ( + + setSelectedAlternativeId(p.id) + } + > + + {p.name} + + + {p.organization.name} + + + ))} + + + ) : ( + <> + + {selectedAlternative.name} + {" "} + ({selectedAlternative.organization.name}) + + )} + . + + + + + + + ) : ( + + + {timedOut + ? "We didn't hear back from GitHub. If the browser tab was closed, click Connect again." + : isConnecting + ? "Waiting for GitHub..." + : "Optional. Unlocks cloud agents and pull request workflows."} + + + + ) ) : null}