Files
kandev/apps/web/components/diff/use-diff-annotation-renderer.tsx
T
José Almeida 3e237e177a feat: add agent-authored code walkthroughs (#1647)
* feat: add code-walkthrough backend (MCP tool, service, persistence, WS events)

* feat: render agent code walkthroughs as line-anchored cards + editor window

* test: add code-walkthrough re-emit mock-agent scenario

* fix: rework code-walkthrough UX (floating card, line reveal, minimize, clickable file)

* fix: improve code walkthrough editor UX

* fix: backfill walkthrough launcher after websocket connect

* fix: improve walkthrough requests and editor anchors

* fix: clear walkthrough highlights on close

* feat: add walkthrough discard and prompt customization

* fix: send walkthrough requests through saved prompt

* fix: support postgres built-in prompt seeding

* fix: address walkthrough review feedback

* fix: address walkthrough review follow-ups

* fix: harden walkthrough lifecycle races

* fix: reuse walkthrough notification cleanup

* fix: guard stale walkthrough file opens

* fix: abort stale file opens before paint

* fix: stabilize github settings e2e readiness

* fix: use stable github settings e2e selector
2026-07-10 08:34:57 +01:00

126 lines
3.6 KiB
TypeScript

import { useCallback, type ReactNode } from "react";
import type { DiffLineAnnotation } from "@pierre/diffs";
import type { DiffComment } from "@/lib/diff/types";
import { CommentForm } from "./comment-form";
import { CommentDisplay } from "./comment-display";
import { HunkActionBar } from "./hunk-action-bar";
import { WalkthroughStepCard } from "./walkthrough-step-card";
type AnnotationMetadata = {
type: "comment" | "new-comment-form" | "hunk-actions" | "walkthrough-step";
comment?: DiffComment;
isEditing?: boolean;
changeBlockId?: string;
};
type UseAnnotationRendererOpts = {
handleRevertBlock: (changeBlockId: string) => Promise<void>;
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<AnnotationMetadata>): ReactNode => {
const { type, comment, isEditing, changeBlockId } = annotation.metadata;
if (type === "walkthrough-step") {
return <WalkthroughStepCard key="walkthrough-step" />;
}
if (type === "hunk-actions" && changeBlockId) {
return (
<HunkActionBar
key={changeBlockId}
changeBlockId={changeBlockId}
onRevert={() => handleRevertBlock(changeBlockId)}
onMouseEnter={onButtonEnter}
onMouseLeave={onButtonLeave}
/>
);
}
if (type === "new-comment-form") {
return (
<div className="my-1 px-2">
<CommentForm
onSubmit={handleCommentSubmit}
onSubmitAndRun={handleCommentSubmitAndRun}
onCancel={() => {
setShowCommentForm(false);
setSelectedLines(null);
}}
/>
</div>
);
}
if (isEditing && comment) {
return (
<div className="my-1 px-2">
<CommentForm
initialContent={comment.text}
onSubmit={(content) => handleCommentUpdate(comment.id, content)}
onCancel={() => setEditingComment(null)}
isEditing
/>
</div>
);
}
if (comment) {
return (
<div className="my-1 px-2">
<CommentDisplay
comment={comment}
onDelete={() => handleCommentDelete(comment.id)}
onEdit={() => setEditingComment(comment.id)}
onRun={handleCommentRun ? () => handleCommentRun(comment) : undefined}
showCode={false}
/>
</div>
);
}
return null;
},
[
setEditingComment,
handleCommentDelete,
handleCommentRun,
handleCommentUpdate,
handleCommentSubmit,
handleCommentSubmitAndRun,
handleRevertBlock,
onButtonEnter,
onButtonLeave,
setShowCommentForm,
setSelectedLines,
],
);
}