Skip to content

Commit 4ddef94

Browse files
authored
Reuse webviews in walkthrough steps instead of creating them each time. (microsoft#186267)
Reuse webviews
1 parent da7f05a commit 4ddef94

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import { ILink, LinkedText } from 'vs/base/common/linkedText';
4242
import { Button } from 'vs/base/browser/ui/button/button';
4343
import { Link } from 'vs/platform/opener/browser/link';
4444
import { renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
45-
import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
45+
import { IWebviewElement, IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
4646
import { ILanguageService } from 'vs/editor/common/languages/language';
4747
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
4848
import { generateUuid } from 'vs/base/common/uuid';
@@ -128,6 +128,7 @@ export class GettingStartedPage extends EditorPane {
128128
private dispatchListeners: DisposableStore = new DisposableStore();
129129
private stepDisposables: DisposableStore = new DisposableStore();
130130
private detailsPageDisposables: DisposableStore = new DisposableStore();
131+
private mediaDisposables: DisposableStore = new DisposableStore();
131132

132133
// Ensure that the these are initialized before use.
133134
// Currently initialized before use in buildCategoriesSlide and scrollToCategory
@@ -158,6 +159,7 @@ export class GettingStartedPage extends EditorPane {
158159
private categoriesSlide!: HTMLElement;
159160
private stepsContent!: HTMLElement;
160161
private stepMediaComponent!: HTMLElement;
162+
private webview!: IWebviewElement;
161163

162164
private layoutMarkdown: (() => void) | undefined;
163165

@@ -494,6 +496,7 @@ export class GettingStartedPage extends EditorPane {
494496
}
495497

496498
private currentMediaComponent: string | undefined = undefined;
499+
private currentMediaType: string | undefined = undefined;
497500
private async buildMediaComponent(stepId: string) {
498501
if (!this.currentWalkthrough) {
499502
throw Error('no walkthrough selected');
@@ -507,11 +510,29 @@ export class GettingStartedPage extends EditorPane {
507510

508511
this.stepDisposables.add({
509512
dispose: () => {
510-
clearNode(this.stepMediaComponent);
511513
this.currentMediaComponent = undefined;
512514
}
513515
});
514516

517+
if (this.currentMediaType !== stepToExpand.media.type) {
518+
519+
this.currentMediaType = stepToExpand.media.type;
520+
521+
this.mediaDisposables.add(toDisposable(() => {
522+
this.currentMediaType = undefined;
523+
}));
524+
525+
clearNode(this.stepMediaComponent);
526+
527+
if (stepToExpand.media.type === 'svg') {
528+
this.webview = this.mediaDisposables.add(this.webviewService.createWebviewElement({ title: undefined, options: { disableServiceWorker: true }, contentOptions: {}, extension: undefined }));
529+
this.webview.mountTo(this.stepMediaComponent);
530+
} else if (stepToExpand.media.type === 'markdown') {
531+
this.webview = this.mediaDisposables.add(this.webviewService.createWebviewElement({ options: {}, contentOptions: { localResourceRoots: [stepToExpand.media.root], allowScripts: true }, title: '', extension: undefined }));
532+
this.webview.mountTo(this.stepMediaComponent);
533+
}
534+
}
535+
515536
if (stepToExpand.media.type === 'image') {
516537

517538
this.stepsContent.classList.add('image');
@@ -542,10 +563,7 @@ export class GettingStartedPage extends EditorPane {
542563
this.stepsContent.classList.remove('markdown');
543564

544565
const media = stepToExpand.media;
545-
const webview = this.stepDisposables.add(this.webviewService.createWebviewElement({ title: undefined, options: {}, contentOptions: {}, extension: undefined }));
546-
webview.mountTo(this.stepMediaComponent);
547-
548-
webview.setHtml(await this.detailsRenderer.renderSVG(media.path));
566+
this.webview.setHtml(await this.detailsRenderer.renderSVG(media.path));
549567

550568
let isDisposed = false;
551569
this.stepDisposables.add(toDisposable(() => { isDisposed = true; }));
@@ -554,7 +572,7 @@ export class GettingStartedPage extends EditorPane {
554572
// Render again since color vars change
555573
const body = await this.detailsRenderer.renderSVG(media.path);
556574
if (!isDisposed) { // Make sure we weren't disposed of in the meantime
557-
webview.setHtml(body);
575+
this.webview.setHtml(body);
558576
}
559577
}));
560578

@@ -569,7 +587,7 @@ export class GettingStartedPage extends EditorPane {
569587
}
570588
}));
571589

572-
this.stepDisposables.add(webview.onDidClickLink(link => {
590+
this.stepDisposables.add(this.webview.onDidClickLink(link => {
573591
if (matchesScheme(link, Schemas.https) || matchesScheme(link, Schemas.http) || (matchesScheme(link, Schemas.command))) {
574592
this.openerService.open(link, { allowCommands: true });
575593
}
@@ -583,11 +601,8 @@ export class GettingStartedPage extends EditorPane {
583601

584602
const media = stepToExpand.media;
585603

586-
const webview = this.stepDisposables.add(this.webviewService.createWebviewElement({ options: {}, contentOptions: { localResourceRoots: [media.root], allowScripts: true }, title: '', extension: undefined }));
587-
webview.mountTo(this.stepMediaComponent);
588-
589604
const rawHTML = await this.detailsRenderer.renderMarkdown(media.path, media.base);
590-
webview.setHtml(rawHTML);
605+
this.webview.setHtml(rawHTML);
591606

592607
const serializedContextKeyExprs = rawHTML.match(/checked-on=\"([^'][^"]*)\"/g)?.map(attr => attr.slice('checked-on="'.length, -1)
593608
.replace(/'/g, '\'')
@@ -596,7 +611,7 @@ export class GettingStartedPage extends EditorPane {
596611
const postTrueKeysMessage = () => {
597612
const enabledContextKeys = serializedContextKeyExprs?.filter(expr => this.contextService.contextMatchesRules(ContextKeyExpr.deserialize(expr)));
598613
if (enabledContextKeys) {
599-
webview.postMessage({
614+
this.webview.postMessage({
600615
enabledContextKeys
601616
});
602617
}
@@ -614,7 +629,7 @@ export class GettingStartedPage extends EditorPane {
614629
let isDisposed = false;
615630
this.stepDisposables.add(toDisposable(() => { isDisposed = true; }));
616631

617-
this.stepDisposables.add(webview.onDidClickLink(link => {
632+
this.stepDisposables.add(this.webview.onDidClickLink(link => {
618633
if (matchesScheme(link, Schemas.https) || matchesScheme(link, Schemas.http) || (matchesScheme(link, Schemas.command))) {
619634
this.openerService.open(link, { allowCommands: true });
620635
}
@@ -625,7 +640,7 @@ export class GettingStartedPage extends EditorPane {
625640
this.stepDisposables.add(this.themeService.onDidColorThemeChange(async () => {
626641
const body = await this.detailsRenderer.renderMarkdown(media.path, media.base);
627642
if (!isDisposed) { // Make sure we weren't disposed of in the meantime
628-
webview.setHtml(body);
643+
this.webview.setHtml(body);
629644
postTrueKeysMessage();
630645
}
631646
}));
@@ -635,7 +650,7 @@ export class GettingStartedPage extends EditorPane {
635650

636651
this.layoutMarkdown = () => {
637652
layoutDelayer.trigger(() => {
638-
webview.postMessage({ layoutMeNow: true });
653+
this.webview.postMessage({ layoutMeNow: true });
639654
});
640655
};
641656

@@ -644,16 +659,13 @@ export class GettingStartedPage extends EditorPane {
644659

645660
postTrueKeysMessage();
646661

647-
this.stepDisposables.add(webview.onMessage(e => {
662+
this.stepDisposables.add(this.webview.onMessage(e => {
648663
const message: string = e.message as string;
649664
if (message.startsWith('command:')) {
650665
this.openerService.open(message, { allowCommands: true });
651666
} else if (message.startsWith('setTheme:')) {
652667
this.configurationService.updateValue(ThemeSettings.COLOR_THEME, message.slice('setTheme:'.length), ConfigurationTarget.USER);
653-
} else if (message === 'unloaded') {
654-
this.buildMediaComponent(stepId);
655-
}
656-
else {
668+
} else {
657669
console.error('Unexpected message', message);
658670
}
659671
}));
@@ -1139,6 +1151,12 @@ export class GettingStartedPage extends EditorPane {
11391151
this.featuredExtensionsList?.layout(size);
11401152
this.recentlyOpenedList?.layout(size);
11411153

1154+
if (this.editorInput.selectedStep && this.currentMediaType) {
1155+
this.mediaDisposables.clear();
1156+
this.stepDisposables.clear();
1157+
this.buildMediaComponent(this.editorInput.selectedStep);
1158+
}
1159+
11421160
this.layoutMarkdown?.();
11431161

11441162
this.container.classList.toggle('height-constrained', size.height <= 600);
@@ -1352,6 +1370,7 @@ export class GettingStartedPage extends EditorPane {
13521370
});
13531371

13541372
this.detailsPageDisposables.clear();
1373+
this.mediaDisposables.clear();
13551374

13561375
const category = this.gettingStartedCategories.find(category => category.id === categoryID);
13571376
if (!category) {

src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ export class GettingStartedDetailsRenderer {
126126
<script nonce="${nonce}">
127127
const vscode = acquireVsCodeApi();
128128
129-
window.addEventListener('unload', event => {
130-
vscode.postMessage('unloaded');
131-
});
132-
133129
document.querySelectorAll('[when-checked]').forEach(el => {
134130
el.addEventListener('click', () => {
135131
vscode.postMessage(el.getAttribute('when-checked'));

0 commit comments

Comments
 (0)