Skip to content
Merged
Changes from all commits
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
35 changes: 29 additions & 6 deletions src/vs/workbench/contrib/extensions/browser/extensionEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ interface IExtensionEditorTemplate {
header: HTMLElement;
}

const enum WebviewIndex {
Readme,
Changelog
}

export class ExtensionEditor extends EditorPane {

static readonly ID: string = 'workbench.editor.extension';
Expand All @@ -179,6 +184,12 @@ export class ExtensionEditor extends EditorPane {
private extensionChangelog: Cache<string> | null;
private extensionManifest: Cache<IExtensionManifest | null> | null;

// Some action bar items use a webview whose vertical scroll position we track in this map
private initialScrollProgress: Map<WebviewIndex, number> = new Map();

// Spot when an ExtensionEditor instance gets reused for a different extension, in which case the vertical scroll positions must be zeroed
private currentIdentifier: string = '';

private layoutParticipants: ILayoutParticipant[] = [];
private readonly contentDisposables = this._register(new DisposableStore());
private readonly transientDisposables = this._register(new DisposableStore());
Expand Down Expand Up @@ -336,6 +347,11 @@ export class ExtensionEditor extends EditorPane {
this.editorLoadComplete = false;
const extension = input.extension;

if (this.currentIdentifier !== extension.identifier.id) {
this.initialScrollProgress.clear();
this.currentIdentifier = extension.identifier.id;
}

this.transientDisposables.clear();

this.extensionReadme = new Cache(() => createCancelablePromise(token => extension.getReadme(token)));
Expand Down Expand Up @@ -563,7 +579,7 @@ export class ExtensionEditor extends EditorPane {
return Promise.resolve(null);
}

private async openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> {
private async openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate, webviewIndex: WebviewIndex, token: CancellationToken): Promise<IActiveElement> {
try {
const body = await this.renderMarkdown(cacheResult, template);
if (token.isCancellationRequested) {
Expand All @@ -572,15 +588,22 @@ export class ExtensionEditor extends EditorPane {

const webview = this.contentDisposables.add(this.webviewService.createWebviewOverlay('extensionEditor', {
enableFindWidget: true,
tryRestoreScrollPosition: true,
}, {}, undefined));

webview.initialScrollProgress = this.initialScrollProgress.get(webviewIndex) || 0;

webview.claim(this, this.scopedContextKeyService);
setParentFlowTo(webview.container, template.content);
webview.layoutWebviewOverElement(template.content);

webview.html = body;
webview.claim(this);

this.contentDisposables.add(webview.onDidFocus(() => this.fireOnDidFocus()));

this.contentDisposables.add(webview.onDidScroll(() => this.initialScrollProgress.set(webviewIndex, webview.initialScrollProgress)));

const removeLayoutParticipant = arrays.insert(this.layoutParticipants, {
layout: () => {
webview.layoutWebviewOverElement(template.content);
Expand Down Expand Up @@ -823,7 +846,7 @@ export class ExtensionEditor extends EditorPane {
if (manifest && manifest.extensionPack && manifest.extensionPack.length) {
return this.openExtensionPackReadme(manifest, template, token);
}
return this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available."), template, token);
return this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available."), template, WebviewIndex.Readme, token);
}

private async openExtensionPackReadme(manifest: IExtensionManifest, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> {
Expand Down Expand Up @@ -854,15 +877,15 @@ export class ExtensionEditor extends EditorPane {
const readmeContent = append(extensionPackReadme, $('div.readme-content'));

await Promise.all([
this.renderExtensionPack(manifest, extensionPackContent, token),
this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available."), { ...template, ...{ content: readmeContent } }, token),
this.renderExtensionPack(manifest, extensionPackContent),
this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available."), { ...template, ...{ content: readmeContent } }, WebviewIndex.Readme, token),
]);

return { focus: () => extensionPackContent.focus() };
}

private openChangelog(template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> {
return this.openMarkdown(this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available."), template, token);
private openChangelog(template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement> {
return this.openMarkdown(this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available."), template, WebviewIndex.Changelog, token);
}

private openContributions(template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> {
Expand Down