4
4
*--------------------------------------------------------------------------------------------*/
5
5
import { addDisposableListener , Dimension } from 'vs/base/browser/dom' ;
6
6
import * as aria from 'vs/base/browser/ui/aria/aria' ;
7
- import { toDisposable } from 'vs/base/common/lifecycle' ;
7
+ import { MutableDisposable , toDisposable } from 'vs/base/common/lifecycle' ;
8
8
import { assertType } from 'vs/base/common/types' ;
9
9
import { ICodeEditor } from 'vs/editor/browser/editorBrowser' ;
10
10
import { EditorLayoutInfo , EditorOption } from 'vs/editor/common/config/editorOptions' ;
@@ -29,6 +29,7 @@ export class InlineChatZoneWidget extends ZoneWidget {
29
29
30
30
readonly widget : EditorBasedInlineChatWidget ;
31
31
32
+ private readonly _scrollUp = this . _disposables . add ( new ScrollUpState ( this . editor ) ) ;
32
33
private readonly _ctxCursorPosition : IContextKey < 'above' | 'below' | '' > ;
33
34
private _dimension ?: Dimension ;
34
35
@@ -165,6 +166,7 @@ export class InlineChatZoneWidget extends ZoneWidget {
165
166
this . widget . focus ( ) ;
166
167
167
168
revealZone ( ) ;
169
+ this . _scrollUp . enable ( ) ;
168
170
}
169
171
170
172
override updatePositionAndHeight ( position : Position ) : void {
@@ -186,14 +188,15 @@ export class InlineChatZoneWidget extends ZoneWidget {
186
188
return isResponseVM ( candidate ) && candidate . response . value . length > 0 ;
187
189
} ) ;
188
190
189
- if ( hasResponse && zoneTop < scrollTop ) {
191
+ if ( hasResponse && zoneTop < scrollTop || this . _scrollUp . didScrollUp ) {
190
192
// don't reveal the zone if it is already out of view (unless we are still getting ready)
191
- return ( ) => {
193
+ // or if an outside scroll-up happened (e.g the user scrolled up to see the new content)
194
+ return this . _scrollUp . runIgnored ( ( ) => {
192
195
scrollState . restore ( this . editor ) ;
193
- } ;
196
+ } ) ;
194
197
}
195
198
196
- return ( ) => {
199
+ return this . _scrollUp . runIgnored ( ( ) => {
197
200
scrollState . restore ( this . editor ) ;
198
201
199
202
const scrollTop = this . editor . getScrollTop ( ) ;
@@ -216,7 +219,7 @@ export class InlineChatZoneWidget extends ZoneWidget {
216
219
this . _logService . trace ( '[IE] REVEAL zone' , { zoneTop, lineTop, lineBottom, scrollTop, newScrollTop, forceScrollTop } ) ;
217
220
this . editor . setScrollTop ( newScrollTop , ScrollType . Immediate ) ;
218
221
}
219
- } ;
222
+ } ) ;
220
223
}
221
224
222
225
protected override revealRange ( range : Range , isLastLine : boolean ) : void {
@@ -229,6 +232,7 @@ export class InlineChatZoneWidget extends ZoneWidget {
229
232
230
233
override hide ( ) : void {
231
234
const scrollState = StableEditorBottomScrollState . capture ( this . editor ) ;
235
+ this . _scrollUp . disable ( ) ;
232
236
this . _ctxCursorPosition . reset ( ) ;
233
237
this . widget . reset ( ) ;
234
238
this . widget . chatWidget . setVisible ( false ) ;
@@ -237,3 +241,54 @@ export class InlineChatZoneWidget extends ZoneWidget {
237
241
scrollState . restore ( this . editor ) ;
238
242
}
239
243
}
244
+
245
+ class ScrollUpState {
246
+
247
+ private _lastScrollTop : number = this . _editor . getScrollTop ( ) ;
248
+ private _didScrollUp ?: boolean ;
249
+ private _ignoreEvents = false ;
250
+
251
+ private readonly _listener = new MutableDisposable ( ) ;
252
+
253
+ constructor ( private readonly _editor : ICodeEditor ) { }
254
+
255
+ dispose ( ) : void {
256
+ this . _listener . dispose ( ) ;
257
+ }
258
+
259
+ enable ( ) : void {
260
+ this . _didScrollUp = undefined ;
261
+ this . _listener . value = this . _editor . onDidScrollChange ( e => {
262
+ if ( ! e . scrollTopChanged || this . _ignoreEvents ) {
263
+ return ;
264
+ }
265
+ const currentScrollTop = e . scrollTop ;
266
+ if ( currentScrollTop > this . _lastScrollTop ) {
267
+ this . _listener . clear ( ) ;
268
+ this . _didScrollUp = true ;
269
+ }
270
+ this . _lastScrollTop = currentScrollTop ;
271
+ } ) ;
272
+ }
273
+
274
+ disable ( ) : void {
275
+ this . _listener . clear ( ) ;
276
+ this . _didScrollUp = undefined ;
277
+ }
278
+
279
+ runIgnored ( callback : ( ) => void ) : ( ) => void {
280
+ return ( ) => {
281
+ this . _ignoreEvents = true ;
282
+ try {
283
+ return callback ( ) ;
284
+ } finally {
285
+ this . _ignoreEvents = false ;
286
+ }
287
+ } ;
288
+ }
289
+
290
+ get didScrollUp ( ) : boolean | undefined {
291
+ return this . _didScrollUp ;
292
+ }
293
+
294
+ }
0 commit comments