@@ -394,7 +394,7 @@ export class DiffViewProvider {
394394 vscode . window . tabGroups . close ( tab ) . then (
395395 ( ) => undefined ,
396396 ( err ) => {
397- // Ignore errors when closing diff tabs - they may already be closed
397+ console . error ( `Failed to close diff tab ${ tab . label } ` , err )
398398 } ,
399399 ) ,
400400 )
@@ -404,7 +404,9 @@ export class DiffViewProvider {
404404
405405 private async openDiffEditor ( ) : Promise < vscode . TextEditor > {
406406 if ( ! this . relPath ) {
407- throw new Error ( "No file path set" )
407+ throw new Error (
408+ "No file path set for opening diff editor. Ensure open() was called before openDiffEditor()" ,
409+ )
408410 }
409411
410412 const uri = vscode . Uri . file ( path . resolve ( this . cwd , this . relPath ) )
@@ -428,86 +430,83 @@ export class DiffViewProvider {
428430
429431 // Open new diff editor.
430432 return new Promise < vscode . TextEditor > ( ( resolve , reject ) => {
431- ; ( async ( ) => {
432- const fileName = path . basename ( uri . fsPath )
433- const fileExists = this . editType === "modify"
434- let timeoutId : NodeJS . Timeout | undefined
435-
436- const checkAndResolve = ( ) => {
437- for ( const group of vscode . window . tabGroups . all ) {
438- for ( const tab of group . tabs ) {
439- if (
440- tab . input instanceof vscode . TabInputTextDiff &&
441- tab . input ?. original ?. scheme === DIFF_VIEW_URI_SCHEME &&
442- arePathsEqual ( tab . input . modified . fsPath , uri . fsPath )
443- ) {
444- // Found the diff editor, now try to show it to get the TextEditor instance
445- vscode . window . showTextDocument ( tab . input . modified , { preserveFocus : true } ) . then (
446- ( editor ) => {
447- if ( timeoutId ) clearTimeout ( timeoutId )
448- disposableTabGroup . dispose ( )
449- resolve ( editor )
450- } ,
451- ( err ) => {
452- if ( timeoutId ) clearTimeout ( timeoutId )
453- disposableTabGroup . dispose ( )
454- reject (
455- new Error ( `Failed to show diff editor after finding tab: ${ err . message } ` ) ,
456- )
457- } ,
458- )
459- return true
460- }
433+ const fileName = path . basename ( uri . fsPath )
434+ const fileExists = this . editType === "modify"
435+ const DIFF_EDITOR_TIMEOUT = 10_000 // ms
436+
437+ let timeoutId : NodeJS . Timeout | undefined
438+ const disposables : vscode . Disposable [ ] = [ ]
439+
440+ const cleanup = ( ) => {
441+ if ( timeoutId ) {
442+ clearTimeout ( timeoutId )
443+ timeoutId = undefined
444+ }
445+ disposables . forEach ( ( d ) => d . dispose ( ) )
446+ disposables . length = 0
447+ }
448+
449+ // Set timeout for the entire operation
450+ timeoutId = setTimeout ( ( ) => {
451+ cleanup ( )
452+ reject (
453+ new Error (
454+ `Failed to open diff editor for ${ uri . fsPath } within ${ DIFF_EDITOR_TIMEOUT / 1000 } seconds. The editor may be blocked or VS Code may be unresponsive.` ,
455+ ) ,
456+ )
457+ } , DIFF_EDITOR_TIMEOUT )
458+
459+ // Listen for document open events - more efficient than scanning all tabs
460+ disposables . push (
461+ vscode . workspace . onDidOpenTextDocument ( async ( document ) => {
462+ if ( arePathsEqual ( document . uri . fsPath , uri . fsPath ) ) {
463+ // Wait a tick for the editor to be available
464+ await new Promise ( ( r ) => setTimeout ( r , 0 ) )
465+
466+ // Find the editor for this document
467+ const editor = vscode . window . visibleTextEditors . find ( ( e ) =>
468+ arePathsEqual ( e . document . uri . fsPath , uri . fsPath ) ,
469+ )
470+
471+ if ( editor ) {
472+ cleanup ( )
473+ resolve ( editor )
461474 }
462475 }
463- return false
464- }
476+ } ) ,
477+ )
465478
466- // Listen for changes in tab groups, which includes tabs moving between windows
467- const disposableTabGroup = vscode . window . tabGroups . onDidChangeTabGroups ( ( ) => {
468- const found = checkAndResolve ( )
469- if ( found ) {
470- // Editor found and resolved, no need to continue listening
471- console . debug ( "Diff editor found via tab group change listener" )
479+ // Also listen for visible editor changes as a fallback
480+ disposables . push (
481+ vscode . window . onDidChangeVisibleTextEditors ( ( editors ) => {
482+ const editor = editors . find ( ( e ) => arePathsEqual ( e . document . uri . fsPath , uri . fsPath ) )
483+ if ( editor ) {
484+ cleanup ( )
485+ resolve ( editor )
472486 }
473- } )
487+ } ) ,
488+ )
474489
475- vscode . commands
476- . executeCommand (
477- "vscode.diff" ,
478- vscode . Uri . parse ( `${ DIFF_VIEW_URI_SCHEME } :${ fileName } ` ) . with ( {
479- query : Buffer . from ( this . originalContent ?? "" ) . toString ( "base64" ) ,
480- } ) ,
481- uri ,
482- `${ fileName } : ${ fileExists ? "Original ↔ Roo's Changes" : "New File" } (Editable)` ,
483- { preserveFocus : true } ,
484- )
485- . then (
486- ( ) => {
487- // Give a brief moment for the editor to appear in tab groups
488- setTimeout ( ( ) => {
489- const found = checkAndResolve ( )
490- if ( ! found ) {
491- // If not found immediately, rely on tab group change listener
492- // and the 10-second timeout fallback to handle resolution
493- console . debug (
494- "Diff editor not found in initial check, waiting for tab group changes..." ,
495- )
496- }
497- } , 100 )
498- } ,
499- ( err ) => {
500- if ( timeoutId ) clearTimeout ( timeoutId )
501- disposableTabGroup . dispose ( )
502- reject ( new Error ( `Failed to open diff editor command: ${ err . message } ` ) )
503- } ,
504- )
505-
506- timeoutId = setTimeout ( ( ) => {
507- disposableTabGroup . dispose ( )
508- reject ( new Error ( "Failed to open diff editor, please try again..." ) )
509- } , 10_000 )
510- } ) ( )
490+ // Execute the diff command
491+ vscode . commands
492+ . executeCommand (
493+ "vscode.diff" ,
494+ vscode . Uri . parse ( `${ DIFF_VIEW_URI_SCHEME } :${ fileName } ` ) . with ( {
495+ query : Buffer . from ( this . originalContent ?? "" ) . toString ( "base64" ) ,
496+ } ) ,
497+ uri ,
498+ `${ fileName } : ${ fileExists ? "Original ↔ Roo's Changes" : "New File" } (Editable)` ,
499+ { preserveFocus : true } ,
500+ )
501+ . then (
502+ ( ) => {
503+ // Command executed successfully, now wait for the editor to appear
504+ } ,
505+ ( err : any ) => {
506+ cleanup ( )
507+ reject ( new Error ( `Failed to execute diff command for ${ uri . fsPath } : ${ err . message } ` ) )
508+ } ,
509+ )
511510 } )
512511 }
513512
0 commit comments