Skip to content

Commit f7cc48c

Browse files
authored
restore zone top only when not having been scrolled out already (microsoft#226395)
fixes microsoft/vscode-copilot#7338
1 parent 555329f commit f7cc48c

File tree

1 file changed

+47
-36
lines changed

1 file changed

+47
-36
lines changed

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

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
2323
import { ILogService } from 'vs/platform/log/common/log';
2424
import { IChatWidgetLocationOptions } from 'vs/workbench/contrib/chat/browser/chatWidget';
2525
import { MenuId } from 'vs/platform/actions/common/actions';
26+
import { isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
2627

2728
export class InlineChatZoneWidget extends ZoneWidget {
2829

@@ -78,21 +79,20 @@ export class InlineChatZoneWidget extends ZoneWidget {
7879
});
7980
this._disposables.add(this.widget);
8081

81-
let scrollState: StableEditorBottomScrollState | undefined;
82+
let revealFn: (() => void) | undefined;
8283
this._disposables.add(this.widget.chatWidget.onWillMaybeChangeHeight(() => {
8384
if (this.position) {
84-
scrollState = StableEditorBottomScrollState.capture(this.editor);
85+
revealFn = this._createZoneAndScrollRestoreFn(this.position);
8586
}
8687
}));
8788
this._disposables.add(this.widget.onDidChangeHeight(() => {
8889
if (this.position) {
8990
// only relayout when visible
90-
scrollState ??= StableEditorBottomScrollState.capture(this.editor);
91+
revealFn ??= this._createZoneAndScrollRestoreFn(this.position);
9192
const height = this._computeHeight();
9293
this._relayout(height.linesValue);
93-
scrollState.restore(this.editor);
94-
scrollState = undefined;
95-
this._revealTopOfZoneWidget(this.position, height);
94+
revealFn();
95+
revealFn = undefined;
9696
}
9797
}));
9898

@@ -154,57 +154,68 @@ export class InlineChatZoneWidget extends ZoneWidget {
154154
override show(position: Position): void {
155155
assertType(this.container);
156156

157-
const scrollState = StableEditorBottomScrollState.capture(this.editor);
158157
const info = this.editor.getLayoutInfo();
159158
const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth;
160159
this.container.style.marginLeft = `${marginWithoutIndentation}px`;
161160

162-
const height = this._computeHeight();
163-
super.show(position, height.linesValue);
161+
const revealZone = this._createZoneAndScrollRestoreFn(position);
162+
super.show(position, this._computeHeight().linesValue);
164163
this.widget.chatWidget.setVisible(true);
165164
this.widget.focus();
166165

167-
scrollState.restore(this.editor);
168-
169-
this._revealTopOfZoneWidget(position, height);
166+
revealZone();
170167
}
171168

172169
override updatePositionAndHeight(position: Position): void {
173-
const scrollState = StableEditorBottomScrollState.capture(this.editor);
174-
const height = this._computeHeight();
175-
super.updatePositionAndHeight(position, height.linesValue);
176-
scrollState.restore(this.editor);
177-
178-
this._revealTopOfZoneWidget(position, height);
170+
const revealZone = this._createZoneAndScrollRestoreFn(position);
171+
super.updatePositionAndHeight(position, this._computeHeight().linesValue);
172+
revealZone();
179173
}
180174

181-
private _revealTopOfZoneWidget(position: Position, height: { linesValue: number; pixelsValue: number }) {
175+
private _createZoneAndScrollRestoreFn(position: Position): () => void {
182176

183-
// reveal top of zone widget
177+
const scrollState = StableEditorBottomScrollState.capture(this.editor);
184178

185179
const lineNumber = position.lineNumber <= 1 ? 1 : 1 + position.lineNumber;
186-
187180
const scrollTop = this.editor.getScrollTop();
188181
const lineTop = this.editor.getTopForLineNumber(lineNumber);
189-
const zoneTop = lineTop - height.pixelsValue;
190-
191-
const editorHeight = this.editor.getLayoutInfo().height;
192-
const lineBottom = this.editor.getBottomForLineNumber(lineNumber);
182+
const zoneTop = lineTop - this._computeHeight().pixelsValue;
193183

194-
let newScrollTop = zoneTop;
195-
let forceScrollTop = false;
184+
const hasResponse = this.widget.chatWidget.viewModel?.getItems().find(candidate => {
185+
return isResponseVM(candidate) && candidate.response.value.length > 0;
186+
});
196187

197-
if (lineBottom >= (scrollTop + editorHeight)) {
198-
// revealing the top of the zone would pust out the line we are interested it and
199-
// therefore we keep the line in the view port
200-
newScrollTop = lineBottom - editorHeight;
201-
forceScrollTop = true;
188+
if (hasResponse && zoneTop < scrollTop) {
189+
// don't reveal the zone if it is already out of view (unless we are still getting ready)
190+
return () => {
191+
scrollState.restore(this.editor);
192+
};
202193
}
203194

204-
if (newScrollTop < scrollTop || forceScrollTop) {
205-
this._logService.trace('[IE] REVEAL zone', { zoneTop, lineTop, lineBottom, scrollTop, newScrollTop, forceScrollTop });
206-
this.editor.setScrollTop(newScrollTop, ScrollType.Immediate);
207-
}
195+
return () => {
196+
scrollState.restore(this.editor);
197+
198+
const scrollTop = this.editor.getScrollTop();
199+
const lineTop = this.editor.getTopForLineNumber(lineNumber);
200+
const zoneTop = lineTop - this._computeHeight().pixelsValue;
201+
const editorHeight = this.editor.getLayoutInfo().height;
202+
const lineBottom = this.editor.getBottomForLineNumber(lineNumber);
203+
204+
let newScrollTop = zoneTop;
205+
let forceScrollTop = false;
206+
207+
if (lineBottom >= (scrollTop + editorHeight)) {
208+
// revealing the top of the zone would push out the line we are interested in and
209+
// therefore we keep the line in the viewport
210+
newScrollTop = lineBottom - editorHeight;
211+
forceScrollTop = true;
212+
}
213+
214+
if (newScrollTop < scrollTop || forceScrollTop) {
215+
this._logService.trace('[IE] REVEAL zone', { zoneTop, lineTop, lineBottom, scrollTop, newScrollTop, forceScrollTop });
216+
this.editor.setScrollTop(newScrollTop, ScrollType.Immediate);
217+
}
218+
};
208219
}
209220

210221
protected override revealRange(range: Range, isLastLine: boolean): void {

0 commit comments

Comments
 (0)