@@ -26,6 +26,9 @@ export class DiffViewProvider {
2626 private streamedLines : string [ ] = [ ]
2727 private preDiagnostics : [ vscode . Uri , vscode . Diagnostic [ ] ] [ ] = [ ]
2828 private fileEncoding : string = "utf8"
29+ private lastFirstVisibleLine : number = 0
30+ private shouldAutoScroll : boolean = true
31+ private scrollListener ?: vscode . Disposable
2932
3033 constructor ( private cwd : string ) { }
3134
@@ -34,6 +37,8 @@ export class DiffViewProvider {
3437 const fileExists = this . editType === "modify"
3538 const absolutePath = path . resolve ( this . cwd , relPath )
3639 this . isEditing = true
40+ this . shouldAutoScroll = true
41+ this . lastFirstVisibleLine = 0
3742 // if the file is already open, ensure it's not dirty before getting its contents
3843 if ( fileExists ) {
3944 const existingDocument = vscode . workspace . textDocuments . find ( ( doc ) => arePathsEqual ( doc . uri . fsPath , absolutePath ) )
@@ -79,6 +84,21 @@ export class DiffViewProvider {
7984 this . fadedOverlayController . addLines ( 0 , this . activeDiffEditor . document . lineCount )
8085 this . scrollEditorToLine ( 0 ) // will this crash for new files?
8186 this . streamedLines = [ ]
87+
88+ // Add scroll detection to disable auto-scrolling when user scrolls up
89+ this . scrollListener = vscode . window . onDidChangeTextEditorVisibleRanges ( ( e : vscode . TextEditorVisibleRangesChangeEvent ) => {
90+ if ( e . textEditor === this . activeDiffEditor ) {
91+ const currentFirstVisibleLine = e . visibleRanges [ 0 ] ?. start . line || 0
92+
93+ // If the first visible line moved upward, user scrolled up
94+ if ( currentFirstVisibleLine < this . lastFirstVisibleLine ) {
95+ this . shouldAutoScroll = false
96+ }
97+
98+ // Always update our tracking variable
99+ this . lastFirstVisibleLine = currentFirstVisibleLine
100+ }
101+ } )
82102 }
83103
84104 async update ( accumulatedContent : string , isFinal : boolean ) {
@@ -128,25 +148,30 @@ export class DiffViewProvider {
128148 this . activeLineController . setActiveLine ( currentLine )
129149 this . fadedOverlayController . updateOverlayAfterLine ( currentLine , document . lineCount )
130150
131- // Scroll to the last changed line
132- if ( diffLines . length <= 5 ) {
133- // For small changes, just jump directly to the line
134- this . scrollEditorToLine ( currentLine )
135- } else {
136- // For larger changes, create a quick scrolling animation
137- const startLine = this . streamedLines . length
138- const endLine = currentLine
139- const totalLines = endLine - startLine
140- const numSteps = 10 // Adjust this number to control animation speed
141- const stepSize = Math . max ( 1 , Math . floor ( totalLines / numSteps ) )
142-
143- // Create and await the smooth scrolling animation
144- for ( let line = startLine ; line <= endLine ; line += stepSize ) {
145- this . activeDiffEditor ?. revealRange ( new vscode . Range ( line , 0 , line , 0 ) , vscode . TextEditorRevealType . InCenter )
146- await new Promise ( ( resolve ) => setTimeout ( resolve , 16 ) ) // ~60fps
151+ // Scroll to the last changed line only if the user hasn't scrolled up
152+ if ( this . shouldAutoScroll ) {
153+ if ( diffLines . length <= 5 ) {
154+ // For small changes, just jump directly to the line
155+ this . scrollEditorToLine ( currentLine )
156+ } else {
157+ // For larger changes, create a quick scrolling animation
158+ const startLine = this . streamedLines . length
159+ const endLine = currentLine
160+ const totalLines = endLine - startLine
161+ const numSteps = 10 // Adjust this number to control animation speed
162+ const stepSize = Math . max ( 1 , Math . floor ( totalLines / numSteps ) )
163+
164+ // Create and await the smooth scrolling animation
165+ for ( let line = startLine ; line <= endLine ; line += stepSize ) {
166+ this . activeDiffEditor ?. revealRange (
167+ new vscode . Range ( line , 0 , line , 0 ) ,
168+ vscode . TextEditorRevealType . InCenter ,
169+ )
170+ await new Promise ( ( resolve ) => setTimeout ( resolve , 16 ) ) // ~60fps
171+ }
172+ // Ensure we end at the final line
173+ this . scrollEditorToLine ( currentLine )
147174 }
148- // Ensure we end at the final line
149- this . scrollEditorToLine ( currentLine )
150175 }
151176 }
152177
@@ -418,5 +443,15 @@ export class DiffViewProvider {
418443 this . activeLineController = undefined
419444 this . streamedLines = [ ]
420445 this . preDiagnostics = [ ]
446+
447+ // Clean up the scroll listener
448+ if ( this . scrollListener ) {
449+ this . scrollListener . dispose ( )
450+ this . scrollListener = undefined
451+ }
452+
453+ // Reset auto-scroll state
454+ this . shouldAutoScroll = true
455+ this . lastFirstVisibleLine = 0
421456 }
422457}
0 commit comments