mirror of
https://github.com/Equicord/Equicord.git
synced 2025-02-25 09:38:52 -05:00
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:
parent
39909d95c4
commit
7220b98b3e
3 changed files with 96 additions and 26 deletions
|
@ -24,17 +24,22 @@ let isDragging: boolean = false;
|
||||||
let shouldKeepPreviewOpenTimeout: NodeJS.Timeout | null = null;
|
let shouldKeepPreviewOpenTimeout: NodeJS.Timeout | null = null;
|
||||||
let shouldKeepPreviewOpen: boolean = false;
|
let shouldKeepPreviewOpen: boolean = false;
|
||||||
let hoverDelayTimeout: NodeJS.Timeout | null = null;
|
let hoverDelayTimeout: NodeJS.Timeout | null = null;
|
||||||
|
let lastMouseEvent: MouseEvent | null = null;
|
||||||
|
|
||||||
let observer: MutationObserver | null = null;
|
let observer: MutationObserver | null = null;
|
||||||
|
|
||||||
function deleteCurrentPreview() {
|
function deleteCurrentPreview() {
|
||||||
if (!currentPreview || !currentPreviewFile || !currentPreviewFileSize || !currentPreviewType) return;
|
if (!currentPreview || !currentPreviewFile || !currentPreviewFileSize || !currentPreviewType || !loadingSpinner) return;
|
||||||
|
|
||||||
currentPreview.remove();
|
currentPreview.remove();
|
||||||
|
loadingSpinner = null;
|
||||||
|
lastMouseEvent = null;
|
||||||
currentPreview = null;
|
currentPreview = null;
|
||||||
currentPreviewFile = null;
|
currentPreviewFile = null;
|
||||||
currentPreviewFileSize = null;
|
currentPreviewFileSize = null;
|
||||||
currentPreviewType = null;
|
currentPreviewType = null;
|
||||||
|
lastMouseEvent = null;
|
||||||
|
loadingSpinner = null;
|
||||||
zoomLevel = 1;
|
zoomLevel = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,9 +131,19 @@ function loadImagePreview(url: string) {
|
||||||
|
|
||||||
const fileName = document.createElement("span");
|
const fileName = document.createElement("span");
|
||||||
const fileSize = 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 mimeTypeSpan = document.createElement("span");
|
||||||
|
|
||||||
|
const updatePositionAfterLoad = () => {
|
||||||
|
if (lastMouseEvent && currentPreview) {
|
||||||
|
updatePreviewPosition(lastMouseEvent, currentPreview);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fileName.textContent = url.split("/").pop()?.split("?")[0] || "";
|
fileName.textContent = url.split("/").pop()?.split("?")[0] || "";
|
||||||
|
|
||||||
mimeTypeSpan.textContent = mimeType;
|
mimeTypeSpan.textContent = mimeType;
|
||||||
|
|
||||||
if (currentPreviewType === "video") {
|
if (currentPreviewType === "video") {
|
||||||
|
@ -146,11 +161,25 @@ function loadImagePreview(url: string) {
|
||||||
|
|
||||||
video.onloadeddata = () => {
|
video.onloadeddata = () => {
|
||||||
currentPreviewFileSize = [video.videoWidth, video.videoHeight];
|
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();
|
if (loadingSpinner) loadingSpinner.remove();
|
||||||
video.style.display = "block";
|
video.style.display = "block";
|
||||||
|
|
||||||
|
updatePositionAfterLoad();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
preview.appendChild(video);
|
preview.appendChild(video);
|
||||||
currentPreviewFile = video;
|
currentPreviewFile = video;
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,10 +188,25 @@ function loadImagePreview(url: string) {
|
||||||
img.className = "preview-media";
|
img.className = "preview-media";
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
currentPreviewFileSize = [img.naturalWidth, img.naturalHeight];
|
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();
|
if (loadingSpinner) loadingSpinner.remove();
|
||||||
img.style.display = "block";
|
img.style.display = "block";
|
||||||
|
|
||||||
|
updatePositionAfterLoad();
|
||||||
};
|
};
|
||||||
|
|
||||||
preview.appendChild(img);
|
preview.appendChild(img);
|
||||||
currentPreviewFile = img;
|
currentPreviewFile = img;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +216,7 @@ function loadImagePreview(url: string) {
|
||||||
fileInfo.appendChild(fileSize);
|
fileInfo.appendChild(fileSize);
|
||||||
preview.appendChild(fileInfo);
|
preview.appendChild(fileInfo);
|
||||||
|
|
||||||
|
if (settings.store.mouseOnlyMode) {
|
||||||
currentPreviewFile.addEventListener("mouseover", () => {
|
currentPreviewFile.addEventListener("mouseover", () => {
|
||||||
if (currentPreview && !isCtrlHeld) {
|
if (currentPreview && !isCtrlHeld) {
|
||||||
shouldKeepPreviewOpen = true;
|
shouldKeepPreviewOpen = true;
|
||||||
|
@ -185,13 +230,15 @@ function loadImagePreview(url: string) {
|
||||||
shouldKeepPreviewOpen = false;
|
shouldKeepPreviewOpen = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
currentPreview.addEventListener("wheel", (event: WheelEvent) => {
|
currentPreview.addEventListener("wheel", (event: WheelEvent) => {
|
||||||
const zoomSpeed = 0.0005;
|
const [{ zoomFactor }, zoomSpeed] = [settings.store, 0.0005];
|
||||||
|
|
||||||
if (isCtrlHeld || event.target === currentPreview || event.target === currentPreviewFile) {
|
if (isCtrlHeld || event.target === currentPreview || event.target === currentPreviewFile) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
zoomLevel += event.deltaY * -zoomSpeed;
|
|
||||||
|
zoomLevel += event.deltaY * -zoomSpeed * zoomFactor;
|
||||||
|
|
||||||
zoomLevel = Math.min(Math.max(zoomLevel, 0.5), 10);
|
zoomLevel = Math.min(Math.max(zoomLevel, 0.5), 10);
|
||||||
|
|
||||||
|
@ -210,6 +257,7 @@ function loadImagePreview(url: string) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
currentPreview.addEventListener("mousedown", (event: MouseEvent) => {
|
currentPreview.addEventListener("mousedown", (event: MouseEvent) => {
|
||||||
if ((isCtrlHeld || shouldKeepPreviewOpen) && currentPreview) {
|
if ((isCtrlHeld || shouldKeepPreviewOpen) && currentPreview) {
|
||||||
isDragging = true;
|
isDragging = true;
|
||||||
|
@ -244,9 +292,12 @@ function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
|
||||||
|
|
||||||
if (top + previewHeight > window.innerHeight) {
|
if (top + previewHeight > window.innerHeight) {
|
||||||
top = mouseEvent.pageY - previewHeight - padding;
|
top = mouseEvent.pageY - previewHeight - padding;
|
||||||
|
|
||||||
if (top < 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`;
|
currentPreview.style.left = `${left}px`;
|
||||||
|
@ -263,10 +314,8 @@ function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
|
||||||
function addHoverListener(element: Element) {
|
function addHoverListener(element: Element) {
|
||||||
element.setAttribute("data-processed", "true");
|
element.setAttribute("data-processed", "true");
|
||||||
|
|
||||||
let lastMouseEvent: MouseEvent | null = null;
|
|
||||||
|
|
||||||
element.addEventListener("mouseover", event => {
|
element.addEventListener("mouseover", event => {
|
||||||
if (currentPreview) {
|
if (currentPreview || loadingSpinner) {
|
||||||
if (isCtrlHeld) return;
|
if (isCtrlHeld) return;
|
||||||
|
|
||||||
deleteCurrentPreview();
|
deleteCurrentPreview();
|
||||||
|
@ -334,12 +383,10 @@ function addHoverListener(element: Element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeydown(event: KeyboardEvent) {
|
function handleKeydown(event: KeyboardEvent) {
|
||||||
if (event.key === "Control") {
|
if (event.key === "Control" && currentPreview) {
|
||||||
isCtrlHeld = true;
|
isCtrlHeld = true;
|
||||||
if (currentPreview) {
|
|
||||||
currentPreview.classList.add("allow-zoom-and-drag");
|
currentPreview.classList.add("allow-zoom-and-drag");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeyup(event: KeyboardEvent) {
|
function handleKeyup(event: KeyboardEvent) {
|
||||||
|
@ -373,6 +420,7 @@ function removeHoverListeners() {
|
||||||
processedElements.forEach(element => {
|
processedElements.forEach(element => {
|
||||||
const clone = element.cloneNode(true);
|
const clone = element.cloneNode(true);
|
||||||
element.replaceWith(clone);
|
element.replaceWith(clone);
|
||||||
|
element.removeAttribute("data-processed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,12 @@ const settings = definePluginSettings({
|
||||||
default: 0.5,
|
default: 0.5,
|
||||||
markers: [0, 1, 2, 3, 4, 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 = {
|
const mimeTypes = {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.image-preview {
|
.image-preview {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
pointer-events: auto;
|
pointer-events: none;
|
||||||
border: 2px solid var(--background-secondary);
|
border: 2px solid var(--background-secondary);
|
||||||
background-color: var(--background-primary);
|
background-color: var(--background-primary);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
.image-preview.allow-zoom-and-drag {
|
.image-preview.allow-zoom-and-drag {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-preview .file-info {
|
.image-preview .file-info {
|
||||||
|
@ -40,6 +41,21 @@
|
||||||
border: 1px solid var(--background-secondary);
|
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 {
|
.image-preview.allow-zoom-and-drag .file-info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue