Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/media-preview/src/videoPreview.ts
4772 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as vscode from 'vscode';
7
import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry';
8
import { MediaPreview, reopenAsText } from './mediaPreview';
9
import { escapeAttribute } from './util/dom';
10
import { generateUuid } from './util/uuid';
11
12
13
class VideoPreviewProvider implements vscode.CustomReadonlyEditorProvider {
14
15
public static readonly viewType = 'vscode.videoPreview';
16
17
constructor(
18
private readonly extensionRoot: vscode.Uri,
19
private readonly binarySizeStatusBarEntry: BinarySizeStatusBarEntry,
20
) { }
21
22
public async openCustomDocument(uri: vscode.Uri) {
23
return { uri, dispose: () => { } };
24
}
25
26
public async resolveCustomEditor(document: vscode.CustomDocument, webviewEditor: vscode.WebviewPanel): Promise<void> {
27
new VideoPreview(this.extensionRoot, document.uri, webviewEditor, this.binarySizeStatusBarEntry);
28
}
29
}
30
31
32
class VideoPreview extends MediaPreview {
33
34
constructor(
35
private readonly extensionRoot: vscode.Uri,
36
resource: vscode.Uri,
37
webviewEditor: vscode.WebviewPanel,
38
binarySizeStatusBarEntry: BinarySizeStatusBarEntry,
39
) {
40
super(extensionRoot, resource, webviewEditor, binarySizeStatusBarEntry);
41
42
this._register(webviewEditor.webview.onDidReceiveMessage(message => {
43
switch (message.type) {
44
case 'reopen-as-text': {
45
reopenAsText(resource, webviewEditor.viewColumn);
46
break;
47
}
48
}
49
}));
50
51
this.updateBinarySize();
52
this.render();
53
this.updateState();
54
}
55
56
protected async getWebviewContents(): Promise<string> {
57
const version = Date.now().toString();
58
const configurations = vscode.workspace.getConfiguration('mediaPreview.video');
59
const settings = {
60
src: await this.getResourcePath(this._webviewEditor, this._resource, version),
61
autoplay: configurations.get('autoPlay'),
62
loop: configurations.get('loop'),
63
};
64
65
const nonce = generateUuid();
66
67
const cspSource = this._webviewEditor.webview.cspSource;
68
return /* html */`<!DOCTYPE html>
69
<html lang="en">
70
<head>
71
<meta charset="UTF-8">
72
73
<!-- Disable pinch zooming -->
74
<meta name="viewport"
75
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
76
77
<title>Video Preview</title>
78
79
<link rel="stylesheet" href="${escapeAttribute(this.extensionResource('media', 'videoPreview.css'))}" type="text/css" media="screen" nonce="${nonce}">
80
81
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src data: ${cspSource}; media-src ${cspSource}; script-src 'nonce-${nonce}'; style-src ${cspSource} 'nonce-${nonce}';">
82
<meta id="settings" data-settings="${escapeAttribute(JSON.stringify(settings))}">
83
</head>
84
<body class="loading" data-vscode-context='{ "preventDefaultContextMenuItems": true }'>
85
<div class="loading-indicator"></div>
86
<div class="loading-error">
87
<p>${vscode.l10n.t("An error occurred while loading the video file.")}</p>
88
<a href="#" class="open-file-link">${vscode.l10n.t("Open file using VS Code's standard text/binary editor?")}</a>
89
</div>
90
<script src="${escapeAttribute(this.extensionResource('media', 'videoPreview.js'))}" nonce="${nonce}"></script>
91
</body>
92
</html>`;
93
}
94
95
private async getResourcePath(webviewEditor: vscode.WebviewPanel, resource: vscode.Uri, version: string): Promise<string | null> {
96
if (resource.scheme === 'git') {
97
const stat = await vscode.workspace.fs.stat(resource);
98
if (stat.size === 0) {
99
// The file is stored on git lfs
100
return null;
101
}
102
}
103
104
// Avoid adding cache busting if there is already a query string
105
if (resource.query) {
106
return webviewEditor.webview.asWebviewUri(resource).toString();
107
}
108
return webviewEditor.webview.asWebviewUri(resource).with({ query: `version=${version}` }).toString();
109
}
110
111
private extensionResource(...parts: string[]) {
112
return this._webviewEditor.webview.asWebviewUri(vscode.Uri.joinPath(this.extensionRoot, ...parts));
113
}
114
}
115
116
export function registerVideoPreviewSupport(context: vscode.ExtensionContext, binarySizeStatusBarEntry: BinarySizeStatusBarEntry): vscode.Disposable {
117
const provider = new VideoPreviewProvider(context.extensionUri, binarySizeStatusBarEntry);
118
return vscode.window.registerCustomEditorProvider(VideoPreviewProvider.viewType, provider, {
119
supportsMultipleEditorsPerDocument: true,
120
webviewOptions: {
121
retainContextWhenHidden: true,
122
}
123
});
124
}
125
126