1- import { useCallback , useEffect , useMemo , useRef , useImperativeHandle , useState , forwardRef } from "react" ;
1+ import { useCallback , useEffect , useMemo , useRef , useImperativeHandle , forwardRef } from "react" ;
22
33import { multiSelectClassNames , createDiffMultiSelectManager } from ".." ;
44import { useCallbackRef } from "../hooks/useCallbackRef" ;
@@ -40,7 +40,7 @@ export type MultiSelectExtendData<T = unknown> = {
4040
4141export interface DiffViewWithMultiSelectProps < T = unknown > extends Omit <
4242 DiffViewProps < T > ,
43- "extendData" | "renderExtendLine" | "onAddWidgetClick"
43+ "extendData" | "renderExtendLine" | "renderWidgetLine" | " onAddWidgetClick"
4444> {
4545 /**
4646 * Enable multi-select feature
@@ -72,10 +72,14 @@ export interface DiffViewWithMultiSelectProps<T = unknown> extends Omit<
7272
7373 onAddWidgetClick ?: ( props : { lineNumber : number ; fromLineNumber ?: number ; side : SplitSide } ) => void ;
7474
75- /**
76- * Render function for extended lines (comments)
77- * Similar to DiffView's renderExtendLine but with fromLine info
78- */
75+ renderWidgetLine ?: ( props : {
76+ lineNumber : number ;
77+ fromLineNumber : number ;
78+ side : SplitSide ;
79+ diffFile : DiffFile ;
80+ onClose : ( ) => void ;
81+ } ) => ReactNode ;
82+
7983 renderExtendLine ?: ( props : {
8084 lineNumber : number ;
8185 fromLineNumber : number ;
@@ -94,6 +98,8 @@ export interface DiffViewWithMultiSelectRef {
9498 setPreselectedLines : ( lines : { old : number [ ] ; new : number [ ] } ) => void ;
9599}
96100
101+ type MultiResult = ReturnType < typeof extendDataToPreselectedLines > ;
102+
97103/* eslint-disable @typescript-eslint/no-unnecessary-type-constraint */
98104const InternalDiffViewWithMultiSelect = < T extends unknown > (
99105 props : DiffViewWithMultiSelectProps < T > ,
@@ -105,6 +111,7 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
105111 onMultiSelectComplete,
106112 onMultiSelectChange,
107113 scopeMultiSelectToHunk,
114+ renderWidgetLine,
108115 renderExtendLine,
109116 onAddWidgetClick,
110117 diffViewMode = DiffModeEnum . SplitGitHub ,
@@ -121,12 +128,17 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
121128 const diffViewRef = useRef < { getDiffFileInstance : ( ) => DiffFile | null } > ( null ) ;
122129 const managerRef = useRef < DiffMultiSelectManager | null > ( null ) ;
123130
124- const [ multiResult , setMultiResult ] = useState < ReturnType < typeof extendDataToPreselectedLines > > ( ) ;
131+ const multiResultRef = useRef < MultiResult > ( undefined ) ;
125132
126133 const isUnifiedMode = ! ( diffViewMode & DiffModeEnum . Split ) ;
127134
135+ const updateMultiResult = useCallback ( ( result ?: MultiResult ) => {
136+ multiResultRef . current = result ;
137+ managerRef . current ?. setPreselectedLines ( result || { old : [ ] , new : [ ] } ) ;
138+ } , [ ] ) ;
139+
128140 useUpdateEffect ( ( ) => {
129- setMultiResult ( undefined ) ;
141+ updateMultiResult ( undefined ) ;
130142 } , [ props . diffViewWrap , diffViewMode ] ) ;
131143
132144 const getDiffFile = useCallback ( ( ) => {
@@ -161,10 +173,10 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
161173 memoSelectComplete ?.( result ) ;
162174 const finalResult = {
163175 [ result . range . side as "old" | "new" ] : [ result . range . startLineNumber , result . range . endLineNumber ] ,
164- } as typeof multiResult ;
165- setMultiResult ( finalResult ) ;
176+ } as MultiResult ;
177+ updateMultiResult ( finalResult ) ;
166178 } else {
167- setMultiResult ( undefined ) ;
179+ updateMultiResult ( undefined ) ;
168180 }
169181 } ,
170182 scopeToHunk : memoScopeSelectToHunk ,
@@ -182,17 +194,15 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
182194 managerRef . current ?. destroy ( ) ;
183195 managerRef . current = null ;
184196 } ;
185- } , [ enableMultiSelect , isUnifiedMode , memoScopeSelectToHunk , memoSelectChange , memoSelectComplete , getDiffFile ] ) ;
186-
187- useEffect ( ( ) => {
188- if ( managerRef . current ) {
189- if ( multiResult ) {
190- managerRef . current . setPreselectedLines ( multiResult ) ;
191- } else {
192- managerRef . current . setPreselectedLines ( { old : [ ] , new : [ ] } ) ;
193- }
194- }
195- } , [ multiResult ] ) ;
197+ } , [
198+ enableMultiSelect ,
199+ isUnifiedMode ,
200+ memoScopeSelectToHunk ,
201+ memoSelectChange ,
202+ memoSelectComplete ,
203+ getDiffFile ,
204+ updateMultiResult ,
205+ ] ) ;
196206
197207 const convertedExtendData = useMemo ( ( ) => {
198208 if ( ! extendData ) return undefined ;
@@ -248,6 +258,36 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
248258 [ renderExtendLine , extendData ]
249259 ) ;
250260
261+ const internalRenderWidgetLine = useCallback (
262+ ( {
263+ lineNumber,
264+ side,
265+ diffFile,
266+ onClose,
267+ } : {
268+ lineNumber : number ;
269+ side : SplitSide ;
270+ diffFile : DiffFile ;
271+ onClose : ( ) => void ;
272+ } ) => {
273+ if ( ! renderWidgetLine ) return null ;
274+
275+ const sideKey = side === SplitSide . old ? "old" : "new" ;
276+ const multiResultItem = multiResultRef . current ?. [ sideKey ] as number [ ] ;
277+ const fromLineNumber = multiResultItem ? Math . min ( ...multiResultItem ) : lineNumber ;
278+ const toLineNumber = multiResultItem ? Math . max ( ...multiResultItem ) : lineNumber ;
279+
280+ return renderWidgetLine ( {
281+ lineNumber : toLineNumber ,
282+ fromLineNumber,
283+ side,
284+ diffFile,
285+ onClose,
286+ } ) ;
287+ } ,
288+ [ renderWidgetLine ]
289+ ) ;
290+
251291 const getSelectionResult = useCallback ( ( ) => {
252292 return managerRef . current ?. getSelectionResult ( ) ?? null ;
253293 } , [ ] ) ;
@@ -266,9 +306,7 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
266306 managerRef . current ?. clearSelection ( ) ;
267307 } , [ ] ) ;
268308
269- const setPreselectedLines = useCallback ( ( lines : { old : number [ ] ; new : number [ ] } ) => {
270- setMultiResult ( lines ) ;
271- } , [ ] ) ;
309+ const setPreselectedLines = updateMultiResult ;
272310
273311 useImperativeHandle (
274312 ref ,
@@ -291,6 +329,7 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
291329 extendData = { convertedExtendData }
292330 onAddWidgetClick = { ( lineNum : number , side : SplitSide ) => {
293331 managerRef . current ?. clearSelection ( ) ;
332+ const multiResult = multiResultRef . current ;
294333 if ( multiResult ) {
295334 const currentSide = SplitSide [ side ] as unknown as "new" | "old" ;
296335 const currentMultiResult = multiResult [ currentSide ] as number [ ] ;
@@ -300,7 +339,7 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
300339 const max = Math . max ( ...currentMultiResult ) ;
301340 if ( max === lineNum ) {
302341 const finalResult = { [ currentSide ] : currentMultiResult } ;
303- setMultiResult ( finalResult as typeof multiResult ) ;
342+ updateMultiResult ( finalResult as MultiResult ) ;
304343 onAddWidgetClick ?.( { lineNumber : max , fromLineNumber : Math . min ( ...currentMultiResult ) , side } ) ;
305344 return ;
306345 }
@@ -313,7 +352,7 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
313352 const otherSideLineNum = side === SplitSide . old ? unifiedItem . newLineNumber : unifiedItem . oldLineNumber ;
314353 if ( max === otherSideLineNum ) {
315354 const finalResult = { [ otherSide ] : otherMultiResult } ;
316- setMultiResult ( finalResult as typeof multiResult ) ;
355+ updateMultiResult ( finalResult as MultiResult ) ;
317356 onAddWidgetClick ?.( {
318357 lineNumber : max ,
319358 fromLineNumber : Math . min ( ...otherMultiResult ) ,
@@ -322,12 +361,14 @@ const InternalDiffViewWithMultiSelect = <T extends unknown>(
322361 return ;
323362 }
324363 }
325- setMultiResult ( { old : [ ] , new : [ ] } ) ;
364+ updateMultiResult ( undefined ) ;
326365 onAddWidgetClick ?.( { lineNumber : lineNum , fromLineNumber : lineNum , side } ) ;
327366 } else {
367+ updateMultiResult ( undefined ) ;
328368 onAddWidgetClick ?.( { lineNumber : lineNum , fromLineNumber : lineNum , side } ) ;
329369 }
330370 } }
371+ renderWidgetLine = { renderWidgetLine ? internalRenderWidgetLine : undefined }
331372 renderExtendLine = { renderExtendLine ? internalRenderExtendLine : undefined }
332373 />
333374 </ div >
0 commit comments