Equicord/src/equicordplugins/iconViewer/utils.tsx
2025-05-05 19:15:23 -04:00

100 lines
3.2 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { saveFile } from "@utils/web";
import { filters, findAll, findByPropsLazy, waitFor } from "@webpack";
import { createRoot, React, ReactDOM } from "@webpack/common";
import * as t from "@webpack/types";
export let _cssColors: string[] = [];
export type IconsDef = { [k: string]: t.Icon; };
export const iconSizesInPx = findByPropsLazy("md", "lg", "xxs");
export const Colors = findByPropsLazy("colors", "layout");
export const cssColors = new Proxy(
{
},
{
get: (target, key) => {
const colorKey = _cssColors[key];
return key in target
? target[key]
: Colors.colors[colorKey]?.css != null ? (target[key] = { name: colorKey.split("_").map((x: string) => x[0].toUpperCase() + x.toLowerCase().slice(1)).join(" "), css: Colors.colors[colorKey].css, key: colorKey }) : undefined;
},
set: (target, key, value) => {
target[key] = value;
return true;
}
}
) as unknown as Array<{ name: string; css: string; key: string; }>;
export const iconSizes = ["xxs", "xs", "sm", "md", "lg"];
const CrosspendingTypes: Record<string, string> = {
"image/png": "png",
"image/jpeg": "jpeg",
"image/gif": "gif",
"image/bmp": "bmp",
"image/tiff": "tiff",
"image/webp": "webp",
"image/svg+xml": "svg",
"image/avif": "avif"
};
export function saveIcon(iconName: string, icon: EventTarget & SVGSVGElement | Element | string, color: number, size: number, type = "image/png") {
const filename = `${iconName}-${cssColors[color]?.name ?? "unknown"}-${size}px.${CrosspendingTypes[type] ?? "png"}`;
if (typeof icon === "string") {
const file = new File([icon], filename, { type: "text/plain" });
saveFile(file);
return;
}
const innerElements = icon.children;
for (const el of innerElements) {
const fill = el.getAttribute("fill");
if (fill && fill.startsWith("var(")) {
el.setAttribute("fill", getComputedStyle(icon).getPropertyValue(fill.replace("var(", "").replace(")", "")));
}
}
// save svg as the given type
const canvas = document.createElement("canvas");
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0, size, size);
const link = document.createElement("a");
link.download = filename;
link.href = canvas.toDataURL(type);
link.click();
};
img.src = `data:image/svg+xml;base64,${btoa(icon.outerHTML)}`;
}
export function convertComponentToHtml(component?: React.ReactElement): string {
const container = document.createElement("div");
const root = createRoot(container);
ReactDOM.flushSync(() => root.render(component));
const content = container.innerHTML;
root.unmount();
return content;
}
export const findAllByCode = (code: string) => findAll(filters.byCode(code));
waitFor(["colors", "layout"], m => {
_cssColors = Object.keys(m.colors);
cssColors.length = _cssColors.length;
});