This commit is contained in:
@ -0,0 +1,28 @@
|
||||
# Media Preview
|
||||
|
||||
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
|
||||
|
||||
## Features
|
||||
|
||||
This extension provides basic preview for images, audio and video files.
|
||||
|
||||
### Supported image file extensions
|
||||
|
||||
- `.jpg`, `.jpe`, `.jpeg`
|
||||
- `.png`
|
||||
- `.bmp`
|
||||
- `.gif`
|
||||
- `.ico`
|
||||
- `.webp`
|
||||
- `.avif`
|
||||
|
||||
### Supported audio formats
|
||||
|
||||
- `.mp3`
|
||||
- `.wav`
|
||||
- `.ogg`, `.oga`
|
||||
|
||||
### Supported video formats
|
||||
|
||||
- `.mp4` (does not support `aac` audio tracks)
|
||||
- `.webm` (vp8 only)
|
2
vscode-server-linux-x64-web/extensions/media-preview/dist/extension.js
vendored
Normal file
2
vscode-server-linux-x64-web/extensions/media-preview/dist/extension.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
vscode-server-linux-x64-web/extensions/media-preview/icon.png
Normal file
BIN
vscode-server-linux-x64-web/extensions/media-preview/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,60 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 5px 10px;
|
||||
box-sizing: border-box;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.audio-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.container.loading,
|
||||
.container.error {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-indicator {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-image: url('./loading.svg');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.loading-indicator,
|
||||
.loading-error {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loading .loading-indicator,
|
||||
.error .loading-error {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.loading-error {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.vscode-dark .loading-indicator {
|
||||
background-image: url('./loading-dark.svg');
|
||||
}
|
||||
|
||||
.vscode-high-contrast .loading-indicator {
|
||||
background-image: url('./loading-hc.svg');
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
// @ts-check
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
// @ts-ignore
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
function getSettings() {
|
||||
const element = document.getElementById('settings');
|
||||
if (element) {
|
||||
const data = element.getAttribute('data-settings');
|
||||
if (data) {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Could not load settings`);
|
||||
}
|
||||
|
||||
const settings = getSettings();
|
||||
|
||||
// State
|
||||
let hasLoadedMedia = false;
|
||||
|
||||
// Elements
|
||||
const container = document.createElement('div');
|
||||
container.className = 'audio-container';
|
||||
document.body.appendChild(container);
|
||||
|
||||
const audio = new Audio(settings.src === null ? undefined : settings.src);
|
||||
audio.controls = true;
|
||||
|
||||
function onLoaded() {
|
||||
if (hasLoadedMedia) {
|
||||
return;
|
||||
}
|
||||
hasLoadedMedia = true;
|
||||
|
||||
document.body.classList.remove('loading');
|
||||
document.body.classList.add('ready');
|
||||
container.append(audio);
|
||||
}
|
||||
|
||||
audio.addEventListener('error', e => {
|
||||
if (hasLoadedMedia) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasLoadedMedia = true;
|
||||
document.body.classList.add('error');
|
||||
document.body.classList.remove('loading');
|
||||
});
|
||||
|
||||
if (settings.src === null) {
|
||||
onLoaded();
|
||||
} else {
|
||||
audio.addEventListener('canplaythrough', () => {
|
||||
onLoaded();
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector('.open-file-link')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
vscode.postMessage({
|
||||
type: 'reopen-as-text',
|
||||
});
|
||||
});
|
||||
}());
|
@ -0,0 +1,116 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body img {
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.container:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 5px 0 0 10px;
|
||||
box-sizing: border-box;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.container.image {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container.image img {
|
||||
padding: 0;
|
||||
background-position: 0 0, 8px 8px;
|
||||
background-size: 16px 16px;
|
||||
border: 1px solid var(--vscode-imagePreview-border);
|
||||
}
|
||||
|
||||
.container.image img {
|
||||
background-image:
|
||||
linear-gradient(45deg, rgb(230, 230, 230) 25%, transparent 25%, transparent 75%, rgb(230, 230, 230) 75%, rgb(230, 230, 230)),
|
||||
linear-gradient(45deg, rgb(230, 230, 230) 25%, transparent 25%, transparent 75%, rgb(230, 230, 230) 75%, rgb(230, 230, 230));
|
||||
}
|
||||
|
||||
.vscode-dark.container.image img {
|
||||
background-image:
|
||||
linear-gradient(45deg, rgb(20, 20, 20) 25%, transparent 25%, transparent 75%, rgb(20, 20, 20) 75%, rgb(20, 20, 20)),
|
||||
linear-gradient(45deg, rgb(20, 20, 20) 25%, transparent 25%, transparent 75%, rgb(20, 20, 20) 75%, rgb(20, 20, 20));
|
||||
}
|
||||
|
||||
.container img.pixelated {
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.container img.scale-to-fit {
|
||||
max-width: calc(100% - 20px);
|
||||
max-height: calc(100% - 20px);
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.container img {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container.ready.zoom-in {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
.container.ready.zoom-out {
|
||||
cursor: zoom-out;
|
||||
}
|
||||
|
||||
.container .embedded-link,
|
||||
.container .embedded-link:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.container.loading,
|
||||
.container.error {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-indicator {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-image: url('./loading.svg');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.loading-indicator,
|
||||
.image-load-error {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loading .loading-indicator,
|
||||
.error .image-load-error {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.image-load-error {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.vscode-dark .loading-indicator {
|
||||
background-image: url('./loading-dark.svg');
|
||||
}
|
||||
|
||||
.vscode-high-contrast .loading-indicator {
|
||||
background-image: url('./loading-hc.svg');
|
||||
}
|
@ -0,0 +1,383 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
// @ts-check
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* @param {number} value
|
||||
* @param {number} min
|
||||
* @param {number} max
|
||||
* @return {number}
|
||||
*/
|
||||
function clamp(value, min, max) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
const element = document.getElementById('image-preview-settings');
|
||||
if (element) {
|
||||
const data = element.getAttribute('data-settings');
|
||||
if (data) {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Could not load settings`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable image-rendering: pixelated for images scaled by more than this.
|
||||
*/
|
||||
const PIXELATION_THRESHOLD = 3;
|
||||
|
||||
const SCALE_PINCH_FACTOR = 0.075;
|
||||
const MAX_SCALE = 20;
|
||||
const MIN_SCALE = 0.1;
|
||||
|
||||
const zoomLevels = [
|
||||
0.1,
|
||||
0.2,
|
||||
0.3,
|
||||
0.4,
|
||||
0.5,
|
||||
0.6,
|
||||
0.7,
|
||||
0.8,
|
||||
0.9,
|
||||
1,
|
||||
1.5,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
10,
|
||||
15,
|
||||
20
|
||||
];
|
||||
|
||||
const settings = getSettings();
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
|
||||
// @ts-ignore
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
const initialState = vscode.getState() || { scale: 'fit', offsetX: 0, offsetY: 0 };
|
||||
|
||||
// State
|
||||
let scale = initialState.scale;
|
||||
let ctrlPressed = false;
|
||||
let altPressed = false;
|
||||
let hasLoadedImage = false;
|
||||
let consumeClick = true;
|
||||
let isActive = false;
|
||||
|
||||
// Elements
|
||||
const container = document.body;
|
||||
const image = document.createElement('img');
|
||||
|
||||
function updateScale(newScale) {
|
||||
if (!image || !hasLoadedImage || !image.parentElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newScale === 'fit') {
|
||||
scale = 'fit';
|
||||
image.classList.add('scale-to-fit');
|
||||
image.classList.remove('pixelated');
|
||||
// @ts-ignore Non-standard CSS property
|
||||
image.style.zoom = 'normal';
|
||||
vscode.setState(undefined);
|
||||
} else {
|
||||
scale = clamp(newScale, MIN_SCALE, MAX_SCALE);
|
||||
if (scale >= PIXELATION_THRESHOLD) {
|
||||
image.classList.add('pixelated');
|
||||
} else {
|
||||
image.classList.remove('pixelated');
|
||||
}
|
||||
|
||||
const dx = (window.scrollX + container.clientWidth / 2) / container.scrollWidth;
|
||||
const dy = (window.scrollY + container.clientHeight / 2) / container.scrollHeight;
|
||||
|
||||
image.classList.remove('scale-to-fit');
|
||||
// @ts-ignore Non-standard CSS property
|
||||
image.style.zoom = scale;
|
||||
|
||||
const newScrollX = container.scrollWidth * dx - container.clientWidth / 2;
|
||||
const newScrollY = container.scrollHeight * dy - container.clientHeight / 2;
|
||||
|
||||
window.scrollTo(newScrollX, newScrollY);
|
||||
|
||||
vscode.setState({ scale: scale, offsetX: newScrollX, offsetY: newScrollY });
|
||||
}
|
||||
|
||||
vscode.postMessage({
|
||||
type: 'zoom',
|
||||
value: scale
|
||||
});
|
||||
}
|
||||
|
||||
function setActive(value) {
|
||||
isActive = value;
|
||||
if (value) {
|
||||
if (isMac ? altPressed : ctrlPressed) {
|
||||
container.classList.remove('zoom-in');
|
||||
container.classList.add('zoom-out');
|
||||
} else {
|
||||
container.classList.remove('zoom-out');
|
||||
container.classList.add('zoom-in');
|
||||
}
|
||||
} else {
|
||||
ctrlPressed = false;
|
||||
altPressed = false;
|
||||
container.classList.remove('zoom-out');
|
||||
container.classList.remove('zoom-in');
|
||||
}
|
||||
}
|
||||
|
||||
function firstZoom() {
|
||||
if (!image || !hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
scale = image.clientWidth / image.naturalWidth;
|
||||
updateScale(scale);
|
||||
}
|
||||
|
||||
function zoomIn() {
|
||||
if (scale === 'fit') {
|
||||
firstZoom();
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
for (; i < zoomLevels.length; ++i) {
|
||||
if (zoomLevels[i] > scale) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateScale(zoomLevels[i] || MAX_SCALE);
|
||||
}
|
||||
|
||||
function zoomOut() {
|
||||
if (scale === 'fit') {
|
||||
firstZoom();
|
||||
}
|
||||
|
||||
let i = zoomLevels.length - 1;
|
||||
for (; i >= 0; --i) {
|
||||
if (zoomLevels[i] < scale) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateScale(zoomLevels[i] || MIN_SCALE);
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (/** @type {KeyboardEvent} */ e) => {
|
||||
if (!image || !hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
ctrlPressed = e.ctrlKey;
|
||||
altPressed = e.altKey;
|
||||
|
||||
if (isMac ? altPressed : ctrlPressed) {
|
||||
container.classList.remove('zoom-in');
|
||||
container.classList.add('zoom-out');
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('keyup', (/** @type {KeyboardEvent} */ e) => {
|
||||
if (!image || !hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctrlPressed = e.ctrlKey;
|
||||
altPressed = e.altKey;
|
||||
|
||||
if (!(isMac ? altPressed : ctrlPressed)) {
|
||||
container.classList.remove('zoom-out');
|
||||
container.classList.add('zoom-in');
|
||||
}
|
||||
});
|
||||
|
||||
container.addEventListener('mousedown', (/** @type {MouseEvent} */ e) => {
|
||||
if (!image || !hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctrlPressed = e.ctrlKey;
|
||||
altPressed = e.altKey;
|
||||
|
||||
consumeClick = !isActive;
|
||||
});
|
||||
|
||||
container.addEventListener('click', (/** @type {MouseEvent} */ e) => {
|
||||
if (!image || !hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (consumeClick) {
|
||||
consumeClick = false;
|
||||
return;
|
||||
}
|
||||
// left click
|
||||
if (scale === 'fit') {
|
||||
firstZoom();
|
||||
}
|
||||
|
||||
if (!(isMac ? altPressed : ctrlPressed)) { // zoom in
|
||||
zoomIn();
|
||||
} else {
|
||||
zoomOut();
|
||||
}
|
||||
});
|
||||
|
||||
container.addEventListener('wheel', (/** @type {WheelEvent} */ e) => {
|
||||
// Prevent pinch to zoom
|
||||
if (e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (!image || !hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isScrollWheelKeyPressed = isMac ? altPressed : ctrlPressed;
|
||||
if (!isScrollWheelKeyPressed && !e.ctrlKey) { // pinching is reported as scroll wheel + ctrl
|
||||
return;
|
||||
}
|
||||
|
||||
if (scale === 'fit') {
|
||||
firstZoom();
|
||||
}
|
||||
|
||||
const delta = e.deltaY > 0 ? 1 : -1;
|
||||
updateScale(scale * (1 - delta * SCALE_PINCH_FACTOR));
|
||||
}, { passive: false });
|
||||
|
||||
window.addEventListener('scroll', e => {
|
||||
if (!image || !hasLoadedImage || !image.parentElement || scale === 'fit') {
|
||||
return;
|
||||
}
|
||||
|
||||
const entry = vscode.getState();
|
||||
if (entry) {
|
||||
vscode.setState({ scale: entry.scale, offsetX: window.scrollX, offsetY: window.scrollY });
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
container.classList.add('image');
|
||||
|
||||
image.classList.add('scale-to-fit');
|
||||
|
||||
image.addEventListener('load', () => {
|
||||
if (hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
hasLoadedImage = true;
|
||||
|
||||
vscode.postMessage({
|
||||
type: 'size',
|
||||
value: `${image.naturalWidth}x${image.naturalHeight}`,
|
||||
});
|
||||
|
||||
document.body.classList.remove('loading');
|
||||
document.body.classList.add('ready');
|
||||
document.body.append(image);
|
||||
|
||||
updateScale(scale);
|
||||
|
||||
if (initialState.scale !== 'fit') {
|
||||
window.scrollTo(initialState.offsetX, initialState.offsetY);
|
||||
}
|
||||
});
|
||||
|
||||
image.addEventListener('error', e => {
|
||||
if (hasLoadedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasLoadedImage = true;
|
||||
document.body.classList.add('error');
|
||||
document.body.classList.remove('loading');
|
||||
});
|
||||
|
||||
image.src = settings.src;
|
||||
|
||||
document.querySelector('.open-file-link')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
vscode.postMessage({
|
||||
type: 'reopen-as-text',
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('message', e => {
|
||||
if (e.origin !== window.origin) {
|
||||
console.error('Dropping message from unknown origin in image preview');
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.data.type) {
|
||||
case 'setScale': {
|
||||
updateScale(e.data.scale);
|
||||
break;
|
||||
}
|
||||
case 'setActive': {
|
||||
setActive(e.data.value);
|
||||
break;
|
||||
}
|
||||
case 'zoomIn': {
|
||||
zoomIn();
|
||||
break;
|
||||
}
|
||||
case 'zoomOut': {
|
||||
zoomOut();
|
||||
break;
|
||||
}
|
||||
case 'copyImage': {
|
||||
copyImage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('copy', () => {
|
||||
copyImage();
|
||||
});
|
||||
|
||||
async function copyImage(retries = 5) {
|
||||
if (!document.hasFocus() && retries > 0) {
|
||||
// copyImage is called at the same time as webview.reveal, which means this function is running whilst the webview is gaining focus.
|
||||
// Since navigator.clipboard.write requires the document to be focused, we need to wait for focus.
|
||||
// We cannot use a listener, as there is a high chance the focus is gained during the setup of the listener resulting in us missing it.
|
||||
setTimeout(() => { copyImage(retries - 1); }, 20);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await navigator.clipboard.write([new ClipboardItem({
|
||||
'image/png': new Promise((resolve, reject) => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = image.naturalWidth;
|
||||
canvas.height = image.naturalHeight;
|
||||
canvas.getContext('2d').drawImage(image, 0, 0);
|
||||
canvas.toBlob((blob) => {
|
||||
resolve(blob);
|
||||
canvas.remove();
|
||||
}, 'image/png');
|
||||
})
|
||||
})]);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}());
|
@ -0,0 +1,31 @@
|
||||
<?xml version='1.0' standalone='no' ?>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
|
||||
<style>
|
||||
circle {
|
||||
animation: ball 0.6s linear infinite;
|
||||
}
|
||||
|
||||
circle:nth-child(2) { animation-delay: 0.075s; }
|
||||
circle:nth-child(3) { animation-delay: 0.15s; }
|
||||
circle:nth-child(4) { animation-delay: 0.225s; }
|
||||
circle:nth-child(5) { animation-delay: 0.3s; }
|
||||
circle:nth-child(6) { animation-delay: 0.375s; }
|
||||
circle:nth-child(7) { animation-delay: 0.45s; }
|
||||
circle:nth-child(8) { animation-delay: 0.525s; }
|
||||
|
||||
@keyframes ball {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
</style>
|
||||
<g style="fill:grey;">
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,31 @@
|
||||
<?xml version='1.0' standalone='no' ?>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
|
||||
<style>
|
||||
circle {
|
||||
animation: ball 0.6s linear infinite;
|
||||
}
|
||||
|
||||
circle:nth-child(2) { animation-delay: 0.075s; }
|
||||
circle:nth-child(3) { animation-delay: 0.15s; }
|
||||
circle:nth-child(4) { animation-delay: 0.225s; }
|
||||
circle:nth-child(5) { animation-delay: 0.3s; }
|
||||
circle:nth-child(6) { animation-delay: 0.375s; }
|
||||
circle:nth-child(7) { animation-delay: 0.45s; }
|
||||
circle:nth-child(8) { animation-delay: 0.525s; }
|
||||
|
||||
@keyframes ball {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
</style>
|
||||
<g style="fill:white;">
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,31 @@
|
||||
<?xml version='1.0' standalone='no' ?>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
|
||||
<style>
|
||||
circle {
|
||||
animation: ball 0.6s linear infinite;
|
||||
}
|
||||
|
||||
circle:nth-child(2) { animation-delay: 0.075s; }
|
||||
circle:nth-child(3) { animation-delay: 0.15s; }
|
||||
circle:nth-child(4) { animation-delay: 0.225s; }
|
||||
circle:nth-child(5) { animation-delay: 0.3s; }
|
||||
circle:nth-child(6) { animation-delay: 0.375s; }
|
||||
circle:nth-child(7) { animation-delay: 0.45s; }
|
||||
circle:nth-child(8) { animation-delay: 0.525s; }
|
||||
|
||||
@keyframes ball {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
</style>
|
||||
<g>
|
||||
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
|
||||
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
|
||||
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 5px 10px;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 10px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.loading-indicator {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-image: url('./loading.svg');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.loading-indicator,
|
||||
.loading-error {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loading .loading-indicator,
|
||||
.error .loading-error {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.loading-error {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.vscode-dark .loading-indicator {
|
||||
background-image: url('./loading-dark.svg');
|
||||
}
|
||||
|
||||
.vscode-high-contrast .loading-indicator {
|
||||
background-image: url('./loading-hc.svg');
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
// @ts-check
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
// @ts-ignore
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
function getSettings() {
|
||||
const element = document.getElementById('settings');
|
||||
if (element) {
|
||||
const data = element.getAttribute('data-settings');
|
||||
if (data) {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Could not load settings`);
|
||||
}
|
||||
|
||||
const settings = getSettings();
|
||||
|
||||
// State
|
||||
let hasLoadedMedia = false;
|
||||
|
||||
// Elements
|
||||
const video = document.createElement('video');
|
||||
if (settings.src !== null) {
|
||||
video.src = settings.src;
|
||||
}
|
||||
video.playsInline = true;
|
||||
video.controls = true;
|
||||
video.autoplay = settings.autoplay;
|
||||
video.muted = settings.autoplay;
|
||||
video.loop = settings.loop;
|
||||
|
||||
function onLoaded() {
|
||||
if (hasLoadedMedia) {
|
||||
return;
|
||||
}
|
||||
hasLoadedMedia = true;
|
||||
|
||||
document.body.classList.remove('loading');
|
||||
document.body.classList.add('ready');
|
||||
document.body.append(video);
|
||||
}
|
||||
|
||||
video.addEventListener('error', e => {
|
||||
if (hasLoadedMedia) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasLoadedMedia = true;
|
||||
document.body.classList.add('error');
|
||||
document.body.classList.remove('loading');
|
||||
});
|
||||
|
||||
if (settings.src === null) {
|
||||
onLoaded();
|
||||
} else {
|
||||
video.addEventListener('canplaythrough', () => {
|
||||
onLoaded();
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector('.open-file-link')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
vscode.postMessage({
|
||||
type: 'reopen-as-text',
|
||||
});
|
||||
});
|
||||
}());
|
@ -0,0 +1 @@
|
||||
{"name":"media-preview","displayName":"%displayName%","description":"%description%","extensionKind":["ui","workspace"],"version":"1.0.0","publisher":"vscode","icon":"icon.png","license":"MIT","aiKey":"0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255","engines":{"vscode":"^1.70.0"},"main":"./dist/extension","browser":"./dist/browser/extension.js","categories":["Other"],"activationEvents":[],"capabilities":{"virtualWorkspaces":true,"untrustedWorkspaces":{"supported":true}},"contributes":{"configuration":{"type":"object","title":"Media Previewer","properties":{"mediaPreview.video.autoPlay":{"type":"boolean","default":false,"markdownDescription":"%videoPreviewerAutoPlay%"},"mediaPreview.video.loop":{"type":"boolean","default":false,"markdownDescription":"%videoPreviewerLoop%"}}},"customEditors":[{"viewType":"imagePreview.previewEditor","displayName":"%customEditor.imagePreview.displayName%","priority":"builtin","selector":[{"filenamePattern":"*.{jpg,jpe,jpeg,png,bmp,gif,ico,webp,avif}"}]},{"viewType":"vscode.audioPreview","displayName":"%customEditor.audioPreview.displayName%","priority":"builtin","selector":[{"filenamePattern":"*.{mp3,wav,ogg,oga}"}]},{"viewType":"vscode.videoPreview","displayName":"%customEditor.videoPreview.displayName%","priority":"builtin","selector":[{"filenamePattern":"*.{mp4,webm}"}]}],"commands":[{"command":"imagePreview.zoomIn","title":"%command.zoomIn%","category":"Image Preview"},{"command":"imagePreview.zoomOut","title":"%command.zoomOut%","category":"Image Preview"},{"command":"imagePreview.copyImage","title":"%command.copyImage%","category":"Image Preview"}],"menus":{"commandPalette":[{"command":"imagePreview.zoomIn","when":"activeCustomEditorId == 'imagePreview.previewEditor'","group":"1_imagePreview"},{"command":"imagePreview.zoomOut","when":"activeCustomEditorId == 'imagePreview.previewEditor'","group":"1_imagePreview"},{"command":"imagePreview.copyImage","when":"false"}],"webview/context":[{"command":"imagePreview.copyImage","when":"webviewId == 'imagePreview.previewEditor'"}]}},"repository":{"type":"git","url":"https://github.com/microsoft/vscode.git"}}
|
@ -0,0 +1 @@
|
||||
{"displayName":"Media Preview","description":"Provides VS Code's built-in previews for images, audio, and video","customEditor.audioPreview.displayName":"Audio Preview","customEditor.imagePreview.displayName":"Image Preview","customEditor.videoPreview.displayName":"Video Preview","videoPreviewerAutoPlay":"Start playing videos on mute automatically.","videoPreviewerLoop":"Loop videos over again automatically.","command.zoomIn":"Zoom in","command.zoomOut":"Zoom out","command.copyImage":"Copy"}
|
Reference in New Issue
Block a user