test
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
mol
2024-07-06 22:23:31 +08:00
parent 08173d8497
commit 263cb5ef03
1663 changed files with 526884 additions and 0 deletions

View File

@ -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');
}

View File

@ -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',
});
});
}());

View File

@ -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');
}

View File

@ -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);
}
}
}());

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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');
}

View File

@ -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',
});
});
}());