Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,8 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
parent,
{
focusChat: () => this._widget.focusInput()
}
},
undefined
));

this._register(this.titleControl.onDidChangeHeight(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { renderAsPlaintext } from '../../../../../../base/browser/markdownRender
import { Gesture, EventType as TouchEventType } from '../../../../../../base/browser/touch.js';
import { Emitter } from '../../../../../../base/common/event.js';
import { MarkdownString } from '../../../../../../base/common/htmlContent.js';
import { Disposable, MutableDisposable } from '../../../../../../base/common/lifecycle.js';
import { Disposable, MutableDisposable, toDisposable } from '../../../../../../base/common/lifecycle.js';
import { MarshalledId } from '../../../../../../base/common/marshallingIds.js';
import { localize } from '../../../../../../nls.js';
import { HiddenItemStrategy, MenuWorkbenchToolBar } from '../../../../../../platform/actions/browser/toolbar.js';
Expand Down Expand Up @@ -49,11 +49,26 @@ export class ChatViewTitleControl extends Disposable {
constructor(
private readonly container: HTMLElement,
private readonly delegate: IChatViewTitleDelegate,
createResizeObserver: (callback: ResizeObserverCallback) => ResizeObserver = callback => new ResizeObserver(callback),
@IInstantiationService private readonly instantiationService: IInstantiationService,
) {
super();

this.render(this.container);
// Avoid forcing layout; ResizeObserver reports the final size before paint and triggers relayout.
const resizeObserver = createResizeObserver(entries => {
Comment thread
dmitrivMS marked this conversation as resolved.
Outdated
const entry = entries.find(entry => entry.target === this.titleContainer);
if (!entry) {
return;
}
const height = entry.borderBoxSize[0]?.blockSize ?? entry.contentRect.height;
if (height !== this.lastKnownHeight) {
this.lastKnownHeight = height;
this._onDidChangeHeight.fire();
}
});
resizeObserver.observe(this.titleContainer!);
Comment thread
dmitrivMS marked this conversation as resolved.
Outdated
this._register(toDisposable(() => resizeObserver.disconnect()));

this.registerActions();
}
Expand Down Expand Up @@ -165,25 +180,14 @@ export class ChatViewTitleControl extends Disposable {

this.titleContainer.classList.toggle('visible', this.shouldRender());
this.titleLabel.value?.updateTitle(title);

const currentHeight = this.getHeight();
if (currentHeight !== this.lastKnownHeight) {
this.lastKnownHeight = currentHeight;

this._onDidChangeHeight.fire();
}
}

private shouldRender(): boolean {
return !!this.model?.title; // we need a chat showing and not being empty
}

getHeight(): number {
if (!this.titleContainer || this.titleContainer.style.display === 'none') {
return 0;
}

return this.titleContainer.offsetHeight;
return this.lastKnownHeight;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import assert from 'assert';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../../base/test/common/utils.js';
import { TestInstantiationService } from '../../../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
import { MenuWorkbenchToolBar } from '../../../../../../../platform/actions/browser/toolbar.js';
import { ChatViewTitleControl } from '../../../../browser/widgetHosts/viewPane/chatViewTitleControl.js';

class TestResizeObserver implements ResizeObserver {
private callback: ResizeObserverCallback | undefined;
private target: Element | undefined;

readonly create = (callback: ResizeObserverCallback): ResizeObserver => {
this.callback = callback;
return this;
};

observe(target: Element): void {
this.target = target;
}

unobserve(): void { }
disconnect(): void { }
takeRecords(): ResizeObserverEntry[] { return []; }

fire(height: number): void {
assert.ok(this.target);
const size: ResizeObserverSize = { inlineSize: 0, blockSize: height };
this.callback?.([{
target: this.target,
contentRect: DOMRectReadOnly.fromRect({ height }),
borderBoxSize: [size],
contentBoxSize: [size],
devicePixelContentBoxSize: [size],
}], this);
}
}

suite('ChatViewTitleControl', () => {
const disposables = ensureNoDisposablesAreLeakedInTestSuite();

test('tracks height changes from ResizeObserver', () => {
const container = document.createElement('div');
const resizeObserver = new TestResizeObserver();
const instantiationService = disposables.add(new TestInstantiationService());
instantiationService.stubInstance(MenuWorkbenchToolBar, { dispose: () => { } });
const control = disposables.add(instantiationService.createInstance(
ChatViewTitleControl,
container,
{ focusChat: () => { } },
resizeObserver.create
));
let heightChangeCount = 0;
disposables.add(control.onDidChangeHeight(() => heightChangeCount++));

resizeObserver.fire(22);
resizeObserver.fire(22);
resizeObserver.fire(0);

assert.deepStrictEqual({
height: control.getHeight(),
heightChangeCount
}, {
height: 0,
heightChangeCount: 2
});
});
});
Loading