Skip to content

Commit 47fc35d

Browse files
authored
add StableEditorBottomScrollState so that inline chat moves lines of interest less (microsoft#209637)
there is still some movement because the height of the zone changes through out the request
1 parent 927ff5b commit 47fc35d

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

src/vs/editor/browser/stableEditorScroll.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,44 @@ export class StableEditorScrollState {
6262
editor.setScrollTop(editor.getScrollTop() + offset);
6363
}
6464
}
65+
66+
67+
export class StableEditorBottomScrollState {
68+
69+
public static capture(editor: ICodeEditor): StableEditorBottomScrollState {
70+
if (editor.hasPendingScrollAnimation()) {
71+
// Never mess with the scroll if there is a pending scroll animation
72+
return new StableEditorBottomScrollState(editor.getScrollTop(), editor.getContentHeight(), null, 0);
73+
}
74+
75+
let visiblePosition: Position | null = null;
76+
let visiblePositionScrollDelta = 0;
77+
const visibleRanges = editor.getVisibleRanges();
78+
if (visibleRanges.length > 0) {
79+
visiblePosition = visibleRanges.at(-1)!.getEndPosition();
80+
const visiblePositionScrollBottom = editor.getBottomForLineNumber(visiblePosition.lineNumber);
81+
visiblePositionScrollDelta = (editor.getScrollTop() + editor.getLayoutInfo().height) - visiblePositionScrollBottom;
82+
}
83+
return new StableEditorBottomScrollState(editor.getScrollTop(), editor.getContentHeight(), visiblePosition, visiblePositionScrollDelta);
84+
}
85+
86+
constructor(
87+
private readonly _initialScrollTop: number,
88+
private readonly _initialContentHeight: number,
89+
private readonly _visiblePosition: Position | null,
90+
private readonly _visiblePositionScrollDelta: number,
91+
) {
92+
}
93+
94+
public restore(editor: ICodeEditor): void {
95+
if (this._initialContentHeight === editor.getContentHeight() && this._initialScrollTop === editor.getScrollTop()) {
96+
// The editor's content height and scroll top haven't changed, so we don't need to do anything
97+
return;
98+
}
99+
100+
if (this._visiblePosition) {
101+
const visiblePositionScrollBottom = editor.getBottomForLineNumber(this._visiblePosition.lineNumber);
102+
editor.setScrollTop(visiblePositionScrollBottom - (this._visiblePositionScrollDelta + editor.getLayoutInfo().height));
103+
}
104+
}
105+
}

src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { assertType } from 'vs/base/common/types';
99
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
1010
import { EditorLayoutInfo, EditorOption } from 'vs/editor/common/config/editorOptions';
1111
import { Position } from 'vs/editor/common/core/position';
12-
import { IRange } from 'vs/editor/common/core/range';
12+
import { IRange, Range } from 'vs/editor/common/core/range';
1313
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
1414
import { localize } from 'vs/nls';
1515
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -18,6 +18,8 @@ import { ACTION_ACCEPT_CHANGES, ACTION_REGENERATE_RESPONSE, ACTION_TOGGLE_DIFF,
1818
import { EditorBasedInlineChatWidget } from './inlineChatWidget';
1919
import { MenuId } from 'vs/platform/actions/common/actions';
2020
import { isEqual } from 'vs/base/common/resources';
21+
import { StableEditorBottomScrollState } from 'vs/editor/browser/stableEditorScroll';
22+
import { ScrollType } from 'vs/editor/common/editorCommon';
2123

2224

2325
export class InlineChatZoneWidget extends ZoneWidget {
@@ -128,13 +130,17 @@ export class InlineChatZoneWidget extends ZoneWidget {
128130
override show(position: Position): void {
129131
assertType(this.container);
130132

133+
const scrollState = StableEditorBottomScrollState.capture(this.editor);
131134
const info = this.editor.getLayoutInfo();
132135
const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth;
133136
this.container.style.marginLeft = `${marginWithoutIndentation}px`;
134137

135138
super.show(position, this._computeHeightInLines());
136139
this._setWidgetMargins(position);
137140
this.widget.focus();
141+
142+
scrollState.restore(this.editor);
143+
this.editor.revealRangeNearTopIfOutsideViewport(Range.fromPositions(position.delta(-1)), ScrollType.Immediate);
138144
}
139145

140146
override updatePositionAndHeight(position: Position): void {

0 commit comments

Comments
 (0)