Skip to content

Commit 6b22ba6

Browse files
committed
Improves editor focus handling in diff view
Enhances focus management when opening and closing diff views by: - Tracking the user's initially focused editor - Adding proper focus restoration logic with fallbacks - Implementing better handling for new files Introduces a more robust focus restoration system that prioritizes returning to the originally focused editor while maintaining fallback behavior for edge cases.
1 parent 67cd4c2 commit 6b22ba6

File tree

1 file changed

+83
-11
lines changed

1 file changed

+83
-11
lines changed

src/integrations/editor/DiffViewProvider.ts

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ export class DiffViewProvider {
1818
private createdDirs: string[] = []
1919
private documentWasOpen = false
2020
private originalViewColumn?: vscode.ViewColumn // Store the original view column
21+
private userFocusedEditorInfo?: { uri: vscode.Uri; viewColumn: vscode.ViewColumn } // Store user's focus before diff
2122
private relPath?: string
2223
private newContent?: string
2324
private activeDiffEditor?: vscode.TextEditor
2425
private fadedOverlayController?: DecorationController
2526
private activeLineController?: DecorationController
2627
private streamedLines: string[] = []
2728
private preDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = []
28-
2929
constructor(private cwd: string) {}
3030

3131
async open(relPath: string): Promise<void> {
@@ -83,6 +83,20 @@ export class DiffViewProvider {
8383
break // Found the relevant tab, no need to check others
8484
}
8585
}
86+
87+
// Store the currently focused editor before opening the diff
88+
const activeEditor = vscode.window.activeTextEditor
89+
if (activeEditor && activeEditor.viewColumn !== undefined) {
90+
// Check if viewColumn is defined
91+
this.userFocusedEditorInfo = {
92+
uri: activeEditor.document.uri,
93+
viewColumn: activeEditor.viewColumn, // Now guaranteed to be defined
94+
}
95+
} else {
96+
// If no active editor or viewColumn is undefined, reset the info
97+
this.userFocusedEditorInfo = undefined
98+
}
99+
86100
this.activeDiffEditor = await this.openDiffEditor()
87101
this.fadedOverlayController = new DecorationController("fadedOverlay", this.activeDiffEditor)
88102
this.activeLineController = new DecorationController("activeLine", this.activeDiffEditor)
@@ -259,7 +273,6 @@ export class DiffViewProvider {
259273

260274
// If the document was originally open, ensure it's focused.
261275
// The revert logic already applied the original content and saved.
262-
// If the document was originally open, ensure it's focused.
263276
await this._focusOriginalDocument(absolutePath, this.originalViewColumn)
264277
}
265278

@@ -308,16 +321,24 @@ export class DiffViewProvider {
308321
const disposable = vscode.window.onDidChangeActiveTextEditor((editor) => {
309322
if (editor && arePathsEqual(editor.document.uri.fsPath, uri.fsPath)) {
310323
disposable.dispose()
324+
// Diff editor is now active, resolve the promise
311325
resolve(editor)
312326
}
313327
})
328+
const options: vscode.TextDocumentShowOptions = {
329+
// preserveFocus: true, // Removed to prevent focus issues
330+
}
331+
if (this.originalViewColumn !== undefined) {
332+
options.viewColumn = this.originalViewColumn
333+
}
314334
vscode.commands.executeCommand(
315335
"vscode.diff",
316336
vscode.Uri.parse(`${DIFF_VIEW_URI_SCHEME}:${fileName}`).with({
317337
query: Buffer.from(this.originalContent ?? "").toString("base64"),
318338
}),
319339
uri,
320340
`${fileName}: ${fileExists ? "Original ↔ Roo's Changes" : "New File"} (Editable)`,
341+
options, // Add options here
321342
)
322343
// This may happen on very slow machines ie project idx
323344
setTimeout(() => {
@@ -371,24 +392,74 @@ export class DiffViewProvider {
371392

372393
private async _focusOriginalDocument(
373394
absolutePath: string,
374-
viewColumn: vscode.ViewColumn | undefined,
395+
viewColumn: vscode.ViewColumn | undefined, // Note: viewColumn here is the original view column of the *modified* file's tab, if it was open
375396
): Promise<void> {
376-
if (this.documentWasOpen && viewColumn) {
377-
// Find the editor for the original document and reveal it
397+
let focusRestoredOrHandled = false
398+
399+
// Priority 1: Try to restore focus to the editor the user had focused *before* the diff started
400+
if (this.userFocusedEditorInfo) {
401+
try {
402+
await vscode.window.showTextDocument(this.userFocusedEditorInfo.uri, {
403+
viewColumn: this.userFocusedEditorInfo.viewColumn,
404+
preserveFocus: false, // Force focus back
405+
})
406+
console.log("Focus restored to originally focused editor:", this.userFocusedEditorInfo.uri.fsPath)
407+
focusRestoredOrHandled = true // Mark as handled
408+
} catch (error) {
409+
console.warn("Failed to restore focus to originally focused editor, proceeding with fallbacks:", error)
410+
// Focus restoration failed, fallbacks might be needed below
411+
}
412+
} else {
413+
// If no editor was focused initially, we still might need to handle new files
414+
console.log("No initial editor focus detected, checking for new file case.")
415+
// Let the new file logic below handle it.
416+
}
417+
418+
// Handle newly created files *regardless* of initial focus state or restoration success
419+
if (!this.documentWasOpen) {
420+
try {
421+
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
422+
preview: false, // Ensure it's not a preview tab
423+
viewColumn: vscode.ViewColumn.Active, // Open in the active column
424+
preserveFocus: false, // Force focus
425+
})
426+
console.log("Opened and focused newly created file:", absolutePath)
427+
focusRestoredOrHandled = true // Mark as handled
428+
} catch (error) {
429+
console.error("Failed to show newly created document:", error)
430+
// Even if it fails, we consider the attempt 'handled' for new files.
431+
focusRestoredOrHandled = true
432+
}
433+
}
434+
435+
// Fallback logic for *existing* documents (only runs if focus restoration failed AND it wasn't a new file)
436+
if (!focusRestoredOrHandled && this.documentWasOpen && viewColumn) {
437+
console.log("Executing fallback logic for existing document as primary focus restore failed.")
438+
// Fallback 1: Try to focus the editor tab corresponding to the *modified* file
378439
const originalEditor = vscode.window.visibleTextEditors.find(
379440
(editor) => arePathsEqual(editor.document.uri.fsPath, absolutePath) && editor.viewColumn === viewColumn,
380441
)
381442
if (originalEditor) {
382-
// Reveal a range (e.g., the start) to ensure focus
383443
const position = new vscode.Position(0, 0)
384444
originalEditor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.AtTop)
445+
console.log("Focus set to modified file's original editor (fallback 1):", absolutePath)
385446
} else {
386-
// Fallback if editor not found
387-
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
388-
preview: false,
389-
viewColumn: viewColumn,
390-
})
447+
// Fallback 2: Open the modified file if its editor wasn't found
448+
try {
449+
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
450+
preview: false,
451+
viewColumn: viewColumn,
452+
preserveFocus: false, // Force focus
453+
})
454+
console.log("Opened modified file's editor (fallback 2):", absolutePath)
455+
} catch (error) {
456+
console.error("Failed to show modified document (fallback 2):", error)
457+
}
391458
}
459+
} else if (!focusRestoredOrHandled) {
460+
console.log(
461+
"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).",
462+
)
392463
}
393464
}
394465

@@ -400,6 +471,7 @@ export class DiffViewProvider {
400471
this.createdDirs = []
401472
this.documentWasOpen = false
402473
this.originalViewColumn = undefined // Reset stored view column
474+
this.userFocusedEditorInfo = undefined // Reset stored user focus info
403475
this.activeDiffEditor = undefined
404476
this.fadedOverlayController = undefined
405477
this.activeLineController = undefined

0 commit comments

Comments
 (0)