From 83357c5dfa749bd58d7bed6c2083d1a7a0659739 Mon Sep 17 00:00:00 2001 From: prism Date: Mon, 19 Jan 2026 22:00:25 +0100 Subject: [PATCH] IconViewer: use IconModule (#662) * IconViewer: use IconModule * t --- .../iconViewer/components/IconsTab.tsx | 16 +- .../iconViewer/components/Modals.tsx | 31 ++-- src/equicordplugins/iconViewer/names.ts | 151 ------------------ src/equicordplugins/iconViewer/styles.css | 44 ++--- src/equicordplugins/iconViewer/utils.ts | 14 +- 5 files changed, 41 insertions(+), 215 deletions(-) delete mode 100644 src/equicordplugins/iconViewer/names.ts diff --git a/src/equicordplugins/iconViewer/components/IconsTab.tsx b/src/equicordplugins/iconViewer/components/IconsTab.tsx index 21d94897f..423f5a2e5 100644 --- a/src/equicordplugins/iconViewer/components/IconsTab.tsx +++ b/src/equicordplugins/iconViewer/components/IconsTab.tsx @@ -17,9 +17,8 @@ import { useIntersection } from "@utils/react"; import { Icon } from "@vencord/discord-types"; import { Clickable, TextInput, useCallback, useEffect, useMemo, useState } from "@webpack/common"; -import { getNameByIcon, IconsFinds } from "../names"; import { IconsDef } from "../types"; -import { findAllIcons } from "../utils"; +import { getIconsModule } from "../utils"; import { openIconModal } from "./Modals"; let cachedIcons: IconsDef | null = null; @@ -27,10 +26,13 @@ let cachedIcons: IconsDef | null = null; function getIcons(): IconsDef { if (cachedIcons) return cachedIcons; - const allIcons = Array.from(new Set(findAllIcons())); + const iconsModule = getIconsModule(); cachedIcons = Object.fromEntries( - allIcons.map((icon, idx) => [getNameByIcon(icon, String(idx)), icon]) + Object.entries(iconsModule).filter(([name, fn]) => + typeof fn === "function" && name.endsWith("Icon") + ) ); + return cachedIcons; } @@ -47,11 +49,11 @@ function searchMatch(search: string, name: string, Icon: Icon, searchByFunction: } function IconItem({ iconName, Icon }: { iconName: string; Icon: Icon; }) { - const fill = iconName === "CircleShield" ? "var(--background-base-low)" : "var(--interactive-icon-default)"; + const fill = iconName === "CircleShieldIcon" ? "var(--background-base-low)" : "var(--interactive-icon-default)"; return (
- openIconModal(iconName, Icon, IconsFinds[iconName])}> + openIconModal(iconName, Icon)}>
@@ -107,7 +109,7 @@ function IconsTab() { return (
- + - @@ -301,8 +306,8 @@ function IconModal({ iconName, Icon, findPattern, onClose, transitionState }: { ); } -export function openIconModal(iconName: string, Icon: Icon, findPattern?: string) { - openModal(props => ); +export function openIconModal(iconName: string, Icon: Icon) { + openModal(props => ); } export function SettingsAbout() { diff --git a/src/equicordplugins/iconViewer/names.ts b/src/equicordplugins/iconViewer/names.ts deleted file mode 100644 index 00c82ea23..000000000 --- a/src/equicordplugins/iconViewer/names.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { Icon } from "@vencord/discord-types"; - -// name: pattern -export const IconsFinds: Record = { - Discord: "1.6 5.64-2.87", - XboxNeutral: "8.68-.62c.89-.81 1.5", - PlaystationNeutral: "2.04Zm-9.35", - TwitterNeutral: "M13.86 10.47", // even discord calls it twitter lmao - InstagramNeutral: "4.12.07Zm.1 2c-", - YoutubeNeutral: "11.5s0 3.95.5 5.85a3.", - FacebookNeutral: "2.8V12h2.8V9", - NintendoSwitchNeutral: "14V2.32c0", - Pencil: "0-2.82 0l-1.38 1.38a1", - AngleBrackets: "0-.4.8v1.98c0", - NitroWheel: "2h3a1 1 0 1 1 0 2H5.5", - Bill: "75.34.75.75C6 7.99 5 9", - Chat: "2.2 22H12Z\",", - ChatVoice: "22H12Zm2-5.26c0", - ChatX: ".23.46-.48.47L12 22H2.", - ChatSmile: "04-.61A10 10 0 1 1 22 ", - ChatRetry: "14.07.3.09.44.04a7", - ChatPlus: "1.24-.37V12a10 10 0 1 ", - Bug: "1.1.27.1.37 0a6.66 6.6", - B: "9V2.9c0-.5.4-.9.9-.9h7", - Eye: "19.1 21 12 21c-7.11 0-", - EyeSlash: "2.63-2.63c", - EyePlus: "3.32ZM19 14a1 ", - Heart: "0C9.43 20.48 1 15.09 1", - Star: ".73-2.25h6.12l1.9-5.83Z", - StarOutline: "3.1h5.26l1.62", - StarShooting: "1.35l2.95 2.14", - QrCode: "0v3ZM20", - Friends: "12h1a8", - PlusSmall: "0v-5h5a1", - CircleQuestion: "10.58l-3.3-3.3a1", - Pin: "1-.06-.63L6.16", - PinUpright: "5H8v4.35l-3.39", - PinUprightSlash: "1.56ZM11.08 ", - ArrowsLeftRight: "18.58V3a1", - XSmall: "13.42l5.3", - XLarge: "13.42l7.3 7.3Z", - XSmallBold: "12l4.94-4.94a1.5", - XLargeBold: "12l6.94-6.94a1.5", - Lock: "3Zm9-3v3H9V6a3", - LockUnlocked: "1-1.33-1.5ZM14", - Video: "1.45-.9V7.62a1", - VideoSlash: "1.4l20-20ZM9.2", - VideoLock: "1.32-.5V7.62a1", - Fire: "14Zm9.26-.84a.57.57", - Warning: "3.15H3.29c-1.74", - Download: "1.42l3.3 3.3V3a1", - Upload: "0ZM3 20a1 1", - // QuestionMark: "0ZM5.5 7a1.5" Unknown name - Quest: "10.47a.76.76", - Play: "4.96v14.08c0", - Emoji: " 0 0 0 0 22ZM6.5", - Gif: "3H5Zm2.18 13.8", - Trash: "2.81h8.36a3", - Bell: "9.5v2.09c0", - Screen: "0-3-3H5ZM13.5", - ScreenArrow: "3V5Zm16", - ScreenStream: " 2-2h3a2", - ScreenSystemRequirements: "3V5Zm3", // a guess - ScreenSlash: "5.8ZM17.15", - ScreenX: "1-3-3V5Zm6.3.3a1", - Plus: "0v8H3a1 1 0 1 0 0 2h8v8a1", - Id: "15h2.04V7.34H6V17Zm4", - Tv: "0-3-3H4ZM6 20a1", - Crown: "1.18l.82.82-3.61", - React: "04-4ZM16.96 4.08c", - Camera: "1.34 1.71 1.34H20a3", - Sticker: "1-.58.82l-4.24", - StageX: "13.07-1.38ZM16.7", - StageLock: "7.14-3.85ZM18.98", - Stage: "20.03c-.25.72.12", - ConnectionFine: "1 0 1 1-2 0A17 17 ", - ConnectionAverage: "\"M3 7a1 1 0 0", - ConnectionBad: "\"M2 13a1 1 0 0", - ConnectionUnknown: "15.86-.6.9-.2.02", - ChatWarning: ".54.5H2.2a1", - ChatCheck: "22H12c.22", - Hammer: "1.42ZM7.76", - StickerSmall: "1-.5.5H7a4", - StickerSad: "1.66-1.12 5.5", - StickerDeny: "\"M21.76 14.83a", // a guess - MagnifyingGlassPlus: "M11 7a1 1 0", - MagnifyingGlassMinus: "3v12H5.5a1.5 1.5", - // MagnifyingGlass: "???", // not quite possible - ChatArrowRight: "2.43l.06", - Bookmark: "1-1.67.74l", - ChannelList: "1-1-1ZM2 8a1", - ChannelListMagnifyingGlass: "2h18a1 1 0 1 0 0-2H3ZM2", - Activities: "1h3a3 3 0 0 0 3-3Z\"", - ActivitiesPlus: "14.35v1.29a", - AnnouncementsLock: "1-2.46-1.28 3.86", - AnnouncementsWarning: "1-2.46-1.28 3.85", - Announcements: ".42.27.79.62", - ShieldLock: "2.83v2.67a.5.5", - ShieldUser: "9.77V6.75c0-.57.17", - ShieldAt: "14.42-.35.75", - Shield: "M4.27 5.22A2.66", // a guess - Slash: "1-.43-.76L15.78", - SlashBox: "0-3-3H5Zm12.79", - Apps: "2.95H20a2 2 0", - CheckmarkLarge: "1.4l-12 12a1", - CheckmarkLargeBold: "2.12-2.12L9", - CheckmarkSmallBold: "13.88l6.94-6.94a1.5", - CheckmarkSmall: "1-1.4 0l-4-4a1", - DoubleCheckmark: "1.4l4.5 4.5a1", - NewUser: "0-.92h-.03a2", // a guess - UserCheck: "0l1.8-1.8c.17", - User: "2.9.06.24.26.", - UserMinus: "3-3h5.02c.38", - UserPlus: "2.07ZM12", - UserPlay: "0-3.61-.71h-.94Z", - UserBox: "0-3-3H5Zm10 6a3", // a guess - Settings: "0ZM16 12a4", - SettingsInfo: "10Zm1-4a1", - Hashtag: "8 4.84a1", // a guess - HashtagLocked: "2.02.31.03", // a guess - HashtagWarning: "8h1.26Z", // a guess - HashtagPlay: "52.88H9.85l", // a guess - Flag: "5.85v7.3a2", - Language: "5.43h3.85l", - Lightbulb: "8.5ZM15.1 19c.5", - Key: "23-.24ZM10 16a2", - InBox: "3H5ZM4 5.5C4", - BookmarkOutline: "0-1-1ZM7 2a3", - Food: "7.58V8a1 1", - CircleShield: "8 10.9999V17.9999C8" -}; - -// 13l4.91-8.05a1.8 - -const namePatterns = new Map(Object.entries(IconsFinds)); - -export function getNameByIcon(Icon: Icon, defaultName: string) { - for (const [name, pattern] of namePatterns) { - if (String(Icon).includes(pattern)) { - namePatterns.delete(name); - return name; - } - } - return defaultName; -} diff --git a/src/equicordplugins/iconViewer/styles.css b/src/equicordplugins/iconViewer/styles.css index d520329ee..ffc458d2a 100644 --- a/src/equicordplugins/iconViewer/styles.css +++ b/src/equicordplugins/iconViewer/styles.css @@ -1,3 +1,4 @@ +/* Icon grid */ .vc-icons-tab-grid-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); @@ -13,7 +14,6 @@ .vc-icon-container { padding: 12px; border-radius: 8px; - border: 3px solid transparent; transition: background-color 0.15s ease; } @@ -22,7 +22,6 @@ } .vc-icon-icon { - color: var(--interactive-icon-default); transition: transform 0.15s ease, filter 0.15s ease; } @@ -35,7 +34,6 @@ font-size: 0.75rem; margin-top: 4px; text-align: center; - white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 64px; @@ -44,11 +42,10 @@ .vc-icon-tab-search-bar-grid { display: flex; gap: 8px; - align-items: center; margin-bottom: 16px; } -.vc-icon-tab-search-bar-grid > div:first-child { +.vc-icon-tab-search-bar-grid>div:first-child { flex: 1; } @@ -56,32 +53,16 @@ height: 32px; } +/* Modal */ .vc-ic-modal-header { - align-items: flex-start; position: relative; padding: 16px 16px 16px 24px; - z-index: 1; -} - -.vc-ic-modal-header-content { - display: flex; - flex-direction: column; - gap: 8px; - flex: 1; } .vc-ic-modal-header-trailing { position: absolute; top: 8px; right: 8px; - display: flex; - flex-direction: column; - align-items: flex-end; - gap: 4px; -} - -.vc-ic-modal-content { - padding: 16px; } .vc-ic-modal-main { @@ -95,11 +76,7 @@ display: flex; align-items: center; justify-content: center; - background-image: repeating-linear-gradient(45deg, - #ffffff1a 0, - #ffffff1a 10px, - #0000001a 10px, - #0000001a 20px); + background-image: repeating-linear-gradient(45deg, #ffffff1a 0, #ffffff1a 10px, #0000001a 10px, #0000001a 20px); border-radius: 8px; cursor: context-menu; } @@ -123,18 +100,15 @@ } .vc-ic-modal-footer { - display: flex; flex-direction: row-reverse; - justify-content: flex-start; - gap: 8px; +} + +.vc-ic-use-as { + margin-top: 16px; + margin-bottom: 8px; } .vc-ic-unordered-list li { margin-left: 16px; list-style: disc; } - -.vc-ic-modal-title { - user-select: none; - padding-right: 32px; -} \ No newline at end of file diff --git a/src/equicordplugins/iconViewer/utils.ts b/src/equicordplugins/iconViewer/utils.ts index 05fc25e22..972a77e34 100644 --- a/src/equicordplugins/iconViewer/utils.ts +++ b/src/equicordplugins/iconViewer/utils.ts @@ -4,13 +4,15 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findAll, findByPropsLazy, waitFor } from "@webpack"; +import { Icon } from "@vencord/discord-types"; +import { findByPropsLazy, waitFor } from "@webpack"; import { CssColorData, IconSize } from "./types"; let colorKeys: string[] = []; const Colors = findByPropsLazy("colors", "layout"); +const IconsModule = findByPropsLazy("AngleBracketsIcon", "StaffBadgeIcon") as Record; export const iconSizesInPx: Record = findByPropsLazy("md", "lg", "xxs"); export const iconSizes: IconSize[] = ["xxs", "xs", "sm", "md", "lg"]; @@ -35,14 +37,8 @@ export const cssColors = new Proxy({} as Record, { } }); -export function findAllIcons() { - return findAll(m => { - if (typeof m !== "function") return false; - const str = m.toString?.() ?? ""; - if (str.includes("direction:")) return false; - if (str.includes('viewBox:"0 0 272 143"')) return false; - return str.includes("viewBox:") && str.includes("color:") && (str.includes("foreground:") || str.includes("colorClass:")); - }); +export function getIconsModule(): Record { + return IconsModule; } waitFor(["colors", "layout"], m => {