Path: blob/main/extensions/media-preview/src/videoPreview.ts
4772 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as vscode from 'vscode';6import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry';7import { MediaPreview, reopenAsText } from './mediaPreview';8import { escapeAttribute } from './util/dom';9import { generateUuid } from './util/uuid';101112class VideoPreviewProvider implements vscode.CustomReadonlyEditorProvider {1314public static readonly viewType = 'vscode.videoPreview';1516constructor(17private readonly extensionRoot: vscode.Uri,18private readonly binarySizeStatusBarEntry: BinarySizeStatusBarEntry,19) { }2021public async openCustomDocument(uri: vscode.Uri) {22return { uri, dispose: () => { } };23}2425public async resolveCustomEditor(document: vscode.CustomDocument, webviewEditor: vscode.WebviewPanel): Promise<void> {26new VideoPreview(this.extensionRoot, document.uri, webviewEditor, this.binarySizeStatusBarEntry);27}28}293031class VideoPreview extends MediaPreview {3233constructor(34private readonly extensionRoot: vscode.Uri,35resource: vscode.Uri,36webviewEditor: vscode.WebviewPanel,37binarySizeStatusBarEntry: BinarySizeStatusBarEntry,38) {39super(extensionRoot, resource, webviewEditor, binarySizeStatusBarEntry);4041this._register(webviewEditor.webview.onDidReceiveMessage(message => {42switch (message.type) {43case 'reopen-as-text': {44reopenAsText(resource, webviewEditor.viewColumn);45break;46}47}48}));4950this.updateBinarySize();51this.render();52this.updateState();53}5455protected async getWebviewContents(): Promise<string> {56const version = Date.now().toString();57const configurations = vscode.workspace.getConfiguration('mediaPreview.video');58const settings = {59src: await this.getResourcePath(this._webviewEditor, this._resource, version),60autoplay: configurations.get('autoPlay'),61loop: configurations.get('loop'),62};6364const nonce = generateUuid();6566const cspSource = this._webviewEditor.webview.cspSource;67return /* html */`<!DOCTYPE html>68<html lang="en">69<head>70<meta charset="UTF-8">7172<!-- Disable pinch zooming -->73<meta name="viewport"74content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">7576<title>Video Preview</title>7778<link rel="stylesheet" href="${escapeAttribute(this.extensionResource('media', 'videoPreview.css'))}" type="text/css" media="screen" nonce="${nonce}">7980<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}';">81<meta id="settings" data-settings="${escapeAttribute(JSON.stringify(settings))}">82</head>83<body class="loading" data-vscode-context='{ "preventDefaultContextMenuItems": true }'>84<div class="loading-indicator"></div>85<div class="loading-error">86<p>${vscode.l10n.t("An error occurred while loading the video file.")}</p>87<a href="#" class="open-file-link">${vscode.l10n.t("Open file using VS Code's standard text/binary editor?")}</a>88</div>89<script src="${escapeAttribute(this.extensionResource('media', 'videoPreview.js'))}" nonce="${nonce}"></script>90</body>91</html>`;92}9394private async getResourcePath(webviewEditor: vscode.WebviewPanel, resource: vscode.Uri, version: string): Promise<string | null> {95if (resource.scheme === 'git') {96const stat = await vscode.workspace.fs.stat(resource);97if (stat.size === 0) {98// The file is stored on git lfs99return null;100}101}102103// Avoid adding cache busting if there is already a query string104if (resource.query) {105return webviewEditor.webview.asWebviewUri(resource).toString();106}107return webviewEditor.webview.asWebviewUri(resource).with({ query: `version=${version}` }).toString();108}109110private extensionResource(...parts: string[]) {111return this._webviewEditor.webview.asWebviewUri(vscode.Uri.joinPath(this.extensionRoot, ...parts));112}113}114115export function registerVideoPreviewSupport(context: vscode.ExtensionContext, binarySizeStatusBarEntry: BinarySizeStatusBarEntry): vscode.Disposable {116const provider = new VideoPreviewProvider(context.extensionUri, binarySizeStatusBarEntry);117return vscode.window.registerCustomEditorProvider(VideoPreviewProvider.viewType, provider, {118supportsMultipleEditorsPerDocument: true,119webviewOptions: {120retainContextWhenHidden: true,121}122});123}124125126