imagePreview fixed (#69)

* move name to top, fix positioning, fix when preview hover and non mouse mode making it disappear, fixed not loading sometimes, add jpeg jpg ???

* Add SVG Back

---------

Co-authored-by: thororen <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
Creation's 2024-10-21 03:01:21 -04:00 committed by GitHub
parent 40469eab78
commit ea7ca4cdab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 107 additions and 36 deletions

View file

@ -7,10 +7,17 @@
import "./styles.css"; import "./styles.css";
import { EquicordDevs } from "@utils/constants"; import { EquicordDevs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findStoreLazy } from "@webpack";
import { getMimeType, isLinkAnImage, settings, stripDiscordParams } from "./settings"; import { getMimeType, isLinkAnImage, settings, stripDiscordParams } from "./settings";
const logger = new Logger("ImagePreview", "#FFFFFF");
const StickerStore = findStoreLazy("StickersStore") as {
getStickerById(id: string): any;
};
let currentPreview: HTMLDivElement | null = null; let currentPreview: HTMLDivElement | null = null;
let currentPreviewFile: HTMLImageElement | HTMLVideoElement | null = null; let currentPreviewFile: HTMLImageElement | HTMLVideoElement | null = null;
let currentPreviewFileSize: [number, number] | null = null; let currentPreviewFileSize: [number, number] | null = null;
@ -91,7 +98,7 @@ function scanObjects(element: Element) {
element.querySelectorAll('img[data-type="sticker"]:not([data-processed="true"])').forEach(sticker => { element.querySelectorAll('img[data-type="sticker"]:not([data-processed="true"])').forEach(sticker => {
const messageParent = sticker.closest("[class^='messageListItem_']"); const messageParent = sticker.closest("[class^='messageListItem_']");
if (messageParent) { if (messageParent) {
addHoverListener(sticker); addHoverListener(sticker, true);
} }
}); });
} }
@ -112,10 +119,37 @@ function createObserver() {
}); });
} }
function loadImagePreview(url: string) { function loadImagePreview(url: string, sticker: boolean) {
let stickerType: string | null = null;
if (sticker) {
const stickerId = url.split("/").pop()?.split(".")[0] ?? null;
const stickerData = stickerId ? StickerStore.getStickerById(stickerId) : null;
if (stickerData) {
switch (stickerData.type) {
case 1:
stickerType = "png";
break;
case 2:
stickerType = "apng";
break;
case 3:
stickerType = "lottie";
break;
case 4:
stickerType = "gif";
break;
default:
stickerType = "png";
break;
}
}
}
const urlParams = new URLSearchParams(url.split("?")[1]); const urlParams = new URLSearchParams(url.split("?")[1]);
const formatParam = urlParams.get("format"); const formatParam = urlParams.get("format");
const extension = formatParam || url.split(".").pop()?.split("?")[0] || ""; const extension = stickerType || formatParam || url.split(".").pop()?.split("?")[0] || "";
const [allowed, mimeType] = getMimeType(extension); const [allowed, mimeType] = getMimeType(extension);
if (!allowed) return; if (!allowed) return;
@ -166,12 +200,11 @@ function loadImagePreview(url: string) {
updatePositionAfterLoad(); updatePositionAfterLoad();
}; };
fileName.className = "file-name";
fileName.textContent = url.split("/").pop()?.split("?")[0] || ""; fileName.textContent = url.split("/").pop()?.split("?")[0] || "";
mimeTypeSpan.textContent = mimeType; mimeTypeSpan.textContent = mimeType;
fileInfo.appendChild(mimeTypeSpan); fileInfo.appendChild(mimeTypeSpan);
fileInfo.appendChild(fileName);
fileInfo.appendChild(fileSize); fileInfo.appendChild(fileSize);
if (currentPreviewType === "video") { if (currentPreviewType === "video") {
@ -199,6 +232,7 @@ function loadImagePreview(url: string) {
fileSize.appendChild(showingSize); fileSize.appendChild(showingSize);
} }
preview.appendChild(fileName);
preview.appendChild(fileInfo); preview.appendChild(fileInfo);
}); });
@ -229,6 +263,7 @@ function loadImagePreview(url: string) {
fileSize.appendChild(showingSize); fileSize.appendChild(showingSize);
} }
preview.appendChild(fileName);
preview.appendChild(fileInfo); preview.appendChild(fileInfo);
}); });
@ -243,6 +278,8 @@ function loadImagePreview(url: string) {
} }
if (settings.store.mouseOnlyMode) { if (settings.store.mouseOnlyMode) {
preview.style.pointerEvents = "auto";
currentPreview.addEventListener("mouseover", () => { currentPreview.addEventListener("mouseover", () => {
if (currentPreview && !isCtrlHeld) { if (currentPreview && !isCtrlHeld) {
shouldKeepPreviewOpen = true; shouldKeepPreviewOpen = true;
@ -293,36 +330,40 @@ function loadImagePreview(url: string) {
function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) { function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
if (currentPreview && !isCtrlHeld) { if (currentPreview && !isCtrlHeld) {
const basePadding = 15; const topPadding = 0;
const topPadding = 40; const leftPadding = 15;
const minTopOffset = 30;
const minBottomOffset = 30;
const maxWidth: number = window.innerWidth * 0.9; const maxWidth: number = window.innerWidth * 0.9;
const maxHeight: number = window.innerHeight * 0.9; const maxHeight: number = window.innerHeight * 0.9;
const previewWidth: number = currentPreview.offsetWidth; const previewWidth: number = currentPreview.offsetWidth;
const previewHeight: number = currentPreview.offsetHeight; const previewHeight: number = currentPreview.offsetHeight;
let left: number; let left: number = mouseEvent.pageX + leftPadding;
let top: number = mouseEvent.pageY + basePadding; let top: number = mouseEvent.pageY + topPadding;
const spaceOnRight = window.innerWidth - mouseEvent.pageX - previewWidth - basePadding; const spaceOnRight = window.innerWidth - mouseEvent.pageX - previewWidth - leftPadding;
const spaceOnLeft = mouseEvent.pageX - previewWidth - basePadding; const spaceOnLeft = mouseEvent.pageX - previewWidth - leftPadding;
if (spaceOnRight >= basePadding) { if (spaceOnRight >= leftPadding) {
left = mouseEvent.pageX + basePadding; left = mouseEvent.pageX + leftPadding;
} else if (spaceOnLeft >= basePadding) { } else if (spaceOnLeft >= leftPadding) {
left = mouseEvent.pageX - previewWidth - basePadding; left = mouseEvent.pageX - previewWidth - leftPadding;
} else { } else {
left = Math.max(basePadding, Math.min(mouseEvent.pageX + basePadding, window.innerWidth - previewWidth - basePadding)); left = Math.max(leftPadding, Math.min(mouseEvent.pageX + leftPadding, window.innerWidth - previewWidth - leftPadding));
} }
if (top + previewHeight > window.innerHeight) { if (top + previewHeight > window.innerHeight - minBottomOffset) {
top = mouseEvent.pageY - previewHeight - topPadding; top = mouseEvent.pageY - previewHeight;
if (top < topPadding) { if (top < minTopOffset) {
top = window.innerHeight - previewHeight - topPadding * 2; top = minTopOffset;
} }
} else if (top + previewHeight + topPadding > window.innerHeight - minBottomOffset) {
top = window.innerHeight - previewHeight - minBottomOffset;
} else { } else {
top = Math.min(top, window.innerHeight - previewHeight - basePadding * 2); top = Math.min(top, window.innerHeight - previewHeight - topPadding - minBottomOffset);
} }
currentPreview.style.left = `${left}px`; currentPreview.style.left = `${left}px`;
@ -336,7 +377,7 @@ function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
} }
} }
function addHoverListener(element: Element) { function addHoverListener(element: Element, sticker: boolean = false) {
element.setAttribute("data-processed", "true"); element.setAttribute("data-processed", "true");
element.addEventListener("mouseover", event => { element.addEventListener("mouseover", event => {
@ -365,7 +406,7 @@ function addHoverListener(element: Element) {
if (!strippedURL) return; if (!strippedURL) return;
hoverDelayTimeout = setTimeout(() => { hoverDelayTimeout = setTimeout(() => {
loadImagePreview(strippedURL); loadImagePreview(strippedURL, sticker);
if (lastMouseEvent) { if (lastMouseEvent) {
updatePreviewPosition(lastMouseEvent, element as HTMLElement); updatePreviewPosition(lastMouseEvent, element as HTMLElement);
} }
@ -451,17 +492,20 @@ export default definePlugin({
settings: settings, settings: settings,
start() { start() {
const targetNode = document.querySelector('[class*="app-"]'); const targetNode = document.body;
if (!targetNode) return;
scanObjects(targetNode); if (targetNode) {
document.addEventListener("keydown", handleKeydown); scanObjects(targetNode);
document.addEventListener("keyup", handleKeyup); document.addEventListener("keydown", handleKeydown);
document.addEventListener("mousemove", handleMousemove); document.addEventListener("keyup", handleKeyup);
document.addEventListener("mouseup", handleMouseup); document.addEventListener("mousemove", handleMousemove);
document.addEventListener("mouseup", handleMouseup);
observer = createObserver(); observer = createObserver();
observer.observe(targetNode, { childList: true, subtree: true }); observer.observe(targetNode, { childList: true, subtree: true });
} else {
logger.info("body wasnt found ?????????");
}
}, },
stop() { stop() {
@ -476,3 +520,4 @@ export default definePlugin({
document.removeEventListener("mouseup", handleMouseup); document.removeEventListener("mouseup", handleMouseup);
} }
}); });

View file

@ -74,12 +74,14 @@ const mimeTypes = {
jpg: "image/jpeg", jpg: "image/jpeg",
jpeg: "image/jpeg", jpeg: "image/jpeg",
png: "image/png", png: "image/png",
apng: "image/apng",
gif: "image/gif", gif: "image/gif",
webp: "image/webp", webp: "image/webp",
svg: "image/svg+xml", svg: "image/svg+xml",
mp4: "video/mp4", mp4: "video/mp4",
webm: "video/webm", webm: "video/webm",
mov: "video/quicktime", mov: "video/quicktime",
lottie: "application/json",
}; };
function getMimeType(extension: string | undefined): [boolean, string] { function getMimeType(extension: string | undefined): [boolean, string] {
@ -105,8 +107,12 @@ function stripDiscordParams(url: string) {
.replace(/\?$/, "") .replace(/\?$/, "")
.replace(/&{2,}/g, "&"); .replace(/&{2,}/g, "&");
if (newUrl.includes("quality=lossless") && !newUrl.includes("?")) { if (!newUrl.includes("quality=lossless")) {
newUrl = newUrl.replace(/&quality=lossless/, "?quality=lossless"); newUrl += newUrl.includes("?") ? "&quality=lossless" : "?quality=lossless";
}
if (!newUrl.includes("?") && newUrl.includes("&")) {
newUrl = newUrl.replace("&", "?");
} }
return newUrl; return newUrl;

View file

@ -1,10 +1,9 @@
.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;
padding: 1px; padding: 1px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -19,6 +18,10 @@
pointer-events: auto; pointer-events: auto;
} }
.image-preview.allow-zoom-and-drag img {
cursor: grab;
}
.image-preview .file-info { .image-preview .file-info {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -30,6 +33,22 @@
text-align: center; text-align: center;
} }
.image-preview .file-name {
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
text-align: center;
background-color: var(--background-primary);
color: var(--text-normal);
padding: 2px 5px;
border-radius: 4px;
font-size: 12px;
box-shadow: 0 0 0 1px var(--background-secondary);
border: 1px solid var(--background-secondary);
}
.image-preview .file-info span { .image-preview .file-info span {
background-color: var(--background-primary); background-color: var(--background-primary);
color: var(--text-normal); color: var(--text-normal);
@ -59,6 +78,7 @@
color: var(--text-muted); color: var(--text-muted);
} }
.image-preview.allow-zoom-and-drag .file-name,
.image-preview.allow-zoom-and-drag .file-info { .image-preview.allow-zoom-and-drag .file-info {
display: none; display: none;
} }