Select Git revision
webviewBase.ts
webviewBase.ts 3.42 KiB
'use strict';
import {
commands,
Disposable,
Uri,
ViewColumn,
Webview,
WebviewPanel,
WebviewPanelOnDidChangeViewStateEvent,
window,
} from 'vscode';
import { Command } from '../theia/command';
const emptyCommands: Disposable[] = [
{
dispose: function () {
/* noop */
},
},
];
export function getUri(webview: Webview, extensionUri: Uri, pathList: string[]) {
return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList));
}
export abstract class WebviewBase implements Disposable {
protected disposable: Disposable;
private _disposablePanel: Disposable | undefined;
protected _panel: WebviewPanel | undefined;
constructor(private id: string, private title: string, command: Command, private readonly _column?: ViewColumn) {
this.disposable = Disposable.from(commands.registerCommand(command.cmd, this.onShowCommand, this));
this.load();
}
getExternalRessourcePath(extensionUri: Uri, pathList: string[]) {
return getUri(this._panel!.webview, extensionUri, pathList);
}
registerCommands(): Disposable[] {
return emptyCommands;
}
renderHead?(): string | Promise<string>;
renderBody?(): string | Promise<string>;
renderEndOfBody?(): string | Promise<string>;
dispose() {
this.disposable.dispose();
this._disposablePanel?.dispose();
}
protected onShowCommand() {
void this.show(this._column);
}
private onPanelDisposed() {
this._disposablePanel?.dispose();
this._panel = undefined;
}
private onViewStateChanged(e: WebviewPanelOnDidChangeViewStateEvent) {
console.log(
`Webview(${this.id}).onViewStateChanged`,
`active=${e.webviewPanel.active}, visible=${e.webviewPanel.visible}`,
);
}
get visible() {
return this._panel?.visible ?? false;
}
hide() {
this._panel?.dispose();
}
setTitle(title: string) {
if (this._panel == null) return;
this._panel.title = title;
}
onMessageReceive(message) {
switch (message.command) {
case 'alert':
window.showErrorMessage(message.text);
return;
}
}
async show(column: ViewColumn = ViewColumn.Beside): Promise<void> {
if (this._panel == null) {
this._panel = window.createWebviewPanel(
this.id,
this.title,
{ viewColumn: column, preserveFocus: false },
{
retainContextWhenHidden: true,
enableFindWidget: true,
enableCommandUris: true,
enableScripts: true,
},
);
this._disposablePanel = Disposable.from(
this._panel,
this._panel.onDidDispose(this.onPanelDisposed, this),
this._panel.onDidChangeViewState(this.onViewStateChanged, this),
this._panel.webview.onDidReceiveMessage(this.onMessageReceive, this),
...this.registerCommands(),
);
this._panel.webview.html = await this.getHtml(this._panel.webview);
} else {
const html = await this.getHtml(this._panel.webview);
// Reset the html to get the webview to reload
this._panel.webview.html = '';
this._panel.webview.html = html;
this._panel.reveal(this._panel.viewColumn ?? ViewColumn.Active, false);
}
}
async reload() {
if (this._panel) {
const html = await this.getHtml(this._panel.webview);
// Reset the html to get the webview to reload
this._panel.webview.html = '';
this._panel.webview.html = html;
}
}
/**
* Must return the content displayed within the webViewPanel
*/
abstract render(): string;
/**
* Method called at the end of first render
*/
abstract load(): void;
private async getHtml(webview: Webview): Promise<string> {
return this.render();
}
}