import { useCallback, type ReactNode } from "react"; import type { DiffLineAnnotation } from "@pierre/diffs"; import type { DiffComment } from "@/lib/diff/types"; import type { TaskReviewFinding } from "@/lib/types/review"; import { CommentForm } from "./comment-form"; import { CommentDisplay } from "./comment-display"; import { HunkActionBar } from "./hunk-action-bar"; import { WalkthroughStepCard } from "./walkthrough-step-card"; import { InlineReviewFinding } from "./inline-review-finding"; type AnnotationMetadata = { type: "comment" | "new-comment-form" | "hunk-actions" | "walkthrough-step" | "review-finding"; comment?: DiffComment; isEditing?: boolean; changeBlockId?: string; /** Set when type is "review-finding". */ finding?: TaskReviewFinding; /** Explains why an anchored finding is stale, when it is. */ findingStaleReason?: string; }; type UseAnnotationRendererOpts = { handleRevertBlock: (changeBlockId: string) => Promise; onButtonEnter: () => void; onButtonLeave: () => void; handleCommentSubmit: (content: string) => void; handleCommentSubmitAndRun?: (content: string) => void; handleCommentUpdate: (commentId: string, content: string) => void; handleCommentDelete: (commentId: string) => void; handleCommentRun?: (comment: DiffComment) => void; setShowCommentForm: (show: boolean) => void; setSelectedLines: (lines: null) => void; setEditingComment: (id: string | null) => void; }; export type { AnnotationMetadata }; export function useAnnotationRenderer(opts: UseAnnotationRendererOpts) { const { handleRevertBlock, onButtonEnter, onButtonLeave, handleCommentSubmit, handleCommentSubmitAndRun, handleCommentUpdate, handleCommentDelete, handleCommentRun, setShowCommentForm, setSelectedLines, setEditingComment, } = opts; return useCallback( (annotation: DiffLineAnnotation): ReactNode => { const { type, comment, isEditing, changeBlockId, finding, findingStaleReason } = annotation.metadata; if (type === "review-finding" && finding) { return ; } if (type === "walkthrough-step") { return ; } if (type === "hunk-actions" && changeBlockId) { return ( handleRevertBlock(changeBlockId)} onMouseEnter={onButtonEnter} onMouseLeave={onButtonLeave} /> ); } if (type === "new-comment-form") { return (
{ setShowCommentForm(false); setSelectedLines(null); }} />
); } if (isEditing && comment) { return (
handleCommentUpdate(comment.id, content)} onCancel={() => setEditingComment(null)} isEditing />
); } if (comment) { return (
handleCommentDelete(comment.id)} onEdit={() => setEditingComment(comment.id)} onRun={handleCommentRun ? () => handleCommentRun(comment) : undefined} showCode={false} />
); } return null; }, [ setEditingComment, handleCommentDelete, handleCommentRun, handleCommentUpdate, handleCommentSubmit, handleCommentSubmitAndRun, handleRevertBlock, onButtonEnter, onButtonLeave, setShowCommentForm, setSelectedLines, ], ); }