@@ -24,6 +24,9 @@ export default function Repositories() {
2424 const [ addMode , setAddMode ] = useState < 'browse' | 'manual' > ( 'browse' ) ;
2525 const [ busyAction , setBusyAction ] = useState < string | null > ( null ) ;
2626 const [ workspaceRoot , setWorkspaceRoot ] = useState ( '' ) ;
27+ const [ autoIndex , setAutoIndex ] = useState ( true ) ;
28+ const [ autoIndexLocked , setAutoIndexLocked ] = useState ( false ) ;
29+ const [ togglingAutoIndex , setTogglingAutoIndex ] = useState ( false ) ;
2730 const { toasts, push : toast , dismiss : dismissToast } = useToast ( ) ;
2831
2932 useEffect ( ( ) => {
@@ -32,8 +35,20 @@ export default function Repositories() {
3235 . then ( ( r ) => r . json ( ) )
3336 . then ( ( d ) => setWorkspaceRoot ( d . workspaceRoot || '' ) )
3437 . catch ( ( err ) => console . warn ( 'Failed to load workspace info:' , err ) ) ;
38+ loadConfig ( ) ;
3539 } , [ ] ) ;
3640
41+ const loadConfig = async ( ) => {
42+ try {
43+ const response = await fetch ( '/api/config' ) ;
44+ const data = await response . json ( ) ;
45+ setAutoIndex ( data . config . autoIndex || false ) ;
46+ setAutoIndexLocked ( data . envLocked . autoIndex || false ) ;
47+ } catch ( error ) {
48+ console . error ( 'Failed to load config:' , error ) ;
49+ }
50+ } ;
51+
3752 const loadRepositories = async ( ) => {
3853 try {
3954 const response = await fetch ( '/api/repositories' ) ;
@@ -108,6 +123,63 @@ export default function Repositories() {
108123 }
109124 } ;
110125
126+ const handleToggleAutoIndex = async ( ) => {
127+ if ( autoIndexLocked ) {
128+ toast ( 'info' , 'Auto-index is locked by environment variable. Cannot change via UI.' ) ;
129+ return ;
130+ }
131+
132+ setTogglingAutoIndex ( true ) ;
133+ try {
134+ const response = await fetch ( '/api/config' , {
135+ method : 'PUT' ,
136+ headers : { 'Content-Type' : 'application/json' } ,
137+ body : JSON . stringify ( { autoIndex : ! autoIndex } ) ,
138+ } ) ;
139+
140+ if ( response . ok ) {
141+ const data = await response . json ( ) ;
142+ if ( data . success ) {
143+ setAutoIndex ( ! autoIndex ) ;
144+ toast ( 'success' , ! autoIndex
145+ ? 'Auto-indexing enabled. New repositories will index automatically.'
146+ : 'Auto-indexing disabled. Use manual indexing for new repositories.' ) ;
147+ } else {
148+ toast ( 'error' , 'Failed to update config.' ) ;
149+ }
150+ } else {
151+ toast ( 'error' , 'Failed to update auto-index setting.' ) ;
152+ }
153+ } catch ( error ) {
154+ toast ( 'error' , 'Network error — could not reach server.' ) ;
155+ } finally {
156+ setTogglingAutoIndex ( false ) ;
157+ }
158+ } ;
159+
160+ const handleQuickIndexWorkspace = async ( ) => {
161+ setBusyAction ( 'quick-index' ) ;
162+ try {
163+ const response = await fetch ( '/api/repositories' , {
164+ method : 'POST' ,
165+ headers : { 'Content-Type' : 'application/json' } ,
166+ body : JSON . stringify ( { path : '/workspace' , incremental : false } ) ,
167+ } ) ;
168+
169+ if ( response . ok ) {
170+ toast ( 'success' , 'Workspace indexing started. This may take a few minutes for large projects.' ) ;
171+ setTimeout ( ( ) => loadRepositories ( ) , 2000 ) ;
172+ } else {
173+ const error = await response . text ( ) ;
174+ toast ( 'error' , `Failed to index workspace: ${ error } ` ) ;
175+ }
176+ } catch ( error ) {
177+ toast ( 'error' , 'Network error — could not reach server.' ) ;
178+ } finally {
179+ setBusyAction ( null ) ;
180+ }
181+ } ;
182+
111183 const handleAddRepository = async ( ) => {
112184 if ( ! newRepoPath . trim ( ) ) return ;
113185
@@ -181,6 +253,22 @@ export default function Repositories() {
181253 </ p >
182254 </ div >
183255 < div className = "flex gap-3" >
256+ < button
257+ onClick = { handleToggleAutoIndex }
258+ disabled = { togglingAutoIndex || autoIndexLocked }
259+ className = { `px-6 py-3 font-semibold text-[0.875rem] rounded-xl transition-all flex items-center gap-2 ${
260+ autoIndex
261+ ? 'bg-green-500/10 text-green-600 hover:bg-green-500/20 border border-green-500/30'
262+ : 'bg-surface-container-highest text-on-surface hover:bg-surface-dim'
263+ } disabled:opacity-50 disabled:cursor-not-allowed`}
264+ title = { autoIndexLocked ? 'Locked by environment variable' : 'Toggle auto-indexing' }
265+ >
266+ < span className = { `material-symbols-outlined text-[18px] ${ togglingAutoIndex ? 'animate-spin' : '' } ` } >
267+ { autoIndex ? 'toggle_on' : 'toggle_off' }
268+ </ span >
269+ Auto-Index: { autoIndex ? 'ON' : 'OFF' }
270+ { autoIndexLocked && < span className = "material-symbols-outlined text-[14px]" > lock</ span > }
271+ </ button >
184272 { repos . length > 0 && (
185273 < button
186274 onClick = { ( ) => {
@@ -222,15 +310,27 @@ export default function Repositories() {
222310 </ span >
223311 < h2 className = "text-2xl font-bold mb-2" > No Repositories Indexed</ h2 >
224312 < p className = "text-on-surface-variant mb-6" >
225- Get started by adding a repository to index for code intelligence .
313+ Get started by indexing your workspace or adding a specific repository .
226314 </ p >
227- < button
228- onClick = { ( ) => setShowAddDialog ( true ) }
229- className = "px-6 py-3 primary-gradient text-white font-semibold text-[0.875rem] rounded-xl shadow-lg shadow-tertiary/10 active:scale-95 transition-all inline-flex items-center gap-2"
230- >
231- < span className = "material-symbols-outlined text-[18px]" > add</ span >
232- Add Repository
233- </ button >
315+ < div className = "flex gap-3 justify-center" >
316+ < button
317+ onClick = { handleQuickIndexWorkspace }
318+ disabled = { busyAction === 'quick-index' }
319+ className = "px-6 py-3 bg-tertiary/10 text-tertiary font-semibold text-[0.875rem] rounded-xl hover:bg-tertiary/20 active:scale-95 transition-all inline-flex items-center gap-2 disabled:opacity-50"
320+ >
321+ < span className = { `material-symbols-outlined text-[18px] ${ busyAction === 'quick-index' ? 'animate-spin' : '' } ` } >
322+ { busyAction === 'quick-index' ? 'refresh' : 'bolt' }
323+ </ span >
324+ { busyAction === 'quick-index' ? 'Indexing...' : 'Quick Index Workspace' }
325+ </ button >
326+ < button
327+ onClick = { ( ) => setShowAddDialog ( true ) }
328+ className = "px-6 py-3 primary-gradient text-white font-semibold text-[0.875rem] rounded-xl shadow-lg shadow-tertiary/10 active:scale-95 transition-all inline-flex items-center gap-2"
329+ >
330+ < span className = "material-symbols-outlined text-[18px]" > add</ span >
331+ Add Specific Path
332+ </ button >
333+ </ div >
234334 </ div >
235335 ) }
236336
0 commit comments