feat(ImagePreview): fix positioning & add preview (WxH) (#60)

* yes

* forgot zoom factor

* lint -_- fr

* remove comments and fix loading spinner and check for mouseOnlyMode
This commit is contained in:
Creation's 2024-10-17 11:06:43 -04:00 committed by GitHub
parent 39909d95c4
commit 7220b98b3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 96 additions and 26 deletions

View file

@ -24,17 +24,22 @@ let isDragging: boolean = false;
let shouldKeepPreviewOpenTimeout: NodeJS.Timeout | null = null;
let shouldKeepPreviewOpen: boolean = false;
let hoverDelayTimeout: NodeJS.Timeout | null = null;
let lastMouseEvent: MouseEvent | null = null;
let observer: MutationObserver | null = null;
function deleteCurrentPreview() {
if (!currentPreview || !currentPreviewFile || !currentPreviewFileSize || !currentPreviewType) return;
if (!currentPreview || !currentPreviewFile || !currentPreviewFileSize || !currentPreviewType || !loadingSpinner) return;
currentPreview.remove();
loadingSpinner = null;
lastMouseEvent = null;
currentPreview = null;
currentPreviewFile = null;
currentPreviewFileSize = null;
currentPreviewType = null;
lastMouseEvent = null;
loadingSpinner = null;
zoomLevel = 1;
}
@ -126,9 +131,19 @@ function loadImagePreview(url: string) {
const fileName = document.createElement("span");
const fileSize = document.createElement("span");
fileSize.className = "file-size";
const fileSizeSpan = document.createElement("p");
const showingSize = document.createElement("p");
const mimeTypeSpan = document.createElement("span");
const updatePositionAfterLoad = () => {
if (lastMouseEvent && currentPreview) {
updatePreviewPosition(lastMouseEvent, currentPreview);
}
};
fileName.textContent = url.split("/").pop()?.split("?")[0] || "";
mimeTypeSpan.textContent = mimeType;
if (currentPreviewType === "video") {
@ -146,11 +161,25 @@ function loadImagePreview(url: string) {
video.onloadeddata = () => {
currentPreviewFileSize = [video.videoWidth, video.videoHeight];
fileSize.textContent = `${currentPreviewFileSize[0]}x${currentPreviewFileSize[1]}`;
fileSizeSpan.textContent = `${currentPreviewFileSize[0]}x${currentPreviewFileSize[1]}`;
fileSize.appendChild(fileSizeSpan);
requestAnimationFrame(() => {
if (!currentPreviewFileSize) return;
const showingMediaSize = [video.clientWidth, video.clientHeight];
if (showingMediaSize[0] !== currentPreviewFileSize[0] && showingMediaSize[1] !== currentPreviewFileSize[1]) {
showingSize.textContent = showingMediaSize ? `(${showingMediaSize[0]}x${showingMediaSize[1]})` : "";
fileSize.appendChild(showingSize);
}
});
if (loadingSpinner) loadingSpinner.remove();
video.style.display = "block";
updatePositionAfterLoad();
};
preview.appendChild(video);
currentPreviewFile = video;
} else {
@ -159,10 +188,25 @@ function loadImagePreview(url: string) {
img.className = "preview-media";
img.onload = () => {
currentPreviewFileSize = [img.naturalWidth, img.naturalHeight];
fileSize.textContent = `${currentPreviewFileSize[0]}x${currentPreviewFileSize[1]}`;
fileSizeSpan.textContent = `${currentPreviewFileSize[0]}x${currentPreviewFileSize[1]}`;
fileSize.appendChild(fileSizeSpan);
requestAnimationFrame(() => {
if (!currentPreviewFileSize) return;
const showingMediaSize = [img.clientWidth, img.clientHeight];
if (showingMediaSize[0] !== currentPreviewFileSize[0] && showingMediaSize[1] !== currentPreviewFileSize[1]) {
showingSize.textContent = showingMediaSize ? `(${showingMediaSize[0]}x${showingMediaSize[1]})` : "";
fileSize.appendChild(showingSize);
}
});
if (loadingSpinner) loadingSpinner.remove();
img.style.display = "block";
updatePositionAfterLoad();
};
preview.appendChild(img);
currentPreviewFile = img;
}
@ -172,26 +216,29 @@ function loadImagePreview(url: string) {
fileInfo.appendChild(fileSize);
preview.appendChild(fileInfo);
currentPreviewFile.addEventListener("mouseover", () => {
if (currentPreview && !isCtrlHeld) {
shouldKeepPreviewOpen = true;
currentPreview.classList.add("allow-zoom-and-drag");
}
});
if (settings.store.mouseOnlyMode) {
currentPreviewFile.addEventListener("mouseover", () => {
if (currentPreview && !isCtrlHeld) {
shouldKeepPreviewOpen = true;
currentPreview.classList.add("allow-zoom-and-drag");
}
});
currentPreviewFile.addEventListener("mouseout", () => {
if (currentPreview && !isCtrlHeld && shouldKeepPreviewOpen) {
deleteCurrentPreview();
shouldKeepPreviewOpen = false;
}
});
currentPreviewFile.addEventListener("mouseout", () => {
if (currentPreview && !isCtrlHeld && shouldKeepPreviewOpen) {
deleteCurrentPreview();
shouldKeepPreviewOpen = false;
}
});
}
currentPreview.addEventListener("wheel", (event: WheelEvent) => {
const zoomSpeed = 0.0005;
const [{ zoomFactor }, zoomSpeed] = [settings.store, 0.0005];
if (isCtrlHeld || event.target === currentPreview || event.target === currentPreviewFile) {
event.preventDefault();
zoomLevel += event.deltaY * -zoomSpeed;
zoomLevel += event.deltaY * -zoomSpeed * zoomFactor;
zoomLevel = Math.min(Math.max(zoomLevel, 0.5), 10);
@ -210,6 +257,7 @@ function loadImagePreview(url: string) {
}
});
currentPreview.addEventListener("mousedown", (event: MouseEvent) => {
if ((isCtrlHeld || shouldKeepPreviewOpen) && currentPreview) {
isDragging = true;
@ -244,9 +292,12 @@ function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
if (top + previewHeight > window.innerHeight) {
top = mouseEvent.pageY - previewHeight - padding;
if (top < padding) {
top = window.innerHeight - previewHeight - padding;
top = window.innerHeight - previewHeight - padding * 2;
}
} else {
top = Math.min(top, window.innerHeight - previewHeight - padding * 2);
}
currentPreview.style.left = `${left}px`;
@ -263,10 +314,8 @@ function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
function addHoverListener(element: Element) {
element.setAttribute("data-processed", "true");
let lastMouseEvent: MouseEvent | null = null;
element.addEventListener("mouseover", event => {
if (currentPreview) {
if (currentPreview || loadingSpinner) {
if (isCtrlHeld) return;
deleteCurrentPreview();
@ -334,11 +383,9 @@ function addHoverListener(element: Element) {
}
function handleKeydown(event: KeyboardEvent) {
if (event.key === "Control") {
if (event.key === "Control" && currentPreview) {
isCtrlHeld = true;
if (currentPreview) {
currentPreview.classList.add("allow-zoom-and-drag");
}
currentPreview.classList.add("allow-zoom-and-drag");
}
}
@ -373,6 +420,7 @@ function removeHoverListeners() {
processedElements.forEach(element => {
const clone = element.cloneNode(true);
element.replaceWith(clone);
element.removeAttribute("data-processed");
});
}

View file

@ -43,6 +43,12 @@ const settings = definePluginSettings({
default: 0.5,
markers: [0, 1, 2, 3, 4, 5],
},
zoomFactor: {
type: OptionType.SLIDER,
description: "Speed at which the image zooms in",
default: 1.5,
markers: [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5],
},
});
const mimeTypes = {

View file

@ -1,7 +1,7 @@
.image-preview {
position: fixed;
z-index: 1000;
pointer-events: auto;
pointer-events: none;
border: 2px solid var(--background-secondary);
background-color: var(--background-primary);
border-radius: 4px;
@ -16,6 +16,7 @@
.image-preview.allow-zoom-and-drag {
background-color: transparent;
border: none;
pointer-events: auto;
}
.image-preview .file-info {
@ -40,6 +41,21 @@
border: 1px solid var(--background-secondary);
}
.file-size {
display: flex;
flex-direction: row;
gap: 5px;
}
.image-preview .file-info span p {
padding: 0;
margin: 0;
}
.image-preview .file-info span p:last-child:not(:first-child) {
color: var(--text-muted);
}
.image-preview.allow-zoom-and-drag .file-info {
display: none;
}