From b90392576e81fe2d0e665039ec832d47dc6a731c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 25 Mar 2023 01:30:24 +0000 Subject: [PATCH] PronounDB: Add support for compact mode & clean up (#604) --- .../components/PronounsChatComponent.tsx | 50 ++++++++++++++----- .../components/PronounsProfileWrapper.tsx | 20 ++++---- src/plugins/pronoundb/index.ts | 35 ++++++++++--- src/plugins/pronoundb/pronoundbUtils.ts | 14 ++++++ src/plugins/pronoundb/styles.css | 9 ++++ src/utils/constants.ts | 4 ++ 6 files changed, 102 insertions(+), 30 deletions(-) create mode 100644 src/plugins/pronoundb/styles.css diff --git a/src/plugins/pronoundb/components/PronounsChatComponent.tsx b/src/plugins/pronoundb/components/PronounsChatComponent.tsx index ce67754e..70a2bf3b 100644 --- a/src/plugins/pronoundb/components/PronounsChatComponent.tsx +++ b/src/plugins/pronoundb/components/PronounsChatComponent.tsx @@ -17,39 +17,63 @@ */ import { Settings } from "@api/settings"; -import { classes, useAwaiter } from "@utils/misc"; +import { classes } from "@utils/misc"; import { findByPropsLazy } from "@webpack"; import { UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; -import { fetchPronouns, formatPronouns } from "../pronoundbUtils"; -import { PronounMapping } from "../types"; +import { awaitAndFormatPronouns } from "../pronoundbUtils"; const styles: Record = findByPropsLazy("timestampInline"); -export default function PronounsChatComponentWrapper({ message }: { message: Message; }) { +function shouldShow(message: Message): boolean { + // Respect showInMessages + if (!Settings.plugins.PronounDB.showInMessages) + return false; // Don't bother fetching bot or system users if (message.author.bot || message.author.system) - return null; + return false; // Respect showSelf options if (!Settings.plugins.PronounDB.showSelf && message.author.id === UserStore.getCurrentUser().id) + return false; + + return true; +} + +export function PronounsChatComponentWrapper({ message }: { message: Message; }) { + if (!shouldShow(message)) return null; return ; } -function PronounsChatComponent({ message }: { message: Message; }) { - const [result, , isPending] = useAwaiter(() => fetchPronouns(message.author.id), { - fallbackValue: null, - onError: e => console.error("Fetching pronouns failed: ", e) - }); +export function CompactPronounsChatComponentWrapper({ message }: { message: Message; }) { + if (!shouldShow(message)) + return null; - // If the promise completed, the result was not "unspecified", and there is a mapping for the code, then return a span with the pronouns - if (!isPending && result && result !== "unspecified" && PronounMapping[result]) { + return ; +} + +function PronounsChatComponent({ message }: { message: Message; }) { + const result = awaitAndFormatPronouns(message.author.id); + if (result != null) { return ( • {formatPronouns(result)} + >• {result} + ); + } + + return null; +} + +export function CompactPronounsChatComponent({ message }: { message: Message; }) { + const result = awaitAndFormatPronouns(message.author.id); + if (result != null) { + return ( + • {result} ); } diff --git a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx index 79fce23a..34cfab5a 100644 --- a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx +++ b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx @@ -17,16 +17,19 @@ */ import { Settings } from "@api/settings"; -import { useAwaiter } from "@utils/misc"; import { UserStore } from "@webpack/common"; -import { fetchPronouns, formatPronouns } from "../pronoundbUtils"; -import { PronounMapping, UserProfilePronounsProps, UserProfileProps } from "../types"; +import { awaitAndFormatPronouns } from "../pronoundbUtils"; +import { UserProfilePronounsProps, UserProfileProps } from "../types"; export default function PronounsProfileWrapper(PronounsComponent: React.ElementType, props: UserProfilePronounsProps, profileProps: UserProfileProps) { const user = UserStore.getUser(profileProps.userId) ?? {}; + // Respect showInProfile + if (!Settings.plugins.PronounDB.showInProfile) + return null; // Don't bother fetching bot or system users - if (user.bot || user.system) return null; + if (user.bot || user.system) + return null; // Respect showSelf options if (!Settings.plugins.PronounDB.showSelf && user.id === UserStore.getCurrentUser().id) return null; @@ -45,15 +48,12 @@ function ProfilePronouns( leProps: UserProfilePronounsProps; } ) { - const [result, , isPending] = useAwaiter(() => fetchPronouns(userId), { - fallbackValue: null, - onError: e => console.error("Fetching pronouns failed: ", e), - }); + const result = awaitAndFormatPronouns(userId); // If the promise completed, the result was not "unspecified", and there is a mapping for the code, then render - if (!isPending && result && result !== "unspecified" && PronounMapping[result]) { + if (result != null) { // First child is the header, second is a div with the actual text - leProps.currentPronouns ||= formatPronouns(result); + leProps.currentPronouns ||= result; return ; } diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts index 820b66ec..55871912 100644 --- a/src/plugins/pronoundb/index.ts +++ b/src/plugins/pronoundb/index.ts @@ -16,11 +16,13 @@ * along with this program. If not, see . */ +import "./styles.css"; + import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import PronounsAboutComponent from "./components/PronounsAboutComponent"; -import PronounsChatComponent from "./components/PronounsChatComponent"; +import { CompactPronounsChatComponentWrapper, PronounsChatComponentWrapper } from "./components/PronounsChatComponent"; import PronounsProfileWrapper from "./components/PronounsProfileWrapper"; export enum PronounsFormat { @@ -30,22 +32,30 @@ export enum PronounsFormat { export default definePlugin({ name: "PronounDB", - authors: [Devs.Tyman], + authors: [Devs.Tyman, Devs.TheKodeToad], description: "Adds pronouns to user messages using pronoundb", patches: [ - // Patch the chat timestamp element + // Add next to username (compact mode) { find: "showCommunicationDisabledStyles", replacement: { - match: /(?<=return\s*\(0,\w{1,3}\.jsxs?\)\(.+!\w{1,3}&&)(\(0,\w{1,3}.jsxs?\)\(.+?\{.+?\}\))/, - replace: "[$1, $self.PronounsChatComponent(e)]" + match: /("span",{id:\i,className:\i,children:\i}\))/, + replace: "$1, $self.CompactPronounsChatComponentWrapper(e)" + } + }, + // Patch the chat timestamp element (normal mode) + { + find: "showCommunicationDisabledStyles", + replacement: { + match: /(?<=return\s*\(0,\i\.jsxs?\)\(.+!\i&&)(\(0,\i.jsxs?\)\(.+?\{.+?\}\))/, + replace: "[$1, $self.PronounsChatComponentWrapper(e)]" } }, // Hijack the discord pronouns section and add a wrapper around the text section { find: ".Messages.BOT_PROFILE_SLASH_COMMANDS", replacement: { - match: /\(0,.\.jsx\)\((?.{1,2}\..),(?{currentPronouns.+?:(?.{1,2})\.pronouns.+?})\)/, + match: /\(0,.\.jsx\)\((?\i\..),(?{currentPronouns.+?:(?\i)\.pronouns.+?})\)/, replace: "$&&$self.PronounsProfileWrapper($,$,$)" } }, @@ -79,10 +89,21 @@ export default definePlugin({ type: OptionType.BOOLEAN, description: "Enable or disable showing pronouns for the current user", default: true + }, + showInMessages: { + type: OptionType.BOOLEAN, + description: "Show in messages", + default: true + }, + showInProfile: { + type: OptionType.BOOLEAN, + description: "Show in profile", + default: true } }, settingsAboutComponent: PronounsAboutComponent, // Re-export the components on the plugin object so it is easily accessible in patches - PronounsChatComponent, + PronounsChatComponentWrapper, + CompactPronounsChatComponentWrapper, PronounsProfileWrapper }); diff --git a/src/plugins/pronoundb/pronoundbUtils.ts b/src/plugins/pronoundb/pronoundbUtils.ts index afeea958..74664315 100644 --- a/src/plugins/pronoundb/pronoundbUtils.ts +++ b/src/plugins/pronoundb/pronoundbUtils.ts @@ -19,6 +19,7 @@ import { Settings } from "@api/settings"; import { VENCORD_USER_AGENT } from "@utils/constants"; import { debounce } from "@utils/debounce"; +import { useAwaiter } from "@utils/misc"; import { PronounsFormat } from "."; import { PronounCode, PronounMapping, PronounsResponse } from "./types"; @@ -39,6 +40,19 @@ const bulkFetch = debounce(async () => { } }); +export function awaitAndFormatPronouns(id: string): string | null { + const [result, , isPending] = useAwaiter(() => fetchPronouns(id), { + fallbackValue: null, + onError: e => console.error("Fetching pronouns failed: ", e) + }); + + // If the promise completed, the result was not "unspecified", and there is a mapping for the code, then return the mappings + if (!isPending && result && result !== "unspecified" && PronounMapping[result]) + return formatPronouns(result); + + return null; +} + // Fetches the pronouns for one id, returning a promise that resolves if it was cached, or once the request is completed export function fetchPronouns(id: string): Promise { return new Promise(res => { diff --git a/src/plugins/pronoundb/styles.css b/src/plugins/pronoundb/styles.css new file mode 100644 index 00000000..a7d9eb9e --- /dev/null +++ b/src/plugins/pronoundb/styles.css @@ -0,0 +1,9 @@ +.vc-pronoundb-compact { + display: none; +} + +[class*="compact"] .vc-pronoundb-compact { + display: inline-block; + margin-left: -2px; + margin-right: 0.25rem; +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index d5faa43d..57fc8164 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -205,5 +205,9 @@ export const Devs = /* #__PURE__*/ Object.freeze({ cloudburst: { name: "cloudburst", id: 892128204150685769n + }, + TheKodeToad: { + name: "TheKodeToad", + id: 706152404072267788n } });