diff --git a/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx b/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx index 23e877ee058a..fc565b5327d8 100644 --- a/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx +++ b/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx @@ -15,7 +15,8 @@ import { MoreHorizontalIcon, PlusIcon, } from "lucide-react"; -import { useCallback, useMemo, useState } from "react"; +import { LegendList } from "@legendapp/list/react"; +import { memo, useCallback, useMemo, useState } from "react"; import { writeTextToClipboard } from "~/hooks/useCopyToClipboard"; import { findProjectForChangeRequest, useOpenPrLink } from "~/lib/openPullRequestLink"; @@ -29,7 +30,6 @@ import { formatRelativeTimeLabel } from "~/timestampFormat"; import { Button } from "../ui/button"; import { Menu, MenuItem, MenuPopup, MenuTrigger } from "../ui/menu"; import { MiddleTruncate } from "../ui/middle-truncate"; -import { ScrollArea } from "../ui/scroll-area"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { openLinkPullRequestDialog } from "./LinkPullRequestDialog"; import { pullRequestListLines, type PullRequestListLine } from "./pullRequestListLines"; @@ -78,7 +78,7 @@ function ChecksGlyph({ ); } -function LinkRow({ +function LinkRowImpl({ line, threadRef, projectId, @@ -326,6 +326,12 @@ function LinkRow({ ); } +/** Memoized so a modifier key or a sync of one link re-renders only the rows that changed. */ +const LinkRow = memo(LinkRowImpl); + +const lineKey = (line: PullRequestListLine) => + `${line.link.host}/${line.link.repository}#${line.link.number}`; + export function ThreadPullRequestsPanel({ threadRef }: { threadRef: ScopedThreadRef }) { const configs = useServerConfigs(); if (configs.get(threadRef.environmentId)?.environment.capabilities.threadPullRequests !== true) { @@ -403,6 +409,13 @@ function EnabledThreadPullRequestsPanel({ threadRef }: { threadRef: ScopedThread return latest; }, [links]); + // Legend re-renders visible rows only when data or extraData changes, so everything the rows + // read from outside their line goes in here. + const rowInputs = useMemo( + () => ({ speedMode, environmentProjects, capabilities, supportsWatch, thread }), + [speedMode, environmentProjects, capabilities, supportsWatch, thread], + ); + if (links.length === 0) { return (