import { isAtomCommandInterrupted } from "@t3tools/client-runtime/state/runtime"; import type { EnvironmentId, PullRequestRef } from "@t3tools/contracts"; import { cloneElement, useState, type ComponentPropsWithoutRef, type ReactElement } from "react"; import { formatRelativeTimeLabel } from "~/timestampFormat"; import { pullRequestEnvironment } from "~/state/pullRequests"; import { useAtomQueryRunner } from "~/state/use-atom-query-runner"; import { useEnvironmentQuery } from "~/state/query"; import { PreviewCard, PreviewCardPopup, PreviewCardTrigger } from "../ui/preview-card"; import { PullRequestActorAvatar, resolvePullRequestState } from "./pullRequestPresentation"; interface PullRequestLinkPreviewTarget { readonly environmentId: EnvironmentId; readonly input: PullRequestRef; } type PullRequestLinkElement = ReactElement>; export function PullRequestLinkPreview({ link, originalUrl, target, confirmBeforeOpen, onOpenPullRequest, onOpenFallback, }: { link: PullRequestLinkElement; originalUrl: string; target: PullRequestLinkPreviewTarget; confirmBeforeOpen: boolean; onOpenPullRequest: (url: string) => boolean; onOpenFallback: (url: string) => Promise; }) { const [open, setOpen] = useState(false); const [resolvingClick, setResolvingClick] = useState(false); const detailQuery = useEnvironmentQuery( open ? pullRequestEnvironment.detail({ environmentId: target.environmentId, input: target.input, }) : null, ); const readDetail = useAtomQueryRunner(pullRequestEnvironment.detail, { reportFailure: false, reportDefect: false, }); const trigger = confirmBeforeOpen ? cloneElement(link, { onClick: (event) => { if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); event.stopPropagation(); if (resolvingClick) return; setOpen(false); setResolvingClick(true); void readDetail({ environmentId: target.environmentId, input: target.input }) .then(async (result) => { if (isAtomCommandInterrupted(result)) return; if (result._tag === "Success" && onOpenPullRequest(result.value.url)) return; await onOpenFallback(originalUrl); }) .catch((error: unknown) => { console.error("[pull-request-link-preview] failed to open link", error); }) .finally(() => setResolvingClick(false)); }, }) : link; const detail = detailQuery.data; const state = detail === null ? null : resolvePullRequestState({ state: detail.state, isDraft: detail.isDraft }); const authorLabel = detail?.author === null ? "ghost" : detail?.author.name && detail.author.name !== detail.author.login ? `${detail.author.name} (@${detail.author.login})` : (detail?.author.login ?? null); return ( {detail === null ? (

{detailQuery.isPending ? "Loading pull request details…" : originalUrl}

) : (
{detail.repository} #{detail.number} · {state === null ? null : ( {state.label} )}

{detail.title}

{authorLabel} · opened {formatRelativeTimeLabel(detail.createdAt)}
)}
); }