From 334ce7c113ab86f964d96a0fa5000d98bd29fade Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:02:52 -0500 Subject: [PATCH] =?UTF-8?q?Krystal=F0=9F=98=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../messageColors/constants.ts | 34 ++++- src/equicordplugins/messageColors/index.tsx | 142 +++++++++++------- src/equicordplugins/messageColors/styles.css | 5 +- src/equicordplugins/signature/index.tsx | 4 +- 5 files changed, 123 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 303692f7..7194eb48 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - SekaiStickers by MaiKokain - ServerSearch by camila314 - ShowBadgesInChat by Inbestigator & KrystalSkull -- Signature by KrystalSkull +- Signature by Ven, Rini, ImBanana, KrystalSkull - SidebarChat by Joona - StatsfmRPC by Crxaw & vmohammad - Slap by Korbo diff --git a/src/equicordplugins/messageColors/constants.ts b/src/equicordplugins/messageColors/constants.ts index 30336512..ccc8f686 100644 --- a/src/equicordplugins/messageColors/constants.ts +++ b/src/equicordplugins/messageColors/constants.ts @@ -13,6 +13,12 @@ export const enum RenderType { BACKGROUND, } +export const enum BlockDisplayType { + LEFT, + RIGHT, + BOTH +} + export const settings = definePluginSettings({ renderType: { type: OptionType.SELECT, @@ -32,6 +38,33 @@ export const settings = definePluginSettings({ value: RenderType.BACKGROUND }, ] + }, + enableShortHexCodes: { + type: OptionType.BOOLEAN, + description: "Enable 3 char hex-code like #39f", + default: true, + // Regex are created on the start, so without restart nothing would change + restartNeeded: true + }, + blockView: { + type: OptionType.SELECT, + disabled: () => settings.store.renderType !== RenderType.BLOCK, + description: "Where to display colored block", + options: [ + { + label: "Right side", + value: BlockDisplayType.RIGHT, + default: true + }, + { + label: "Left side", + value: BlockDisplayType.LEFT + }, + { + label: "Both sides", + value: BlockDisplayType.BOTH + } + ] } }); @@ -59,5 +92,4 @@ export const regex = [ { reg: /rgb\(\v\c\v\c\v\)/g, type: ColorType.RGB }, { reg: /rgba\(\v\c\v\c\v(\c|\/?)\s*\f\)/g, type: ColorType.RGBA }, { reg: /hsl\(\v°?\c\s*?\d+%?\s*?\c\s*?\d+%?\s*?\)/g, type: ColorType.HSL }, - { reg: /#(?:[0-9a-fA-F]{3}){1,2}/g, type: ColorType.HEX } ].map(v => { v.reg = replaceRegexp(v.reg.source); return v; }); diff --git a/src/equicordplugins/messageColors/index.tsx b/src/equicordplugins/messageColors/index.tsx index d90f069d..b5fe6155 100644 --- a/src/equicordplugins/messageColors/index.tsx +++ b/src/equicordplugins/messageColors/index.tsx @@ -6,20 +6,14 @@ import "./styles.css"; +import ErrorBoundary from "@components/ErrorBoundary"; import { EquicordDevs } from "@utils/constants"; -import definePlugin from "@utils/types"; +import definePlugin, { StartAt } from "@utils/types"; import { React } from "@webpack/common"; +import type { ReactElement } from "react"; -import { - ColorType, - regex, - RenderType, - replaceRegexp, - settings, -} from "./constants"; +import { BlockDisplayType, ColorType, regex, RenderType, replaceRegexp, settings } from "./constants"; -const source = regex.map(r => r.reg.source).join("|"); -const matchAllRegExp = new RegExp(`^(${source})`, "i"); interface ParsedColorInfo { type: "color"; @@ -28,10 +22,7 @@ interface ParsedColorInfo { text: string; } -const requiredFirstCharacters = ["r", "h", "#"].flatMap(v => [ - v, - v.toUpperCase(), -]); +const requiredFirstCharacters = ["r", "h", "#"].flatMap(v => [v, v.toUpperCase()]); export default definePlugin({ authors: [EquicordDevs.Hen], @@ -46,8 +37,8 @@ export default definePlugin({ group: true, replacement: { match: /roleMention:\{order:(\i\.\i\.order)/, - replace: "color:$self.getColor($1),$&", - }, + replace: "color:$self.getColor($1),$&" + } }, // Changes text md rule regex, so it stops right before hsl( | rgb( // Without it discord will try to pass a string without those to color rule @@ -55,11 +46,19 @@ export default definePlugin({ find: ".defaultRules.text,match:", group: true, replacement: { - // $) don't match with a " after the ) - match: /\$\)(?!")/, + // $)/) + match: /\$\)\//, // hsl(|rgb(|$& - replace: requiredFirstCharacters.join("|") + "|$&", - }, + replace: requiredFirstCharacters.join("|") + "|$&" + } + }, + // Fix the issue with [#123](https://example.com) rendered as plain text + { + find: "parseInlineCodeChildContent:", + replacement: { + match: /parseInlineCodeChildContent:/, + replace: "isInsideOfLink:true,$&" + } }, // Discord just requires it to be here // Or it explodes (bad) @@ -68,11 +67,23 @@ export default definePlugin({ group: true, replacement: { match: /roleMention:{type:/, - replace: 'color:{type:"inlineObject"},$&', - }, + replace: "color:{type:\"inlineObject\"},$&", + } }, ], + start() { + const amount = settings.store.enableShortHexCodes ? "{1,2}" : "{2}"; + regex.push({ + reg: new RegExp("#(?:[0-9a-fA-F]{3})" + amount, "g"), + type: ColorType.HEX + }); + }, + // Needed to load all regex before patching + startAt: StartAt.Init, getColor(order: number) { + const source = regex.map(r => r.reg.source).join("|"); + const matchAllRegExp = new RegExp(`^(${source})`, "i"); + return { order, // Don't even try to match if the message chunk doesn't start with... @@ -82,20 +93,16 @@ export default definePlugin({ match(content: string) { return matchAllRegExp.exec(content); }, - parse( - matchedContent: RegExpExecArray, - _, - parseProps: Record, - ): ParsedColorInfo | { type: "text"; content: string; } { + parse(matchedContent: RegExpExecArray, _, parseProps: Record): + ParsedColorInfo | ({ type: "text", content: string; }) { // This check makes sure that it doesn't try to parse color // When typing/editing message // // Discord doesn't know how to deal with color and crashes - if (!parseProps.messageId) - return { - type: "text", - content: matchedContent[0], - }; + if (!parseProps.messageId || parseProps.isInsideOfLink) return { + type: "text", + content: matchedContent[0] + }; const content = matchedContent[0]; try { @@ -105,44 +112,59 @@ export default definePlugin({ type: "color", colorType: type, color: parseColor(content, type), - text: content, + text: content }; } catch (e) { console.error(e); return { type: "text", - content: matchedContent[0], + content: matchedContent[0] }; } }, - // react(args: ReturnType) - react({ text, colorType, color }: ParsedColorInfo) { + react: ErrorBoundary.wrap(({ text, colorType, color }: ParsedColorInfo) => { if (settings.store.renderType === RenderType.FOREGROUND) { return {text}; } const styles = { - "--color": color, + "--color": color } as React.CSSProperties; if (settings.store.renderType === RenderType.BACKGROUND) { const isDark = isColorDark(color, colorType); const className = `vc-color-bg ${!isDark ? "vc-color-bg-invert" : ""}`; - return ( - - {text} - - ); + return {text}; } - return ( - <> - {text} - - - ); - }, + // Only block display left + const margin = "2px"; + + switch (settings.store.blockView) { + case BlockDisplayType.LEFT: + styles.marginRight = margin; + return <>{text}; + + case BlockDisplayType.RIGHT: + styles.marginLeft = margin; + return <>{text}; + + case BlockDisplayType.BOTH: + styles.marginLeft = margin; + styles.marginRight = margin; + return <> + + {text} + + ; + } + }, { + fallback: data => { + const child = data.children as ReactElement; + return <>{child.props?.text}; + } + }) }; - }, + } }); // https://en.wikipedia.org/wiki/Relative_luminance @@ -150,25 +172,32 @@ const calcRGBLightness = (r: number, g: number, b: number) => { return 0.2126 * r + 0.7152 * g + 0.0722 * b; }; const isColorDark = (color: string, type: ColorType): boolean => { + const border = 115; switch (type) { case ColorType.RGBA: case ColorType.RGB: { const match = color.match(/\d+/g)!; const lightness = calcRGBLightness(+match[0], +match[1], +match[2]); - return lightness < 140; + return lightness < border; } case ColorType.HEX: { - var rgb = parseInt(color.substring(1), 16); + color = color.substring(1); + if (color.length === 3) { + color = color.split("").flatMap(v => [v, v]).join(""); + } + + const rgb = parseInt(color, 16); const r = (rgb >> 16) & 0xff; const g = (rgb >> 8) & 0xff; const b = (rgb >> 0) & 0xff; + const lightness = calcRGBLightness(r, g, b); - return lightness < 140; + return lightness < border; } case ColorType.HSL: { const match = color.match(/\d+/g)!; const lightness = +match[2]; - return lightness < 50; + return lightness < (border / 255 * 100); } } }; @@ -184,10 +213,7 @@ const getColorType = (color: string): ColorType => { }; function parseColor(str: string, type: ColorType): string { - str = str - .toLowerCase() - .trim() - .replaceAll(/(\s|,)+/g, " "); + str = str.toLowerCase().trim().replaceAll(/(\s|,)+/g, " "); switch (type) { case ColorType.RGB: return str; diff --git a/src/equicordplugins/messageColors/styles.css b/src/equicordplugins/messageColors/styles.css index 87d34e84..be10871b 100644 --- a/src/equicordplugins/messageColors/styles.css +++ b/src/equicordplugins/messageColors/styles.css @@ -3,10 +3,11 @@ background: var(--color); height: 1rem; vertical-align: middle; + margin-bottom: 0.2rem; border-radius: 4px; display: inline-block; user-select: none; - margin-left: 2px; + box-sizing: border-box; } .vc-color-bg { @@ -16,5 +17,5 @@ /* Light color in dark theme */ .theme-dark .vc-color-bg.vc-color-bg-invert, .theme-light .vc-color-bg:not(.vc-color-bg-invert) { - color: var(--background-tertiary); + color: var(--background-secondary); } diff --git a/src/equicordplugins/signature/index.tsx b/src/equicordplugins/signature/index.tsx index c160bab3..70c17801 100644 --- a/src/equicordplugins/signature/index.tsx +++ b/src/equicordplugins/signature/index.tsx @@ -9,7 +9,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { addMessagePreSendListener, removeMessagePreSendListener } from "@api/MessageEvents"; import { definePluginSettings, migratePluginSettings } from "@api/Settings"; -import { EquicordDevs } from "@utils/constants"; +import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { Menu, React } from "@webpack/common"; @@ -98,7 +98,7 @@ migratePluginSettings("Signature", "SentVia"); export default definePlugin({ name: "Signature", description: "Automated fingerprint/end text", - authors: [EquicordDevs.KrystalSkull], + authors: [Devs.Ven, Devs.Rini, Devs.ImBanana, EquicordDevs.KrystalSkull], dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"], start: () => {