@@ -19,6 +19,7 @@ export class DiffViewProvider {
1919 private documentWasOpen = false
2020 private originalViewColumn ?: vscode . ViewColumn // Store the original view column
2121 private userFocusedEditorInfo ?: { uri : vscode . Uri ; viewColumn : vscode . ViewColumn } // Store user's focus before diff
22+ private originalTabState ?: { uri : vscode . Uri ; isPinned : boolean ; viewColumn : vscode . ViewColumn ; index : number } // Store original tab state if open
2223 private relPath ?: string
2324 private newContent ?: string
2425 private activeDiffEditor ?: vscode . TextEditor
@@ -67,10 +68,23 @@ export class DiffViewProvider {
6768 ( tab ) => tab . input instanceof vscode . TabInputText && arePathsEqual ( tab . input . uri . fsPath , absolutePath ) ,
6869 )
6970 for ( const tab of tabs ) {
71+ // Store state BEFORE closing
72+ if ( tab . input instanceof vscode . TabInputText ) {
73+ // Ensure it's a text tab to access URI safely
74+ this . originalTabState = {
75+ uri : tab . input . uri ,
76+ isPinned : tab . isPinned ,
77+ viewColumn : tab . group . viewColumn ,
78+ index : tab . group . tabs . indexOf ( tab ) , // Correct way to get the index
79+ }
80+ this . documentWasOpen = true // Set flag indicating we found an open tab state
81+ console . log ( "Original tab state saved:" , this . originalTabState ) // Optional: for debugging
82+ }
83+
7084 if ( ! tab . isDirty ) {
7185 await vscode . window . tabGroups . close ( tab )
7286 }
73- this . documentWasOpen = true
87+ // Removed this.documentWasOpen = true from here as it's set when state is saved
7488 }
7589
7690 // Store the currently focused editor before opening the diff
@@ -174,9 +188,13 @@ export class DiffViewProvider {
174188 await vscode . window . showTextDocument ( vscode . Uri . file ( absolutePath ) , { preview : false } )
175189 await this . closeAllDiffViews ( )
176190
177- // If the original document was open, try to focus it.
178- // VS Code should handle showing the updated content automatically since the file was saved.
179- await this . _focusOriginalDocument ( absolutePath , this . originalViewColumn )
191+ // Restore original tab state if it existed, otherwise handle focus normally
192+ if ( this . originalTabState ) {
193+ await this . _restoreOriginalTabState ( )
194+ } else {
195+ // Fallback to old focus logic only if no original tab state was saved (e.g., new file)
196+ await this . _focusOriginalDocument ( absolutePath , undefined ) // Pass undefined as viewColumn is part of originalTabState now
197+ }
180198
181199 /*
182200 Getting diagnostics before and after the file edit is a better approach than
@@ -260,10 +278,13 @@ export class DiffViewProvider {
260278 // Close the diff view first
261279 await this . closeAllDiffViews ( )
262280
263- // If the document was originally open, ensure it's focused.
264- // The revert logic already applied the original content and saved.
265- await this . _focusOriginalDocument ( absolutePath , this . originalViewColumn )
266-
281+ // Restore original tab state if it existed, otherwise handle focus normally
282+ if ( this . originalTabState ) {
283+ await this . _restoreOriginalTabState ( )
284+ } else {
285+ // Fallback to old focus logic only if no original tab state was saved (e.g., new file)
286+ await this . _focusOriginalDocument ( absolutePath , undefined ) // Pass undefined as viewColumn is part of originalTabState now
287+ }
267288 }
268289 // edit is done
269290 await this . reset ( )
@@ -310,16 +331,61 @@ export class DiffViewProvider {
310331 const disposable = vscode . window . onDidChangeActiveTextEditor ( ( editor ) => {
311332 if ( editor && arePathsEqual ( editor . document . uri . fsPath , uri . fsPath ) ) {
312333 disposable . dispose ( )
313- // Diff editor is now active, resolve the promise
314- resolve ( editor )
334+ // Diff editor is now active
335+ // Pin the diff editor if the original tab was pinned
336+ const pinAndMoveIfNeeded = async ( ) => {
337+ if ( this . originalTabState ?. isPinned ) {
338+ try {
339+ await vscode . commands . executeCommand ( "workbench.action.pinEditor" )
340+ console . log ( "Diff editor pinned." )
341+ // Add a small delay after pinning before moving
342+ await new Promise ( ( resolve ) => setTimeout ( resolve , 50 ) )
343+
344+ // Move the pinned diff editor to the original index
345+ const targetGroup = vscode . window . tabGroups . all . find (
346+ ( group ) => group . viewColumn === this . originalTabState ?. viewColumn ,
347+ )
348+ const index = this . originalTabState . index
349+ if ( targetGroup && index >= 0 ) {
350+ // Check if index is still valid after potential async operations
351+ if ( index < targetGroup . tabs . length ) {
352+ await vscode . commands . executeCommand ( "moveActiveEditor" , {
353+ to : "position" ,
354+ value : index + 1 , // 1-based index
355+ } )
356+ console . log ( `Diff editor moved to index ${ index } .` )
357+ } else {
358+ console . warn (
359+ `Diff editor move skipped: Index ${ index } out of bounds after pinning/delay.` ,
360+ )
361+ }
362+ } else {
363+ console . warn (
364+ `Could not move diff editor: Invalid index (${ index } ) or target group not found.` ,
365+ )
366+ }
367+ } catch ( err ) {
368+ console . error ( "Failed to pin or move diff editor:" , err )
369+ }
370+ }
371+ // Resolve the promise regardless of pin/move success
372+ resolve ( editor )
373+ }
374+ pinAndMoveIfNeeded ( ) // Execute async pin/move logic
315375 }
316376 } )
317377 const options : vscode . TextDocumentShowOptions = {
318378 // preserveFocus: true, // Removed to prevent focus issues
319379 }
320- if ( this . originalViewColumn !== undefined ) {
380+ // Use viewColumn from originalTabState if available
381+ if ( this . originalTabState ?. viewColumn !== undefined ) {
382+ options . viewColumn = this . originalTabState . viewColumn
383+ } else if ( this . originalViewColumn !== undefined ) {
384+ // Fallback to originalViewColumn if originalTabState is not set (e.g., file wasn't open)
321385 options . viewColumn = this . originalViewColumn
322386 }
387+
388+ // Execute the diff command first
323389 vscode . commands . executeCommand (
324390 "vscode.diff" ,
325391 vscode . Uri . parse ( `${ DIFF_VIEW_URI_SCHEME } :${ fileName } ` ) . with ( {
@@ -381,7 +447,7 @@ export class DiffViewProvider {
381447
382448 private async _focusOriginalDocument (
383449 absolutePath : string ,
384- viewColumn : vscode . ViewColumn | undefined , // Note: viewColumn here is the original view column of the *modified* file's tab, if it was open
450+ _viewColumn : vscode . ViewColumn | undefined , // Prefixed as unused now
385451 ) : Promise < void > {
386452 let focusRestoredOrHandled = false
387453
@@ -421,34 +487,86 @@ export class DiffViewProvider {
421487 }
422488 }
423489
424- // Fallback logic for *existing* documents (only runs if focus restoration failed AND it wasn't a new file)
425- if ( ! focusRestoredOrHandled && this . documentWasOpen && viewColumn ) {
426- console . log ( "Executing fallback logic for existing document as primary focus restore failed." )
427- // Fallback 1: Try to focus the editor tab corresponding to the *modified* file
428- const originalEditor = vscode . window . visibleTextEditors . find (
429- ( editor ) => arePathsEqual ( editor . document . uri . fsPath , absolutePath ) && editor . viewColumn === viewColumn ,
490+ // Fallback logic for existing documents is now handled by _restoreOriginalTabState
491+ // Keep the final log message for clarity
492+ else if ( ! focusRestoredOrHandled ) {
493+ console . log (
494+ "No specific focus action taken by _focusOriginalDocument (focus restore might have succeeded, or it was a new file handled above)." ,
430495 )
431- if ( originalEditor ) {
432- const position = new vscode . Position ( 0 , 0 )
433- originalEditor . revealRange ( new vscode . Range ( position , position ) , vscode . TextEditorRevealType . AtTop )
434- console . log ( "Focus set to modified file's original editor (fallback 1):" , absolutePath )
496+ }
497+ }
498+
499+ private async _restoreOriginalTabState ( ) : Promise < void > {
500+ if ( ! this . originalTabState ) {
501+ console . log ( "No original tab state to restore." )
502+ return
503+ }
504+
505+ console . log ( "Attempting to restore original tab state:" , this . originalTabState )
506+ const { uri, viewColumn, isPinned, index } = this . originalTabState
507+
508+ try {
509+ // 1. Show the document in the correct view column
510+ // Prefix 'editor' as it's not directly used after assignment (focus happens implicitly)
511+ const _editor = await vscode . window . showTextDocument ( uri , {
512+ viewColumn : viewColumn ,
513+ preview : false , // Ensure it's not a preview tab
514+ preserveFocus : false , // Ensure this editor gets focus initially for commands
515+ } )
516+ console . log ( "Document shown:" , uri . fsPath )
517+
518+ // Small delay to allow VS Code to potentially update tab state after showing
519+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) // 100ms delay
520+
521+ // 2. Pin the editor if necessary
522+ if ( isPinned ) {
523+ await vscode . commands . executeCommand ( "workbench.action.pinEditor" )
524+ console . log ( "Editor pinned." )
525+ // Another small delay might be needed after pinning before moving
526+ await new Promise ( ( resolve ) => setTimeout ( resolve , 50 ) )
527+ }
528+
529+ // 3. Move the editor to the original index
530+ // Ensure the target index is valid. VS Code's move command is 1-based.
531+ // We need to find the current group to check tab count.
532+ const targetGroup = vscode . window . tabGroups . all . find ( ( group ) => group . viewColumn === viewColumn )
533+ if ( targetGroup && index >= 0 && index < targetGroup . tabs . length ) {
534+ // The 'moveActiveEditor' command uses 1-based index for 'value'
535+ await vscode . commands . executeCommand ( "moveActiveEditor" , { to : "position" , value : index + 1 } )
536+ console . log ( `Editor moved to index ${ index } .` )
435537 } else {
436- // Fallback 2: Open the modified file if its editor wasn't found
538+ console . warn ( `Could not move editor: Invalid index (${ index } ) or target group not found.` )
539+ }
540+
541+ // 4. Restore original user focus if it was different from the restored tab
542+ if ( this . userFocusedEditorInfo && ! arePathsEqual ( this . userFocusedEditorInfo . uri . fsPath , uri . fsPath ) ) {
437543 try {
438- await vscode . window . showTextDocument ( vscode . Uri . file ( absolutePath ) , {
439- preview : false ,
440- viewColumn : viewColumn ,
441- preserveFocus : false , // Force focus
544+ await vscode . window . showTextDocument ( this . userFocusedEditorInfo . uri , {
545+ viewColumn : this . userFocusedEditorInfo . viewColumn ,
546+ preserveFocus : false , // Force focus back
442547 } )
443- console . log ( "Opened modified file's editor (fallback 2):" , absolutePath )
444- } catch ( error ) {
445- console . error ( "Failed to show modified document (fallback 2):" , error )
548+ console . log (
549+ "Focus restored to originally focused editor (after tab state restore):" ,
550+ this . userFocusedEditorInfo . uri . fsPath ,
551+ )
552+ } catch ( focusError ) {
553+ console . warn ( "Failed to restore original user focus after tab state restore:" , focusError )
554+ // If restoring original focus fails, at least the target tab should be focused.
555+ await vscode . window . showTextDocument ( uri , { viewColumn : viewColumn , preserveFocus : false } )
446556 }
557+ } else {
558+ // Ensure the restored tab keeps focus if no other editor was focused or if it was the focused one
559+ await vscode . window . showTextDocument ( uri , { viewColumn : viewColumn , preserveFocus : false } )
560+ console . log ( "Focus kept on restored tab:" , uri . fsPath )
561+ }
562+ } catch ( error ) {
563+ console . error ( "Error restoring original tab state:" , error )
564+ // Fallback: Just try to show the document without state restoration
565+ try {
566+ await vscode . window . showTextDocument ( uri , { viewColumn : viewColumn , preview : false } )
567+ } catch ( fallbackError ) {
568+ console . error ( "Fallback showTextDocument also failed:" , fallbackError )
447569 }
448- } else if ( ! focusRestoredOrHandled ) {
449- console . log (
450- "No specific focus action taken (focus restore might have succeeded, or it was a new file handled above, or fallbacks for existing file didn't apply)." ,
451- )
452570 }
453571 }
454572
@@ -459,7 +577,8 @@ export class DiffViewProvider {
459577 this . originalContent = undefined
460578 this . createdDirs = [ ]
461579 this . documentWasOpen = false
462- this . originalViewColumn = undefined // Reset stored view column
580+ this . originalViewColumn = undefined // Reset stored view column - Keep for potential fallback? Replaced by originalTabState.viewColumn mostly.
581+ this . originalTabState = undefined // Reset stored tab state
463582 this . userFocusedEditorInfo = undefined // Reset stored user focus info
464583 this . activeDiffEditor = undefined
465584 this . fadedOverlayController = undefined
0 commit comments