Remember chat editor scroll position when switching tabs (#295278)

This commit is contained in:
Rob Lourens
2026-02-13 23:58:21 +00:00
committed by GitHub
parent 93e553f7ff
commit 2d0b88e904
2 changed files with 46 additions and 6 deletions

View File

@@ -634,6 +634,14 @@ export class ChatWidget extends Disposable implements IChatWidget {
return this.input.height.get() + this.listWidget.contentHeight + this.chatSuggestNextWidget.height;
}
get scrollTop(): number {
return this.listWidget.scrollTop;
}
set scrollTop(value: number) {
this.listWidget.scrollTop = value;
}
get attachmentModel(): ChatAttachmentModel {
return this.input.attachmentModel;
}

View File

@@ -9,7 +9,9 @@ import { raceCancellationError } from '../../../../../../base/common/async.js';
import { CancellationToken } from '../../../../../../base/common/cancellation.js';
import { Codicon } from '../../../../../../base/common/codicons.js';
import { ThemeIcon } from '../../../../../../base/common/themables.js';
import { URI } from '../../../../../../base/common/uri.js';
import * as nls from '../../../../../../nls.js';
import { ITextResourceConfigurationService } from '../../../../../../editor/common/services/textResourceConfiguration.js';
import { IContextKeyService, IScopedContextKeyService } from '../../../../../../platform/contextkey/common/contextkey.js';
import { IEditorOptions } from '../../../../../../platform/editor/common/editor.js';
import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js';
@@ -18,10 +20,12 @@ import { IStorageService } from '../../../../../../platform/storage/common/stora
import { ITelemetryService } from '../../../../../../platform/telemetry/common/telemetry.js';
import { editorBackground, editorForeground, inputBackground } from '../../../../../../platform/theme/common/colorRegistry.js';
import { IThemeService } from '../../../../../../platform/theme/common/themeService.js';
import { EditorPane } from '../../../../../browser/parts/editor/editorPane.js';
import { AbstractEditorWithViewState } from '../../../../../browser/parts/editor/editorWithViewState.js';
import { IEditorOpenContext } from '../../../../../common/editor.js';
import { EditorInput } from '../../../../../common/editor/editorInput.js';
import { EDITOR_DRAG_AND_DROP_BACKGROUND } from '../../../../../common/theme.js';
import { IEditorGroup } from '../../../../../services/editor/common/editorGroupsService.js';
import { IEditorGroup, IEditorGroupsService } from '../../../../../services/editor/common/editorGroupsService.js';
import { IEditorService } from '../../../../../services/editor/common/editorService.js';
import { ChatContextKeys } from '../../../common/actions/chatContextKeys.js';
import { IChatModel, IChatModelInputState, IExportableChatData, ISerializableChatData } from '../../../common/model/chatModel.js';
import { IChatService } from '../../../common/chatService/chatService.js';
@@ -45,7 +49,13 @@ export interface IChatEditorOptions extends IEditorOptions {
};
}
export class ChatEditor extends EditorPane {
export interface IChatEditorViewState {
scrollTop: number;
}
export class ChatEditor extends AbstractEditorWithViewState<IChatEditorViewState> {
private static readonly VIEW_STATE_KEY = 'chatEditorViewState';
private _widget!: ChatWidget;
public get widget(): ChatWidget {
return this._widget;
@@ -63,13 +73,16 @@ export class ChatEditor extends EditorPane {
group: IEditorGroup,
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IInstantiationService instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService,
@IChatSessionsService private readonly chatSessionsService: IChatSessionsService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IChatService private readonly chatService: IChatService,
@ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService,
@IEditorService editorService: IEditorService,
@IEditorGroupsService editorGroupService: IEditorGroupsService,
) {
super(ChatEditorInput.EditorID, group, telemetryService, themeService, storageService);
super(ChatEditorInput.EditorID, group, ChatEditor.VIEW_STATE_KEY, telemetryService, instantiationService, storageService, textResourceConfigurationService, themeService, editorService, editorGroupService);
}
private async clear() {
@@ -138,7 +151,6 @@ export class ChatEditor extends EditorPane {
}
override clearInput(): void {
this.saveState();
this.widget.setModel(undefined);
super.clearInput();
}
@@ -242,6 +254,11 @@ export class ChatEditor extends EditorPane {
this.updateModel(editorModel.model);
const viewState = this.loadEditorViewState(input, context);
if (viewState) {
this._widget.scrollTop = viewState.scrollTop;
}
if (isContributedChatSession && options?.title?.preferred && input.sessionResource) {
this.chatService.setChatSessionTitle(input.sessionResource, options.title.preferred);
}
@@ -255,6 +272,21 @@ export class ChatEditor extends EditorPane {
this.widget.setModel(model);
}
protected computeEditorViewState(_resource: URI): IChatEditorViewState | undefined {
if (!this._widget) {
return undefined;
}
return { scrollTop: this._widget.scrollTop };
}
protected tracksEditorViewState(input: EditorInput): boolean {
return input instanceof ChatEditorInput;
}
protected toEditorViewStateResource(input: EditorInput): URI | undefined {
return (input as ChatEditorInput).sessionResource;
}
override layout(dimension: dom.Dimension, position?: dom.IDomPosition | undefined): void {
this.dimension = dimension;
if (this.widget) {