1- import { useState , useEffect } from 'react'
1+ import { useState , useEffect , useRef } from 'react'
22import { toast } from 'sonner'
33import { Progress } from '@/components/ui/progress'
44import type { Repository } from '../types'
5+ import { WS_URL } from '../config/api'
56
67interface RepoOverviewProps {
78 repo : Repository
@@ -10,37 +11,104 @@ interface RepoOverviewProps {
1011 apiKey : string
1112}
1213
14+ interface IndexProgress {
15+ files_processed : number
16+ functions_indexed : number
17+ total_files : number
18+ progress_pct : number
19+ }
20+
1321export function RepoOverview ( { repo, onReindex, apiUrl, apiKey } : RepoOverviewProps ) {
1422 const [ indexing , setIndexing ] = useState ( false )
15- const [ progress , setProgress ] = useState ( 0 )
23+ const [ progress , setProgress ] = useState < IndexProgress | null > ( null )
24+ const wsRef = useRef < WebSocket | null > ( null )
25+
26+ // Cleanup WebSocket on unmount
27+ useEffect ( ( ) => {
28+ return ( ) => {
29+ if ( wsRef . current ) {
30+ wsRef . current . close ( )
31+ }
32+ }
33+ } , [ ] )
1634
1735 const handleReindex = async ( ) => {
1836 setIndexing ( true )
19- setProgress ( 10 )
20- toast . loading ( 'Starting re-index...' , { id : 'reindex' } )
37+ setProgress ( { files_processed : 0 , functions_indexed : 0 , total_files : 0 , progress_pct : 0 } )
38+
39+ // Connect to WebSocket for real-time progress
40+ const wsUrl = `${ WS_URL } /ws/index/${ repo . id } ?token=${ apiKey } `
41+
42+ try {
43+ const ws = new WebSocket ( wsUrl )
44+ wsRef . current = ws
45+
46+ ws . onopen = ( ) => {
47+ toast . loading ( 'Indexing started...' , { id : 'reindex' } )
48+ }
49+
50+ ws . onmessage = ( event ) => {
51+ const data = JSON . parse ( event . data )
52+
53+ if ( data . type === 'progress' ) {
54+ setProgress ( {
55+ files_processed : data . files_processed ,
56+ functions_indexed : data . functions_indexed ,
57+ total_files : data . total_files ,
58+ progress_pct : data . progress_pct
59+ } )
60+ } else if ( data . type === 'complete' ) {
61+ setProgress ( prev => prev ? { ...prev , progress_pct : 100 } : null )
62+ toast . success ( `Indexing complete! ${ data . total_functions } functions indexed.` , { id : 'reindex' } )
63+ setIndexing ( false )
64+ onReindex ( ) // Refresh repo data
65+ } else if ( data . type === 'error' ) {
66+ toast . error ( `Indexing failed: ${ data . message } ` , { id : 'reindex' } )
67+ setIndexing ( false )
68+ }
69+ }
70+
71+ ws . onerror = ( ) => {
72+ // WebSocket error - fall back to HTTP
73+ toast . dismiss ( 'reindex' )
74+ fallbackToHttp ( )
75+ }
76+
77+ ws . onclose = ( event ) => {
78+ if ( event . code !== 1000 && indexing ) {
79+ // Abnormal close while still indexing - fall back to HTTP
80+ fallbackToHttp ( )
81+ }
82+ }
83+
84+ } catch {
85+ // WebSocket connection failed - fall back to HTTP
86+ fallbackToHttp ( )
87+ }
88+ }
89+
90+ const fallbackToHttp = async ( ) => {
91+ // Fallback: Use HTTP endpoint with simulated progress
92+ toast . loading ( 'Using fallback indexing...' , { id : 'reindex' } )
2193
2294 try {
2395 await onReindex ( )
24- toast . success ( 'Re-indexing started!' , {
25- id : 'reindex' ,
26- description : 'Using incremental mode - 100x faster!'
27- } )
96+ toast . success ( 'Re-indexing started!' , { id : 'reindex' } )
2897
29- // Simulate progress
98+ // Simulate progress for HTTP fallback
99+ let pct = 10
30100 const interval = setInterval ( ( ) => {
31- setProgress ( prev => {
32- if ( prev >= 90 ) return prev
33- return prev + 10
34- } )
101+ pct = Math . min ( pct + 10 , 90 )
102+ setProgress ( prev => prev ? { ...prev , progress_pct : pct } : null )
35103 } , 1000 )
36104
37105 setTimeout ( ( ) => {
38106 clearInterval ( interval )
39- setProgress ( 100 )
107+ setProgress ( prev => prev ? { ... prev , progress_pct : 100 } : null )
40108 setIndexing ( false )
41109 } , 8000 )
42110
43- } catch ( error ) {
111+ } catch {
44112 setIndexing ( false )
45113 toast . error ( 'Failed to start re-indexing' , { id : 'reindex' } )
46114 }
@@ -81,16 +149,17 @@ export function RepoOverview({ repo, onReindex, apiUrl, apiKey }: RepoOverviewPr
81149 </ div >
82150
83151 { /* Indexing Progress */ }
84- { indexing && (
152+ { indexing && progress && (
85153 < div className = "card p-6 border-2 border-blue-500 bg-blue-50" >
86154 < div className = "flex items-center justify-between mb-3" >
87155 < h3 className = "text-base font-semibold text-gray-900" > 🔄 Indexing in Progress</ h3 >
88- < span className = "text-sm font-mono text-blue-600" > { progress } %</ span >
156+ < span className = "text-sm font-mono text-blue-600" > { progress . progress_pct } %</ span >
157+ </ div >
158+ < Progress value = { progress . progress_pct } className = "h-2" />
159+ < div className = "flex justify-between text-xs text-gray-600 mt-2" >
160+ < span > Files: { progress . files_processed } /{ progress . total_files || '?' } </ span >
161+ < span > Functions: { progress . functions_indexed } </ span >
89162 </ div >
90- < Progress value = { progress } className = "h-2" />
91- < p className = "text-xs text-gray-600 mt-2" >
92- Incremental mode - only processing changed files for 100x faster updates
93- </ p >
94163 </ div >
95164 ) }
96165
0 commit comments