-
Notifications
You must be signed in to change notification settings - Fork 731
Expand file tree
/
Copy pathwebview.ts
More file actions
133 lines (114 loc) · 3.44 KB
/
webview.ts
File metadata and controls
133 lines (114 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { commands } from './executeCommands';
import { Disposable } from './lifecycle';
export const PULL_REQUEST_OVERVIEW_VIEW_TYPE = 'PullRequestOverview';
export interface IRequestMessage<T> {
req: string;
command: string;
args: T;
}
export interface IReplyMessage {
seq?: string;
err?: string;
// eslint-disable-next-line rulesdir/no-any-except-union-method-signature
res?: any;
}
export function getNonce() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
export class WebviewBase extends Disposable {
protected _webview?: vscode.Webview;
private _waitForReady: Promise<void>;
protected _onIsReady: vscode.EventEmitter<void> = this._register(new vscode.EventEmitter());
protected readonly MESSAGE_UNHANDLED: string = 'message not handled';
constructor() {
super();
this._waitForReady = new Promise(resolve => {
const disposable = this._onIsReady.event(() => {
disposable.dispose();
resolve();
});
});
}
public initialize(): void {
const disposable = this._webview?.onDidReceiveMessage(
async message => {
await this._onDidReceiveMessage(message as IRequestMessage<any>);
});
if (disposable) {
this._register(disposable);
}
}
protected async _onDidReceiveMessage(message: IRequestMessage<any>): Promise<any> {
switch (message.command) {
case 'ready':
this._onIsReady.fire();
return;
default:
return this.MESSAGE_UNHANDLED;
}
}
protected async _postMessage(message: any) {
// Without the following ready check, we can end up in a state where the message handler in the webview
// isn't ready for any of the messages we post.
await this._waitForReady;
this._webview?.postMessage({
res: message,
});
}
protected async _replyMessage(originalMessage: IRequestMessage<any>, message: any) {
const reply: IReplyMessage = {
seq: originalMessage.req,
res: message,
};
this._webview?.postMessage(reply);
}
protected async _throwError(originalMessage: IRequestMessage<any> | undefined, error: string) {
const reply: IReplyMessage = {
seq: originalMessage?.req,
err: error,
};
this._webview?.postMessage(reply);
}
}
export class WebviewViewBase extends WebviewBase {
public readonly viewType: string;
protected _view?: vscode.WebviewView;
constructor(
protected readonly _extensionUri: vscode.Uri) {
super();
}
protected resolveWebviewView(
webviewView: vscode.WebviewView,
_context: vscode.WebviewViewResolveContext,
_token: vscode.CancellationToken) {
this._view = webviewView;
this._webview = webviewView.webview;
super.initialize();
webviewView.webview.options = {
// Allow scripts in the webview
enableScripts: true,
localResourceRoots: [this._extensionUri],
};
this._register(this._view.onDidDispose(() => {
this._webview = undefined;
this._view = undefined;
}));
}
public show() {
if (this._view) {
this._view.show();
} else {
commands.focusView(this.viewType);
}
}
}