MCPcopy
hub / github.com/coder/mux / ReviewPanel

Function ReviewPanel

src/browser/features/RightSidebar/CodeReview/ReviewPanel.tsx:782–2667  ·  view source on GitHub ↗
({
  workspaceId,
  workspacePath,
  projectPath,
  onReviewNote,
  focusTrigger,
  isCreating = false,
  onStatsChange,
  isTouchImmersive = false,
  onTouchImmersiveChange,
})

Source from the content-addressed store, hash-verified

780};
781
782export const ReviewPanel: React.FC<ReviewPanelProps> = ({
783 workspaceId,
784 workspacePath,
785 projectPath,
786 onReviewNote,
787 focusTrigger,
788 isCreating = false,
789 onStatsChange,
790 isTouchImmersive = false,
791 onTouchImmersiveChange,
792}) => {
793 const originFetchRef = useRef<OriginFetchState | null>(null);
794 const { api } = useAPI();
795 const { theme } = useTheme();
796 const { workspaceMetadata } = useWorkspaceMetadata();
797 const panelRef = useRef<HTMLDivElement>(null);
798 const scrollContainerRef = useRef<HTMLDivElement>(null);
799 const searchInputRef = useRef<HTMLInputElement>(null);
800
801 useEffect(() => {
802 // Review is a code-heavy surface; warm the worker/highlighter during diff loading
803 // so immersive mode does not reveal plain text before Shiki is ready.
804 preloadHighlightedDiff({
805 content: "+const muxReviewSyntaxWarmup = true;",
806 filePath: "review-warmup.ts",
807 themeMode: theme,
808 }).catch(() => undefined);
809 }, [theme]);
810
811 // Unified diff state - discriminated union makes invalid states unrepresentable
812 // Note: Parent renders with key={workspaceId}, so component remounts on workspace change.
813 const [diffState, setDiffState] = useState<DiffState>({ status: "loading" });
814
815 const selectedHunkStorageKey = getReviewSelectedHunkKey(workspaceId);
816 // Keep hunk selection local during navigation; persisting every J/K step writes
817 // localStorage synchronously and dominates large immersive-review iteration.
818 const [selectedHunkId, setSelectedHunkId] = useState<string | null>(() =>
819 readPersistedState(selectedHunkStorageKey, null)
820 );
821 const [isLoadingTree, setIsLoadingTree] = useState(true);
822 const [diagnosticInfo, setDiagnosticInfo] = useState<DiagnosticInfo | null>(null);
823 const [isPanelFocused, setIsPanelFocused] = useState(false);
824 const [refreshTrigger, setRefreshTrigger] = useState(0);
825 const [fileTree, setFileTree] = useState<FileTreeNode | null>(null);
826
827 // Map of hunkId -> toggle function for expand/collapse
828 const toggleExpandFnsRef = useRef<Map<string, () => void>>(new Map());
829
830 // Ref to hold current filteredHunks for use in navigation callbacks.
831 // Avoids needing filteredHunks as a dependency (which changes frequently).
832 const filteredHunksRef = useRef<DiffHunk[]>([]);
833
834 // Track refresh trigger changes so we can distinguish initial mount vs manual refresh.
835 // Each effect gets its own ref to avoid cross-effect interference.
836 const lastDiffRefreshTriggerRef = useRef<number | null>(null);
837 const lastFileTreeRefreshTriggerRef = useRef<number | null>(null);
838
839 // Check if tools completed while we were unmounted - skip cache on initial mount if so.

Callers

nothing calls this directly

Calls 15

scheduleMethod · 0.95
requestImmediateMethod · 0.95
disposeMethod · 0.95
useAPIFunction · 0.90
useThemeFunction · 0.90
useWorkspaceMetadataFunction · 0.90
preloadHighlightedDiffFunction · 0.90
getReviewSelectedHunkKeyFunction · 0.90
readPersistedStateFunction · 0.90
usePersistedStateFunction · 0.90
getReviewSearchStateKeyFunction · 0.90

Tested by

no test coverage detected