mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-09 14:43:03 -04:00
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:
parent
40469eab78
commit
ea7ca4cdab
3 changed files with 107 additions and 36 deletions
|
@ -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,9 +492,9 @@ export default definePlugin({
|
||||||
settings: settings,
|
settings: settings,
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
const targetNode = document.querySelector('[class*="app-"]');
|
const targetNode = document.body;
|
||||||
if (!targetNode) return;
|
|
||||||
|
|
||||||
|
if (targetNode) {
|
||||||
scanObjects(targetNode);
|
scanObjects(targetNode);
|
||||||
document.addEventListener("keydown", handleKeydown);
|
document.addEventListener("keydown", handleKeydown);
|
||||||
document.addEventListener("keyup", handleKeyup);
|
document.addEventListener("keyup", handleKeyup);
|
||||||
|
@ -462,6 +503,9 @@ export default definePlugin({
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue