import { ExternalLinkIcon, PaperclipIcon } from "lucide-react"; import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts"; import { createContext, useContext, useMemo } from "react"; import type { Options as ReactMarkdownOptions } from "react-markdown"; import { cn } from "~/lib/utils"; import { PULL_REQUESTS_PANEL_REF } from "~/rightPanelStore"; import ChatMarkdown from "../ChatMarkdown"; import { MediaVideoPlayer } from "../media/MediaVideoPlayer"; import { remarkPullRequestAutolinks, splitPullRequestBody } from "./pullRequestMarkdown.logic"; export const PullRequestMarkdownContext = createContext<{ repositoryUrl: string | null; threadRef: ScopedThreadRef | null; } | null>(null); /** Renders PR uploads inline, with retry and an original link when video playback fails. */ export function PullRequestMarkdown({ text, cwd, environmentId, threadRef, className, }: { text: string; cwd: string; environmentId: EnvironmentId; /** Thread the body is shown beside, so its links can open in that thread's in-app browser. */ threadRef?: ScopedThreadRef | null; className?: string; }) { const segments = splitPullRequestBody(text); const context = useContext(PullRequestMarkdownContext); const repositoryUrl = context?.repositoryUrl; const resolvedThreadRef = threadRef ?? context?.threadRef ?? undefined; const extraRemarkPlugins = useMemo>( () => (repositoryUrl ? [[remarkPullRequestAutolinks, { repositoryUrl }]] : []), [repositoryUrl], ); return (
svg]:text-muted-foreground/60", className, )} data-image-gallery > {segments.map((segment) => { if (segment.kind === "markdown") { return ( ); } if (segment.media === "video") { return ( ); } return ( // A plain anchor rather than the page's openExternal button: the desktop window // turns a blocked _blank into openExternal itself, and in a browser tab — where // there is no shell to call — this is the only one of the two that goes anywhere. Open attachment on GitHub ); })}
); }