diff --git a/src/browser/features/Shared/DiffRenderer.tsx b/src/browser/features/Shared/DiffRenderer.tsx index 05fcdb3c9f..d0846f67d7 100644 --- a/src/browser/features/Shared/DiffRenderer.tsx +++ b/src/browser/features/Shared/DiffRenderer.tsx @@ -1,17 +1,16 @@ /** * DiffRenderer - Shared diff rendering component * Used by FileEditToolCall for read-only diff display. - * ReviewPanel uses SelectableDiffRenderer for interactive line selection. + * ReviewPanel and ImmersiveReviewView both use SelectableDiffRenderer for + * interactive line selection. */ import React, { useEffect, useMemo, useState } from "react"; -import { createPortal } from "react-dom"; import { stopKeyboardPropagation } from "@/browser/utils/events"; import { cn } from "@/common/lib/utils"; import { getLanguageFromPath } from "@/common/utils/git/languageDetector"; import { useOverflowDetection } from "@/browser/hooks/useOverflowDetection"; import { MessageSquare } from "lucide-react"; -import { TOOLTIP_SURFACE_CLASSNAME } from "@/browser/components/Tooltip/Tooltip"; import { InlineReviewNote, type ReviewActionCallbacks } from "./InlineReviewNote"; import { groupDiffLines } from "@/browser/utils/highlighting/diffChunking"; import { useTheme, type ThemeMode } from "@/browser/contexts/ThemeContext"; @@ -672,15 +671,6 @@ interface LineSelection { endIndex: number; } -interface TooltipAnchorRect { - left: number; - top: number; - width: number; - height: number; -} - -const REVIEW_COMMENT_TOOLTIP = "Add review comment (Shift-click or drag to select range)"; - // CSS class for diff line wrapper - used by arbitrary selector in CommentButton const SELECTABLE_DIFF_LINE_CLASS = "selectable-diff-line"; @@ -1029,49 +1019,6 @@ export const SelectableDiffRenderer = React.memo( const [selection, setSelection] = React.useState(null); const [selectionInitialNoteText, setSelectionInitialNoteText] = React.useState(""); - const reviewTooltipTriggerRef = React.useRef(null); - const [reviewTooltipAnchorRect, setReviewTooltipAnchorRect] = - React.useState(null); - - const hideReviewTooltip = React.useCallback((trigger?: HTMLButtonElement | null) => { - if (trigger && reviewTooltipTriggerRef.current !== trigger) { - return; - } - - reviewTooltipTriggerRef.current = null; - setReviewTooltipAnchorRect(null); - }, []); - - const syncReviewTooltipAnchor = React.useCallback(() => { - const trigger = reviewTooltipTriggerRef.current; - if (!trigger?.isConnected) { - hideReviewTooltip(); - return; - } - - const { left, top, width, height } = trigger.getBoundingClientRect(); - setReviewTooltipAnchorRect((previousRect) => { - if ( - previousRect?.left === left && - previousRect?.top === top && - previousRect?.width === width && - previousRect?.height === height - ) { - return previousRect; - } - - return { left, top, width, height }; - }); - }, [hideReviewTooltip]); - - const showReviewTooltip = React.useCallback( - (trigger: HTMLButtonElement) => { - reviewTooltipTriggerRef.current = trigger; - syncReviewTooltipAnchor(); - }, - [syncReviewTooltipAnchor] - ); - const flushPendingDragSelection = React.useCallback(() => { const anchorIndex = dragAnchorRef.current; const pendingLineIndex = pendingDragLineIndexRef.current; @@ -1139,34 +1086,6 @@ export const SelectableDiffRenderer = React.memo( }; }, []); - React.useEffect(() => { - if (!reviewTooltipAnchorRect) { - return; - } - - const handleViewportChange = () => { - syncReviewTooltipAnchor(); - }; - - window.addEventListener("resize", handleViewportChange); - window.addEventListener("scroll", handleViewportChange, true); - - return () => { - window.removeEventListener("resize", handleViewportChange); - window.removeEventListener("scroll", handleViewportChange, true); - }; - }, [reviewTooltipAnchorRect, syncReviewTooltipAnchor]); - - React.useEffect(() => { - if (!reviewTooltipTriggerRef.current) { - return; - } - - // File/hunk switches can remove the hovered trigger during a normal React render without any - // scroll/resize event, so resync here too to avoid leaving a stale floating tooltip behind. - syncReviewTooltipAnchor(); - }); - const { theme } = useTheme(); const lastExternalSelectionRequestIdRef = React.useRef(null); @@ -1368,8 +1287,6 @@ export const SelectableDiffRenderer = React.memo( return; } - hideReviewTooltip(); - // Notify parent that this hunk should become active. onLineClick?.(); onLineIndexSelect?.(lineIndex, shiftKey); @@ -1396,7 +1313,7 @@ export const SelectableDiffRenderer = React.memo( return { startIndex: anchor, endIndex: lineIndex }; }); }, - [hideReviewTooltip, onLineClick, onLineIndexSelect, onReviewNote, renderSelectionStartIndex] + [onLineClick, onLineIndexSelect, onReviewNote, renderSelectionStartIndex] ); const updateDragSelection = React.useCallback( @@ -1413,8 +1330,6 @@ export const SelectableDiffRenderer = React.memo( ); const handleCommentButtonClick = (lineIndex: number, shiftKey: boolean) => { - hideReviewTooltip(); - // Keep immersive cursor/hunk selection in sync with inline comment actions. onLineClick?.(); onLineIndexSelect?.(lineIndex, shiftKey); @@ -1573,17 +1488,13 @@ export const SelectableDiffRenderer = React.memo( reviewButton={ onReviewNote && ( <> - {/* Regular review can mount thousands of diff lines at once, so keep - one shared tooltip anchored to the active button instead of mounting - a full Radix tooltip tree for every individual line. */} + {/* Both review panes share SelectableDiffRenderer, so keep the + review action inline without an extra floating tooltip + covering nearby lines. */}