import { pipe } from "effect/Function"; import { ThreadDetailsControl } from "./ThreadDetailsControl"; import type { EnvironmentId, ScopedThreadRef, ThreadPullRequestLink } from "@t3tools/contracts"; import { pullRequestListLines, resolveThreadPullRequestChains, threadPullRequestKeyOf, visibleThreadPullRequests, } from "@t3tools/client-runtime/thread-pull-requests"; import { ChevronDown, ChevronUp } from "lucide"; import { useState, type ComponentProps, type MouseEvent as ReactMouseEvent } from "react"; import { sourceControlClients } from "@t3tools/client-runtime/source-control-clients"; import { findProjectOnChangeRequestHost } from "@t3tools/client-runtime/change-request-links"; import { useProjects } from "~/state/entities"; import { threadEnvironment } from "~/state/threads"; import { useAtomCommand } from "~/state/use-atom-command"; import { MorphIcon } from "~/components/MorphIcon"; import { linkedPullRequestSnapshotStatus, prStatusIndicator } from "../ThreadStatusIndicators"; import { ThreadDetailsPrRow } from "./ThreadDetailsPrRow"; function ThreadDetailsPrLinkRow({ environmentId, link, onOpen, onActed, onStopWatching, }: { environmentId: EnvironmentId; link: ThreadPullRequestLink; onOpen: (event: ReactMouseEvent) => void; onActed?: (() => void) | undefined; onStopWatching?: (() => void) | undefined; }) { const projects = useProjects(); const parsed = sourceControlClients.parseChangeRequestUrl(link.url)?.link; const project = parsed === undefined ? null : (findProjectOnChangeRequestHost( projects.filter((candidate) => candidate.environmentId === environmentId), parsed, ) ?? null); const linked = linkedPullRequestSnapshotStatus(link); const pr = linked?.pr ?? null; return ( ); } export function ThreadDetailsPrRows({ threadRef, links, currentLink, onOpenLink, ...row }: ComponentProps & { threadRef: ScopedThreadRef; links: ReadonlyArray; currentLink: ThreadPullRequestLink | null; onOpenLink: (event: ReactMouseEvent, url: string) => void; }) { const [expanded, setExpanded] = useState(false); const watch = useAtomCommand(threadEnvironment.watchPullRequest, { reportFailure: true }); const stopWatching = (link: ThreadPullRequestLink | null) => link?.watch === undefined ? undefined : () => void watch({ environmentId: threadRef.environmentId, input: { threadId: threadRef.threadId, host: link.host, repository: link.repository, number: link.number, watching: false, }, }); const currentRow = ; const rest = currentLink === null ? [] : pipe(visibleThreadPullRequests(links), resolveThreadPullRequestChains, pullRequestListLines) .map((line) => line.link) .filter((link) => threadPullRequestKeyOf(link) !== threadPullRequestKeyOf(currentLink)); if (rest.length === 0) return currentRow; return ( <> {currentRow} {expanded ? (
{rest.map((link) => ( onOpenLink(event, link.url)} onActed={row.onActed} onStopWatching={stopWatching(link)} /> ))}
) : null} setExpanded(!expanded)} part="row" tone="muted" className="w-full active:scale-100" > {expanded ? "Show less" : `Show ${rest.length} more`} ); }