Skip to content

Commit

Permalink
notebook: cache preferred mimetypes for renderers
Browse files Browse the repository at this point in the history
Fixes #119899
  • Loading branch information
connor4312 committed Apr 13, 2021
1 parent f2b1e94 commit 0905543
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 31 deletions.
36 changes: 26 additions & 10 deletions src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/ext
import { Extensions as EditorExtensions, IEditorTypesHandler, IEditorType, IEditorAssociationsRegistry } from 'vs/workbench/browser/editor';
import { Registry } from 'vs/platform/registry/common/platform';
import { Schemas } from 'vs/base/common/network';
import { Lazy } from 'vs/base/common/lazy';

export class NotebookKernelProviderInfoStore {
private readonly _notebookKernelProviders: INotebookKernelProvider[] = [];
Expand Down Expand Up @@ -206,13 +207,19 @@ export class NotebookProviderInfoStore extends Disposable {

export class NotebookOutputRendererInfoStore {
private readonly contributedRenderers = new Map<string, NotebookOutputRendererInfo>();
private readonly preferredMimetypeMemento: Memento;
private readonly preferredMimetype = new Lazy(() => this.preferredMimetypeMemento.getMemento(StorageScope.WORKSPACE, StorageTarget.USER));

constructor(@IStorageService storageService: IStorageService) {
this.preferredMimetypeMemento = new Memento('workbench.editor.notebook.preferredRenderer', storageService);
}

clear() {
this.contributedRenderers.clear();
}

get(viewType: string): NotebookOutputRendererInfo | undefined {
return this.contributedRenderers.get(viewType);
get(rendererId: string): NotebookOutputRendererInfo | undefined {
return this.contributedRenderers.get(rendererId);
}

add(info: NotebookOutputRendererInfo): void {
Expand All @@ -222,8 +229,15 @@ export class NotebookOutputRendererInfoStore {
this.contributedRenderers.set(info.id, info);
}

/** Update and remember the preferred renderer for the given mimetype in this workspace */
setPreferred(mimeType: string, rendererId: string) {
this.preferredMimetype.getValue()[mimeType] = rendererId;
this.preferredMimetypeMemento.saveMemento();
}

getContributedRenderer(mimeType: string, kernelProvides: readonly string[] | undefined): NotebookOutputRendererInfo[] {
return Array.from(this.contributedRenderers.values())
const preferred = this.preferredMimetype.getValue()[mimeType];
const possible = Array.from(this.contributedRenderers.values())
.map(renderer => ({
renderer,
score: kernelProvides === undefined
Expand All @@ -233,6 +247,8 @@ export class NotebookOutputRendererInfoStore {
.sort((a, b) => a.score - b.score)
.filter(r => r.score !== NotebookRendererMatch.Never)
.map(r => r.renderer);

return preferred ? possible.sort((a, b) => (a.id === preferred ? -1 : 0) + (b.id === preferred ? 1 : 0)) : possible;
}
}

Expand All @@ -259,7 +275,7 @@ export class NotebookService extends Disposable implements INotebookService, IEd

private readonly _notebookProviders = new Map<string, ComplexNotebookProviderInfo | SimpleNotebookProviderInfo>();
private readonly _notebookProviderInfoStore: NotebookProviderInfoStore;
private readonly _notebookRenderersInfoStore: NotebookOutputRendererInfoStore = new NotebookOutputRendererInfoStore();
private readonly _notebookRenderersInfoStore = this._instantiationService.createInstance(NotebookOutputRendererInfoStore);
private readonly _markdownRenderersInfos = new Set<INotebookMarkdownRendererInfo>();
private readonly _notebookKernelProviderInfoStore: NotebookKernelProviderInfoStore = new NotebookKernelProviderInfoStore();
private readonly _models = new ResourceMap<ModelData>();
Expand Down Expand Up @@ -535,8 +551,12 @@ export class NotebookService extends Disposable implements INotebookService, IEd
return kernelProviders;
}

getRendererInfo(id: string): INotebookRendererInfo | undefined {
return this._notebookRenderersInfoStore.get(id);
getRendererInfo(rendererId: string): INotebookRendererInfo | undefined {
return this._notebookRenderersInfoStore.get(rendererId);
}

updateMimePreferredRenderer(mimeType: string, rendererId: string): void {
this._notebookRenderersInfoStore.setPreferred(mimeType, rendererId);
}

getMarkdownRendererInfo(): INotebookMarkdownRendererInfo[] {
Expand Down Expand Up @@ -654,10 +674,6 @@ export class NotebookService extends Disposable implements INotebookService, IEd
return this._notebookProviderInfoStore.get(viewType);
}

getContributedNotebookOutputRenderers(viewType: string): NotebookOutputRendererInfo | undefined {
return this._notebookRenderersInfoStore.get(viewType);
}

getNotebookProviderResourceRoots(): URI[] {
const ret: URI[] = [];
this._notebookProviders.forEach(val => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,35 +268,36 @@ export class CellOutputElement extends Disposable {
? nls.localize('promptChooseMimeTypeInSecure.placeHolder', "Select mimetype to render for current output. Rich mimetypes are available only when the notebook is trusted")
: nls.localize('promptChooseMimeType.placeHolder', "Select mimetype to render for current output");

const pick = await new Promise<number | undefined>(resolve => {
const pick = await new Promise<IMimeTypeRenderer | undefined>(resolve => {
picker.onDidAccept(() => {
resolve(picker.selectedItems.length === 1 ? (picker.selectedItems[0] as IMimeTypeRenderer).index : undefined);
resolve(picker.selectedItems.length === 1 ? (picker.selectedItems[0] as IMimeTypeRenderer) : undefined);
picker.dispose();
});
picker.show();
});

if (pick === undefined) {
if (pick === undefined || pick.index === currIndex) {
return;
}

if (pick !== currIndex) {
// user chooses another mimetype
const index = this.viewCell.outputsViewModels.indexOf(viewModel);
const nextElement = this.domNode.nextElementSibling;
this.localDisposableStore.clear();
const element = this.domNode;
if (element) {
element.parentElement?.removeChild(element);
this.notebookEditor.removeInset(viewModel);
}

viewModel.pickedMimeType = pick;
this.viewCell.updateOutputMinHeight(this.viewCell.layoutInfo.outputTotalHeight);
this.render(index, nextElement as HTMLElement);
this._validateFinalOutputHeight(false);
this.relayoutCell();
// user chooses another mimetype
const index = this.viewCell.outputsViewModels.indexOf(viewModel);
const nextElement = this.domNode.nextElementSibling;
this.localDisposableStore.clear();
const element = this.domNode;
if (element) {
element.parentElement?.removeChild(element);
this.notebookEditor.removeInset(viewModel);
}

viewModel.pickedMimeType = pick.index;
this.viewCell.updateOutputMinHeight(this.viewCell.layoutInfo.outputTotalHeight);

const { mimeType, rendererId } = mimeTypes[pick.index];
this.notebookService.updateMimePreferredRenderer(mimeType, rendererId);
this.render(index, nextElement as HTMLElement);
this._validateFinalOutputHeight(false);
this.relayoutCell();
}

private generateRendererInfo(renderId: string | undefined): string {
Expand Down
5 changes: 3 additions & 2 deletions src/vs/workbench/contrib/notebook/common/notebookService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no
import { CancellationToken } from 'vs/base/common/cancellation';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { IDisposable } from 'vs/base/common/lifecycle';
import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
import { IRelativePattern } from 'vs/base/common/glob';
import { VSBuffer } from 'vs/base/common/buffer';

Expand Down Expand Up @@ -78,10 +77,12 @@ export interface INotebookService {
registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable;
getNotebookKernels(viewType: string, resource: URI, token: CancellationToken): Promise<INotebookKernel[]>;
getContributedNotebookKernelProviders(): Promise<INotebookKernelProvider[]>;
getContributedNotebookOutputRenderers(id: string): NotebookOutputRendererInfo | undefined;
getRendererInfo(id: string): INotebookRendererInfo | undefined;
getMarkdownRendererInfo(): INotebookMarkdownRendererInfo[];

/** Updates the preferred renderer for the given mimetype in the workspace. */
updateMimePreferredRenderer(mimeType: string, rendererId: string): void;

createNotebookTextModel(viewType: string, uri: URI, data: NotebookDataDto, transientOptions: TransientOptions): NotebookTextModel;
getNotebookTextModel(uri: URI): NotebookTextModel | undefined;
getNotebookTextModels(): Iterable<NotebookTextModel>;
Expand Down

0 comments on commit 0905543

Please sign in to comment.