mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
lazy load webview if there is no webview outputs or not kernel dependencies
This commit is contained in:
parent
cf9d6d7667
commit
9c467b969c
|
@ -933,7 +933,7 @@ suite('webview', () => {
|
|||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
// assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
// const uri = vscode.notebook.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
|
||||
// assert.equal(uri.scheme, 'vscode-resource');
|
||||
// assert.equal(uri.scheme, 'vscode-webview-resource');
|
||||
// await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
// });
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
private _overlayContainer!: HTMLElement;
|
||||
private _body!: HTMLElement;
|
||||
private _webview: BackLayerWebView | null = null;
|
||||
private _webviewResolved: boolean = false;
|
||||
private _webviewResolvePromise: Promise<BackLayerWebView | null> | null = null;
|
||||
private _webviewTransparentCover: HTMLElement | null = null;
|
||||
private _list: INotebookCellList | undefined;
|
||||
private _dndController: CellDragAndDropController | null = null;
|
||||
|
@ -591,7 +593,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
// @deprecated
|
||||
if (provider && provider.kernel) {
|
||||
// it has a builtin kernel, don't automatically choose a kernel
|
||||
this._loadKernelPreloads(provider.providerExtensionLocation, provider.kernel);
|
||||
await this._loadKernelPreloads(provider.providerExtensionLocation, provider.kernel);
|
||||
tokenSource.dispose();
|
||||
return;
|
||||
}
|
||||
|
@ -610,7 +612,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
// the provider doesn't have a builtin kernel, choose a kernel
|
||||
this.activeKernel = availableKernels[0];
|
||||
if (this.activeKernel) {
|
||||
this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
|
@ -630,7 +632,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
}
|
||||
|
||||
if (this.activeKernel) {
|
||||
this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await this.activeKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
}
|
||||
|
||||
|
@ -643,7 +645,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
if (kernelsFromSameExtension.length) {
|
||||
const preferedKernel = kernelsFromSameExtension.find(kernel => kernel.isPreferred) || kernelsFromSameExtension[0];
|
||||
this.activeKernel = preferedKernel;
|
||||
this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await preferedKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
tokenSource.dispose();
|
||||
return;
|
||||
|
@ -652,15 +654,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
// the provider doesn't have a builtin kernel, choose a kernel
|
||||
this.activeKernel = kernels[0];
|
||||
if (this.activeKernel) {
|
||||
this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
await this.activeKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
}
|
||||
|
||||
private _loadKernelPreloads(extensionLocation: URI, kernel: INotebookKernelInfoDto) {
|
||||
if (kernel.preloads) {
|
||||
private async _loadKernelPreloads(extensionLocation: URI, kernel: INotebookKernelInfoDto) {
|
||||
if (kernel.preloads && kernel.preloads.length) {
|
||||
await this._resolveWebview();
|
||||
this._webview?.updateKernelPreloads([extensionLocation], kernel.preloads.map(preload => URI.revive(preload)));
|
||||
}
|
||||
}
|
||||
|
@ -675,34 +678,63 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
this._notebookExecuting?.set(notebookMetadata.runState === NotebookRunState.Running);
|
||||
}
|
||||
|
||||
private async _resolveWebview(): Promise<BackLayerWebView | null> {
|
||||
if (!this.textModel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._webviewResolvePromise) {
|
||||
return this._webviewResolvePromise;
|
||||
}
|
||||
|
||||
if (!this._webview) {
|
||||
this._webview = this.instantiationService.createInstance(BackLayerWebView, this, this.getId(), this.textModel!.uri);
|
||||
// attach the webview container to the DOM tree first
|
||||
this._list?.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element);
|
||||
}
|
||||
|
||||
this._webviewResolvePromise = new Promise(async resolve => {
|
||||
await this._webview!.createWebview();
|
||||
this._webview!.webview!.onDidBlur(() => {
|
||||
this._outputFocus?.set(false);
|
||||
this.updateEditorFocus();
|
||||
|
||||
if (this._overlayContainer.contains(document.activeElement)) {
|
||||
this._webiewFocused = false;
|
||||
}
|
||||
});
|
||||
this._webview!.webview!.onDidFocus(() => {
|
||||
this._outputFocus?.set(true);
|
||||
this.updateEditorFocus();
|
||||
this._onDidFocusEmitter.fire();
|
||||
|
||||
if (this._overlayContainer.contains(document.activeElement)) {
|
||||
this._webiewFocused = true;
|
||||
}
|
||||
});
|
||||
|
||||
this._localStore.add(this._webview!.onMessage(({ message, forRenderer }) => {
|
||||
if (this.viewModel) {
|
||||
this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.getId(), forRenderer, message);
|
||||
}
|
||||
}));
|
||||
|
||||
if (this.viewModel && this.viewModel!.renderers.size) {
|
||||
this._webview?.updateRendererPreloads(this.viewModel!.renderers);
|
||||
}
|
||||
|
||||
this._webviewResolved = true;
|
||||
|
||||
resolve(this._webview!);
|
||||
});
|
||||
|
||||
return this._webviewResolvePromise;
|
||||
}
|
||||
|
||||
private async _createWebview(id: string, resource: URI): Promise<void> {
|
||||
this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource);
|
||||
// attach the webview container to the DOM tree first
|
||||
this._list?.rowsContainer.insertAdjacentElement('afterbegin', this._webview.element);
|
||||
await this._webview.createWebview();
|
||||
this._webview.webview.onDidBlur(() => {
|
||||
this._outputFocus?.set(false);
|
||||
this.updateEditorFocus();
|
||||
|
||||
if (this._overlayContainer.contains(document.activeElement)) {
|
||||
this._webiewFocused = false;
|
||||
}
|
||||
});
|
||||
this._webview.webview.onDidFocus(() => {
|
||||
this._outputFocus?.set(true);
|
||||
this.updateEditorFocus();
|
||||
this._onDidFocusEmitter.fire();
|
||||
|
||||
if (this._overlayContainer.contains(document.activeElement)) {
|
||||
this._webiewFocused = true;
|
||||
}
|
||||
});
|
||||
|
||||
this._localStore.add(this._webview.onMessage(({ message, forRenderer }) => {
|
||||
if (this.viewModel) {
|
||||
this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.getId(), forRenderer, message);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined) {
|
||||
|
@ -736,10 +768,17 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
}
|
||||
}
|
||||
|
||||
this._webview?.updateRendererPreloads(this.viewModel.renderers);
|
||||
if (this.viewModel.renderers.size) {
|
||||
await this._resolveWebview();
|
||||
this._webview?.updateRendererPreloads(this.viewModel.renderers);
|
||||
}
|
||||
|
||||
this._localStore.add(this._list!.onWillScroll(e => {
|
||||
this._webview!.updateViewScrollTop(-e.scrollTop, []);
|
||||
if (!this._webviewResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._webview?.updateViewScrollTop(-e.scrollTop, []);
|
||||
this._webviewTransparentCover!.style.top = `${e.scrollTop}px`;
|
||||
}));
|
||||
|
||||
|
@ -751,6 +790,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
|
||||
const scrollTop = this._list?.scrollTop || 0;
|
||||
const scrollHeight = this._list?.scrollHeight || 0;
|
||||
|
||||
if (!this._webviewResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._webview!.element.style.height = `${scrollHeight}px`;
|
||||
|
||||
if (this._webview?.insetMapping) {
|
||||
|
@ -1375,6 +1419,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
return;
|
||||
}
|
||||
|
||||
await this._resolveWebview();
|
||||
|
||||
let preloads = this._notebookViewModel!.renderers;
|
||||
|
||||
if (!this._webview!.insetMapping.has(output)) {
|
||||
|
@ -1389,7 +1435,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
}
|
||||
|
||||
removeInset(output: IProcessedOutput) {
|
||||
if (!this._webview) {
|
||||
if (!this._webview || !this._webviewResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1397,7 +1443,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
}
|
||||
|
||||
hideInset(output: IProcessedOutput) {
|
||||
if (!this._webview) {
|
||||
if (!this._webview || !this._webviewResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1409,10 +1455,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
}
|
||||
|
||||
postMessage(forRendererId: string | undefined, message: any) {
|
||||
if (!this._webview || !this._webviewResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (forRendererId === undefined) {
|
||||
this._webview?.webview.postMessage(message);
|
||||
this._webview.webview?.postMessage(message);
|
||||
} else {
|
||||
this._webview?.postRendererMessage(forRendererId, message);
|
||||
this._webview.postRendererMessage(forRendererId, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ export interface INotebookWebviewMessage {
|
|||
let version = 0;
|
||||
export class BackLayerWebView extends Disposable {
|
||||
element: HTMLElement;
|
||||
webview!: WebviewElement;
|
||||
webview: WebviewElement | undefined = undefined;
|
||||
insetMapping: Map<IProcessedOutput, ICachedInset> = new Map();
|
||||
hiddenInsetMapping: Set<IProcessedOutput> = new Set();
|
||||
reversedInsetMapping: Map<string, IProcessedOutput> = new Map();
|
||||
|
@ -714,7 +714,7 @@ ${loaderJs}
|
|||
return;
|
||||
}
|
||||
|
||||
this.webview.focus();
|
||||
this.webview?.focus();
|
||||
}
|
||||
|
||||
focusOutput(cellId: string) {
|
||||
|
@ -722,7 +722,7 @@ ${loaderJs}
|
|||
return;
|
||||
}
|
||||
|
||||
this.webview.focus();
|
||||
this.webview?.focus();
|
||||
setTimeout(() => { // Need this, or focus decoration is not shown. No clue.
|
||||
this._sendMessageToWebview({
|
||||
type: 'focus-output',
|
||||
|
@ -814,6 +814,10 @@ ${loaderJs}
|
|||
}
|
||||
|
||||
private _updatePreloads(resources: IPreloadResource[], source: 'renderer' | 'kernel') {
|
||||
if (!this.webview) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mixedResourceRoots = [...(this.localResourceRootsCache || []), ...this.rendererRootsCache, ...this.kernelRootsCache];
|
||||
|
||||
this.webview.localResourcesRoot = mixedResourceRoots;
|
||||
|
@ -830,7 +834,7 @@ ${loaderJs}
|
|||
return;
|
||||
}
|
||||
|
||||
this.webview.postMessage(message);
|
||||
this.webview?.postMessage(message);
|
||||
}
|
||||
|
||||
clearPreloadsCache() {
|
||||
|
@ -839,7 +843,7 @@ ${loaderJs}
|
|||
|
||||
dispose() {
|
||||
this._disposed = true;
|
||||
this.webview.dispose();
|
||||
this.webview?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue