@@ -51,7 +51,7 @@ const UnifiedDiffView: React.FC<DiffViewProps> = ({
5151  const  [ lineDiffs ,  setLineDiffs ]  =  React . useState < LineDiff [ ] > ( [ ] ) ; 
5252  const  [ loading ,  setLoading ]  =  React . useState ( true ) ; 
5353  const  [ viewMode ,  setViewMode ]  =  React . useState < ViewMode > ( 'unified' ) ; 
54-   const  [ diffAlgorithm ,  setDiffAlgorithm ]  =  React . useState < DiffAlgorithm > ( 'lcs ' ) ; 
54+   const  [ diffAlgorithm ,  setDiffAlgorithm ]  =  React . useState < DiffAlgorithm > ( 'ast ' ) ; 
5555  const  scrollContainerRef  =  React . useRef < HTMLDivElement > ( null ) ; 
5656
5757  React . useEffect ( ( )  =>  { 
@@ -60,7 +60,7 @@ const UnifiedDiffView: React.FC<DiffViewProps> = ({
6060        setLoading ( true ) ; 
6161
6262        // Call the Rust backend AST diff API 
63-         const  response  =  await  fetch ( 'http://localhost:8080/api/ast- diff' ,  { 
63+         const  response  =  await  fetch ( 'http://localhost:8080/api/ast/ diff' ,  { 
6464          method : 'POST' , 
6565          headers : {  'Content-Type' : 'application/json'  } , 
6666          body : JSON . stringify ( { 
@@ -81,7 +81,9 @@ const UnifiedDiffView: React.FC<DiffViewProps> = ({
8181        } ) ; 
8282
8383        if  ( ! response . ok )  { 
84-           throw  new  Error ( 'Failed to fetch diff' ) ; 
84+           const  errorText  =  await  response . text ( ) ; 
85+           console . warn ( 'AST diff API failed, falling back to simple diff:' ,  response . status ,  errorText ) ; 
86+           throw  new  Error ( `Failed to fetch diff: ${ response . statusText }  ) ; 
8587        } 
8688
8789        const  data  =  await  response . json ( ) ; 
@@ -97,7 +99,7 @@ const UnifiedDiffView: React.FC<DiffViewProps> = ({
9799
98100        setLineDiffs ( diffs ) ; 
99101      }  catch  ( error )  { 
100-         console . error ( 'Error fetching  diff:' ,   error ) ; 
102+         console . info ( 'Using fallback  diff algorithm (AST backend not available)' ) ; 
101103        // Fallback to simple line-by-line comparison 
102104        const  sourceLines  =  sourceContent . split ( '\n' ) ; 
103105        const  targetLines  =  targetContent . split ( '\n' ) ; 
@@ -251,8 +253,84 @@ const UnifiedDiffView: React.FC<DiffViewProps> = ({
251253        </ div > 
252254      </ div > 
253255
254-       { /* Unified View */ } 
256+       { /* Unified View - Traditional single-column diff  */ } 
255257      { viewMode  ===  'unified'  &&  ( 
258+         < div 
259+           ref = { scrollContainerRef } 
260+           className = "overflow-auto max-h-[600px] bg-slate-900" 
261+           style = { {  scrollbarGutter : 'stable'  } } 
262+         > 
263+           < div > 
264+             { lineDiffs . map ( ( diff ,  idx )  =>  { 
265+               // For unified view, show each line with +/- prefix 
266+               const  showSourceLine  =  diff . sourceLineNum  !==  null  &&  diff . type  !==  'added' ; 
267+               const  showTargetLine  =  diff . targetLineNum  !==  null  &&  diff . type  !==  'deleted' ; 
268+ 
269+               return  ( 
270+                 < React . Fragment  key = { `unified-${ idx }  } > 
271+                   { /* Show deleted/modified source line with - prefix */ } 
272+                   { showSourceLine  &&  diff . type  !==  'unchanged'  &&  ( 
273+                     < div 
274+                       className = { `flex ${ getLineBackgroundColor ( diff . type  ===  'modified'  ? 'deleted'  : diff . type ) } ${ getLineBorderColor ( 'deleted' ) }  } 
275+                     > 
276+                       < div  className = "w-12 flex-shrink-0 text-right pr-3 py-1 text-slate-500 text-xs font-mono select-none border-r border-slate-700" > 
277+                         { diff . sourceLineNum } 
278+                       </ div > 
279+                       < div  className = "w-8 flex-shrink-0 text-center py-1 text-red-400 text-xs font-mono select-none" > 
280+                         -
281+                       </ div > 
282+                       < div  className = "flex-1 px-3 py-1" > 
283+                         < pre  className = "font-mono text-sm text-slate-100 whitespace-pre" > 
284+                           { diff . sourceContent } 
285+                         </ pre > 
286+                       </ div > 
287+                     </ div > 
288+                   ) } 
289+ 
290+                   { /* Show added/modified target line with + prefix */ } 
291+                   { showTargetLine  &&  diff . type  !==  'unchanged'  &&  ( 
292+                     < div 
293+                       className = { `flex ${ getLineBackgroundColor ( diff . type  ===  'modified'  ? 'added'  : diff . type ) } ${ getLineBorderColor ( 'added' ) }  } 
294+                     > 
295+                       < div  className = "w-12 flex-shrink-0 text-right pr-3 py-1 text-slate-500 text-xs font-mono select-none border-r border-slate-700" > 
296+                         { diff . targetLineNum } 
297+                       </ div > 
298+                       < div  className = "w-8 flex-shrink-0 text-center py-1 text-green-400 text-xs font-mono select-none" > 
299+                         +
300+                       </ div > 
301+                       < div  className = "flex-1 px-3 py-1" > 
302+                         < pre  className = "font-mono text-sm text-slate-100 whitespace-pre" > 
303+                           { diff . targetContent } 
304+                         </ pre > 
305+                       </ div > 
306+                     </ div > 
307+                   ) } 
308+ 
309+                   { /* Show unchanged lines with no prefix */ } 
310+                   { diff . type  ===  'unchanged'  &&  ( 
311+                     < div  className = { `flex ${ getLineBackgroundColor ( 'unchanged' ) }  } > 
312+                       < div  className = "w-12 flex-shrink-0 text-right pr-3 py-1 text-slate-500 text-xs font-mono select-none border-r border-slate-700" > 
313+                         { diff . sourceLineNum  ||  diff . targetLineNum } 
314+                       </ div > 
315+                       < div  className = "w-8 flex-shrink-0 text-center py-1 text-slate-600 text-xs font-mono select-none" > 
316+                         { ' ' } 
317+                       </ div > 
318+                       < div  className = "flex-1 px-3 py-1" > 
319+                         < pre  className = "font-mono text-sm text-slate-100 whitespace-pre" > 
320+                           { diff . sourceContent  ||  diff . targetContent } 
321+                         </ pre > 
322+                       </ div > 
323+                     </ div > 
324+                   ) } 
325+                 </ React . Fragment > 
326+               ) ; 
327+             } ) } 
328+           </ div > 
329+         </ div > 
330+       ) } 
331+ 
332+       { /* Side-by-Side View - Synchronized two-column layout */ } 
333+       { viewMode  ===  'side-by-side'  &&  ( 
256334        < div 
257335          ref = { scrollContainerRef } 
258336          className = "overflow-auto max-h-[600px]" 
@@ -313,71 +391,6 @@ const UnifiedDiffView: React.FC<DiffViewProps> = ({
313391          </ div > 
314392        </ div > 
315393      ) } 
316- 
317-       { /* Side-by-Side View */ } 
318-       { viewMode  ===  'side-by-side'  &&  ( 
319-         < div  className = "grid grid-cols-2 divide-x divide-slate-700" > 
320-           { /* Source Code */ } 
321-           < div  className = "bg-slate-900" > 
322-             < div  className = "sticky top-0 z-10 px-4 py-2 bg-slate-800 border-b border-slate-700" > 
323-               < span  className = "text-xs font-medium text-slate-300 uppercase tracking-wide" > Source</ span > 
324-             </ div > 
325-             < div  className = "overflow-auto max-h-[600px]" > 
326-               < div > 
327-                 { lineDiffs 
328-                   . filter ( diff  =>  diff . sourceLineNum  !==  null ) 
329-                   . map ( ( diff ,  idx )  =>  ( 
330-                     < div 
331-                       key = { `source-sbs-${ idx }  } 
332-                       className = { `flex ${ getLineBackgroundColor ( diff . type  ===  'added'  ? 'unchanged'  : diff . type ) } ${  
333-                         diff . type  ===  'deleted'  ||  diff . type  ===  'modified'  ? getLineBorderColor ( diff . type )  : ''  
334-                       }  `} 
335-                     > 
336-                       < div  className = "w-12 flex-shrink-0 text-right pr-3 py-1 text-slate-500 text-xs font-mono select-none border-r border-slate-700" > 
337-                         { diff . sourceLineNum } 
338-                       </ div > 
339-                       < div  className = "flex-1 px-3 py-1" > 
340-                         < pre  className = "font-mono text-sm text-slate-100 whitespace-pre" > 
341-                           { diff . sourceContent } 
342-                         </ pre > 
343-                       </ div > 
344-                     </ div > 
345-                   ) ) } 
346-               </ div > 
347-             </ div > 
348-           </ div > 
349- 
350-           { /* Target Code */ } 
351-           < div  className = "bg-slate-900" > 
352-             < div  className = "sticky top-0 z-10 px-4 py-2 bg-slate-800 border-b border-slate-700" > 
353-               < span  className = "text-xs font-medium text-slate-300 uppercase tracking-wide" > Target</ span > 
354-             </ div > 
355-             < div  className = "overflow-auto max-h-[600px]" > 
356-               < div > 
357-                 { lineDiffs 
358-                   . filter ( diff  =>  diff . targetLineNum  !==  null ) 
359-                   . map ( ( diff ,  idx )  =>  ( 
360-                     < div 
361-                       key = { `target-sbs-${ idx }  } 
362-                       className = { `flex ${ getLineBackgroundColor ( diff . type  ===  'deleted'  ? 'unchanged'  : diff . type ) } ${  
363-                         diff . type  ===  'added'  ||  diff . type  ===  'modified'  ? getLineBorderColor ( diff . type )  : ''  
364-                       }  `} 
365-                     > 
366-                       < div  className = "w-12 flex-shrink-0 text-right pr-3 py-1 text-slate-500 text-xs font-mono select-none border-r border-slate-700" > 
367-                         { diff . targetLineNum } 
368-                       </ div > 
369-                       < div  className = "flex-1 px-3 py-1" > 
370-                         < pre  className = "font-mono text-sm text-slate-100 whitespace-pre" > 
371-                           { diff . targetContent } 
372-                         </ pre > 
373-                       </ div > 
374-                     </ div > 
375-                   ) ) } 
376-               </ div > 
377-             </ div > 
378-           </ div > 
379-         </ div > 
380-       ) } 
381394    </ div > 
382395  ) ; 
383396} ; 
0 commit comments