@@ -6,13 +6,7 @@ import type {
66 FileDiffMetadata ,
77 SelectedLineRange ,
88} from "@pierre/diffs" ;
9- import {
10- CodeView ,
11- type CodeViewHandle ,
12- type CodeViewProps ,
13- FileDiff ,
14- type FileDiffProps ,
15- } from "@pierre/diffs/react" ;
9+ import { CodeView , type CodeViewHandle , type CodeViewProps } from "@pierre/diffs/react" ;
1610import type { ScopedThreadRef } from "@t3tools/contracts" ;
1711import { useCallback , useMemo , useState , type ReactNode , type Ref } from "react" ;
1812
@@ -76,178 +70,6 @@ function appendAnnotationEntry(
7670 ) ;
7771}
7872
79- interface AnnotatableFileDiffProps {
80- fileDiff : FileDiffMetadata ;
81- filePath : string ;
82- sectionId : string ;
83- sectionTitle : string ;
84- composerDraftTarget : ScopedThreadRef | DraftId ;
85- options : FileDiffProps < DiffCommentAnnotationGroup > [ "options" ] ;
86- renderHeaderPrefix : ( fileDiff : FileDiffMetadata ) => ReactNode ;
87- }
88-
89- export function AnnotatableFileDiff ( {
90- fileDiff,
91- filePath,
92- sectionId,
93- sectionTitle,
94- composerDraftTarget,
95- options,
96- renderHeaderPrefix,
97- } : AnnotatableFileDiffProps ) {
98- const addReviewComment = useComposerDraftStore ( ( store ) => store . addReviewComment ) ;
99- const removeReviewComment = useComposerDraftStore ( ( store ) => store . removeReviewComment ) ;
100- const reviewComments = useComposerDraftStore (
101- ( store ) => store . getComposerDraft ( composerDraftTarget ) ?. reviewComments ?? EMPTY_REVIEW_COMMENTS ,
102- ) ;
103- const [ selectedRange , setSelectedRange ] = useState < SelectedLineRange | null > ( null ) ;
104- const [ draftAnnotation , setDraftAnnotation ] = useState < DiffCommentLineAnnotation | null > ( null ) ;
105- const persistedAnnotations = useMemo (
106- ( ) =>
107- reviewComments
108- . filter (
109- ( comment ) =>
110- comment . sectionId === sectionId &&
111- comment . filePath === filePath &&
112- ( comment . fenceLanguage ?? "diff" ) === "diff" ,
113- )
114- . reduce < DiffCommentLineAnnotation [ ] > ( ( annotations , comment ) => {
115- const range = restoreDiffReviewCommentRange ( fileDiff , comment ) ;
116- if ( ! range ) return annotations ;
117- return appendAnnotationEntry ( annotations , range , {
118- id : comment . id ,
119- kind : "comment" ,
120- range,
121- rangeLabel : comment . rangeLabel ,
122- text : comment . text ,
123- } ) ;
124- } , [ ] ) ,
125- [ fileDiff , filePath , reviewComments , sectionId ] ,
126- ) ;
127- const lineAnnotations = useMemo (
128- ( ) => ( draftAnnotation ? [ ...persistedAnnotations , draftAnnotation ] : persistedAnnotations ) ,
129- [ draftAnnotation , persistedAnnotations ] ,
130- ) ;
131-
132- const removeAnnotationEntry = useCallback (
133- ( entryId : string ) => {
134- setSelectedRange ( null ) ;
135- if (
136- draftAnnotation ?. metadata . entries . some (
137- ( entry ) => entry . id === entryId && entry . kind === "draft" ,
138- )
139- ) {
140- setDraftAnnotation ( null ) ;
141- return ;
142- }
143- removeReviewComment ( composerDraftTarget , entryId ) ;
144- } ,
145- [ composerDraftTarget , draftAnnotation , removeReviewComment ] ,
146- ) ;
147-
148- const submitAnnotationEntry = useCallback (
149- ( entryId : string , text : string ) => {
150- const entry = draftAnnotation ?. metadata . entries . find ( ( candidate ) => candidate . id === entryId ) ;
151- if ( ! entry ) return ;
152-
153- const comment = buildDiffReviewComment ( {
154- id : entry . id ,
155- sectionId,
156- sectionTitle,
157- filePath,
158- fileDiff,
159- range : entry . range ,
160- text,
161- } ) ;
162- if ( comment ) {
163- addReviewComment ( composerDraftTarget , comment ) ;
164- }
165- setSelectedRange ( null ) ;
166- setDraftAnnotation ( null ) ;
167- } ,
168- [
169- addReviewComment ,
170- composerDraftTarget ,
171- fileDiff ,
172- filePath ,
173- draftAnnotation ,
174- sectionId ,
175- sectionTitle ,
176- ] ,
177- ) ;
178-
179- const beginComment = useCallback (
180- ( range : SelectedLineRange ) => {
181- const id = nextFileCommentId ( ) ;
182- const comment = buildDiffReviewComment ( {
183- id,
184- sectionId,
185- sectionTitle,
186- filePath,
187- fileDiff,
188- range,
189- text : "" ,
190- } ) ;
191- if ( ! comment ) return ;
192-
193- const draftEntry : DiffCommentAnnotationEntry = {
194- id,
195- kind : "draft" ,
196- range,
197- rangeLabel : comment . rangeLabel ,
198- text : "" ,
199- } ;
200- setDraftAnnotation ( {
201- side : annotationSide ( range ) ,
202- lineNumber : range . end ,
203- metadata : { entries : [ draftEntry ] } ,
204- } ) ;
205- } ,
206- [ fileDiff , filePath , sectionId , sectionTitle ] ,
207- ) ;
208-
209- const hasOpenCommentForm = draftAnnotation !== null ;
210- const handleLineSelectionEnd = useCallback (
211- ( range : SelectedLineRange | null ) => {
212- setSelectedRange ( range ) ;
213- if ( range ) beginComment ( range ) ;
214- } ,
215- [ beginComment ] ,
216- ) ;
217-
218- return (
219- < FileDiff < DiffCommentAnnotationGroup >
220- fileDiff = { fileDiff }
221- renderHeaderPrefix = { renderHeaderPrefix }
222- options = { {
223- ...options ,
224- enableGutterUtility : ! hasOpenCommentForm ,
225- enableLineSelection : ! hasOpenCommentForm ,
226- onGutterUtilityClick : setSelectedRange ,
227- onLineSelectionChange : setSelectedRange ,
228- onLineSelectionEnd : handleLineSelectionEnd ,
229- } }
230- selectedLines = { selectedRange }
231- lineAnnotations = { lineAnnotations }
232- renderAnnotation = { ( annotation ) => (
233- < div className = "py-1" >
234- { annotation . metadata . entries . map ( ( entry ) => (
235- < LocalCommentAnnotation
236- key = { entry . id }
237- kind = { entry . kind }
238- rangeLabel = { entry . rangeLabel }
239- text = { entry . text }
240- onCancel = { ( ) => removeAnnotationEntry ( entry . id ) }
241- onComment = { ( text ) => submitAnnotationEntry ( entry . id , text ) }
242- onDelete = { ( ) => removeAnnotationEntry ( entry . id ) }
243- />
244- ) ) }
245- </ div >
246- ) }
247- />
248- ) ;
249- }
250-
25173interface AnnotatableCodeViewProps {
25274 files : ReadonlyArray < {
25375 fileDiff : FileDiffMetadata ;
0 commit comments