"use strict"; import { commands, Disposable, ViewColumn, Webview, WebviewPanel, WebviewPanelOnDidChangeViewStateEvent, window, } from "vscode"; import { Command } from "../theia/command"; const emptyCommands: Disposable[] = [ { dispose: function () { /* noop */ }, }, ]; export abstract class WebviewBase implements Disposable { protected disposable: Disposable; private _disposablePanel: Disposable | undefined; private _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(); } 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); } } /** * 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(); } }