From 7b13b9a53ea92c337b9840c0050c6a47266efdcc Mon Sep 17 00:00:00 2001
From: Vendicated <vendicated@riseup.net>
Date: Fri, 28 Apr 2023 19:15:07 +0200
Subject: PronounDB: Fix not working in profiles

---
 .../pronoundb/components/PronounsChatComponent.tsx | 51 ++++++++---------
 .../components/PronounsProfileWrapper.tsx          | 61 --------------------
 src/plugins/pronoundb/index.ts                     | 65 ++++++----------------
 src/plugins/pronoundb/pronoundbUtils.ts            | 22 +++++++-
 src/plugins/pronoundb/settings.ts                  | 55 ++++++++++++++++++
 5 files changed, 112 insertions(+), 142 deletions(-)
 delete mode 100644 src/plugins/pronoundb/components/PronounsProfileWrapper.tsx
 create mode 100644 src/plugins/pronoundb/settings.ts

(limited to 'src')

diff --git a/src/plugins/pronoundb/components/PronounsChatComponent.tsx b/src/plugins/pronoundb/components/PronounsChatComponent.tsx
index 70a2bf3..e302676 100644
--- a/src/plugins/pronoundb/components/PronounsChatComponent.tsx
+++ b/src/plugins/pronoundb/components/PronounsChatComponent.tsx
@@ -16,66 +16,59 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-import { Settings } from "@api/settings";
 import { classes } from "@utils/misc";
 import { findByPropsLazy } from "@webpack";
 import { UserStore } from "@webpack/common";
 import { Message } from "discord-types/general";
 
-import { awaitAndFormatPronouns } from "../pronoundbUtils";
+import { useFormattedPronouns } from "../pronoundbUtils";
+import { settings } from "../settings";
 
 const styles: Record<string, string> = findByPropsLazy("timestampInline");
 
 function shouldShow(message: Message): boolean {
-    // Respect showInMessages
-    if (!Settings.plugins.PronounDB.showInMessages)
+    if (!settings.store.showInMessages)
         return false;
-    // Don't bother fetching bot or system users
     if (message.author.bot || message.author.system)
         return false;
-    // Respect showSelf options
-    if (!Settings.plugins.PronounDB.showSelf && message.author.id === UserStore.getCurrentUser().id)
+    if (!settings.store.showSelf && message.author.id === UserStore.getCurrentUser().id)
         return false;
 
     return true;
 }
 
 export function PronounsChatComponentWrapper({ message }: { message: Message; }) {
-    if (!shouldShow(message))
-        return null;
-
-    return <PronounsChatComponent message={message} />;
+    return shouldShow(message)
+        ? <PronounsChatComponent message={message} />
+        : null;
 }
 
 export function CompactPronounsChatComponentWrapper({ message }: { message: Message; }) {
-    if (!shouldShow(message))
-        return null;
-
-    return <CompactPronounsChatComponent message={message} />;
+    return shouldShow(message)
+        ? <CompactPronounsChatComponent message={message} />
+        : null;
 }
 
 function PronounsChatComponent({ message }: { message: Message; }) {
-    const result = awaitAndFormatPronouns(message.author.id);
-    if (result != null) {
-        return (
+    const result = useFormattedPronouns(message.author.id);
+
+    return result
+        ? (
             <span
                 className={classes(styles.timestampInline, styles.timestamp)}
             >• {result}</span>
-        );
-    }
-
-    return null;
+        )
+        : null;
 }
 
 export function CompactPronounsChatComponent({ message }: { message: Message; }) {
-    const result = awaitAndFormatPronouns(message.author.id);
-    if (result != null) {
-        return (
+    const result = useFormattedPronouns(message.author.id);
+
+    return result
+        ? (
             <span
                 className={classes(styles.timestampInline, styles.timestamp, "vc-pronoundb-compact")}
             >• {result}</span>
-        );
-    }
-
-    return null;
+        )
+        : null;
 }
diff --git a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx
deleted file mode 100644
index 34cfab5..0000000
--- a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Vencord, a modification for Discord's desktop app
- * Copyright (c) 2022 Vendicated and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
-
-import { Settings } from "@api/settings";
-import { UserStore } from "@webpack/common";
-
-import { awaitAndFormatPronouns } from "../pronoundbUtils";
-import { UserProfilePronounsProps, UserProfileProps } from "../types";
-
-export default function PronounsProfileWrapper(PronounsComponent: React.ElementType<UserProfilePronounsProps>, 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;
-    // Respect showSelf options
-    if (!Settings.plugins.PronounDB.showSelf && user.id === UserStore.getCurrentUser().id)
-        return null;
-
-    return <ProfilePronouns
-        userId={profileProps.userId}
-        Component={PronounsComponent}
-        leProps={props}
-    />;
-}
-
-function ProfilePronouns(
-    { userId, Component, leProps }: {
-        userId: string;
-        Component: React.ElementType<UserProfilePronounsProps>;
-        leProps: UserProfilePronounsProps;
-    }
-) {
-    const result = awaitAndFormatPronouns(userId);
-
-    // If the promise completed, the result was not "unspecified", and there is a mapping for the code, then render
-    if (result != null) {
-        // First child is the header, second is a div with the actual text
-        leProps.currentPronouns ||= result;
-        return <Component {...leProps} />;
-    }
-
-    return null;
-}
diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts
index 59ade8d..bc01e1d 100644
--- a/src/plugins/pronoundb/index.ts
+++ b/src/plugins/pronoundb/index.ts
@@ -19,20 +19,16 @@
 import "./styles.css";
 
 import { Devs } from "@utils/constants";
-import definePlugin, { OptionType } from "@utils/types";
+import definePlugin from "@utils/types";
 
 import PronounsAboutComponent from "./components/PronounsAboutComponent";
 import { CompactPronounsChatComponentWrapper, PronounsChatComponentWrapper } from "./components/PronounsChatComponent";
-import PronounsProfileWrapper from "./components/PronounsProfileWrapper";
-
-export enum PronounsFormat {
-    Lowercase = "LOWERCASE",
-    Capitalized = "CAPITALIZED"
-}
+import { useProfilePronouns } from "./pronoundbUtils";
+import { settings } from "./settings";
 
 export default definePlugin({
     name: "PronounDB",
-    authors: [Devs.Tyman, Devs.TheKodeToad],
+    authors: [Devs.Tyman, Devs.TheKodeToad, Devs.Ven],
     description: "Adds pronouns to user messages using pronoundb",
     patches: [
         // Add next to username (compact mode)
@@ -51,59 +47,30 @@ export default definePlugin({
                 replace: "[$1, $self.PronounsChatComponentWrapper(e)]"
             }
         },
-        // Hijack the discord pronouns section and add a wrapper around the text section
+        // Patch the profile popout username header to use our pronoun hook instead of Discord's pronouns
         {
-            find: ".Messages.BOT_PROFILE_SLASH_COMMANDS",
+            find: ".userTagNoNickname",
             replacement: {
-                match: /\(0,.\.jsx\)\((?<PronounComponent>\i\..),(?<pronounProps>{currentPronouns.+?:(?<fullProps>\i)\.pronouns.+?})\)/,
-                replace: "$<fullProps>&&$self.PronounsProfileWrapper($<PronounComponent>,$<pronounProps>,$<fullProps>)"
+                match: /=(\i)\.pronouns/,
+                replace: "=$self.useProfilePronouns($1.user.id)"
             }
         },
-        // Force enable pronouns component ignoring the experiment value
+        // Patch the profile modal username header to use our pronoun hook instead of Discord's pronouns
         {
-            find: ".Messages.USER_POPOUT_PRONOUNS",
+            find: ".USER_PROFILE_ACTIVITY",
             replacement: {
-                match: /\.showPronouns/,
-                replace: ".showPronouns||true"
+                match: /\).showPronouns/,
+                replace: ").showPronouns||true;if(arguments[0].displayProfile)arguments[0].displayProfile.pronouns=$self.useProfilePronouns(arguments[0].user.id)"
             }
         }
     ],
 
-    options: {
-        pronounsFormat: {
-            type: OptionType.SELECT,
-            description: "The format for pronouns to appear in chat",
-            options: [
-                {
-                    label: "Lowercase",
-                    value: PronounsFormat.Lowercase,
-                    default: true
-                },
-                {
-                    label: "Capitalized",
-                    value: PronounsFormat.Capitalized
-                }
-            ]
-        },
-        showSelf: {
-            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
-        }
-    },
+    settings,
+
     settingsAboutComponent: PronounsAboutComponent,
+
     // Re-export the components on the plugin object so it is easily accessible in patches
     PronounsChatComponentWrapper,
     CompactPronounsChatComponentWrapper,
-    PronounsProfileWrapper
+    useProfilePronouns
 });
diff --git a/src/plugins/pronoundb/pronoundbUtils.ts b/src/plugins/pronoundb/pronoundbUtils.ts
index c2354c3..c079e36 100644
--- a/src/plugins/pronoundb/pronoundbUtils.ts
+++ b/src/plugins/pronoundb/pronoundbUtils.ts
@@ -20,10 +20,16 @@ import { Settings } from "@api/settings";
 import { VENCORD_USER_AGENT } from "@utils/constants";
 import { debounce } from "@utils/debounce";
 import { useAwaiter } from "@utils/misc";
+import { UserStore } from "@webpack/common";
 
-import { PronounsFormat } from ".";
+import { settings } from "./settings";
 import { PronounCode, PronounMapping, PronounsResponse } from "./types";
 
+export const enum PronounsFormat {
+    Lowercase = "LOWERCASE",
+    Capitalized = "CAPITALIZED"
+}
+
 // A map of cached pronouns so the same request isn't sent twice
 const cache: Record<string, PronounCode> = {};
 // A map of ids and callbacks that should be triggered on fetch
@@ -40,8 +46,8 @@ const bulkFetch = debounce(async () => {
     }
 });
 
-export function awaitAndFormatPronouns(id: string): string | null {
-    const [result, , isPending] = useAwaiter(() => fetchPronouns(id), {
+export function useFormattedPronouns(id: string): string | null {
+    const [result] = useAwaiter(() => fetchPronouns(id), {
         fallbackValue: getCachedPronouns(id),
         onError: e => console.error("Fetching pronouns failed: ", e)
     });
@@ -53,6 +59,16 @@ export function awaitAndFormatPronouns(id: string): string | null {
     return null;
 }
 
+export function useProfilePronouns(id: string) {
+    const pronouns = useFormattedPronouns(id);
+
+    if (!settings.store.showInProfile) return null;
+    if (!settings.store.showSelf && id === UserStore.getCurrentUser().id) return null;
+
+    return pronouns;
+}
+
+
 // Gets the cached pronouns, if you're too impatient for a promise!
 export function getCachedPronouns(id: string): PronounCode | null {
     return cache[id] ?? null;
diff --git a/src/plugins/pronoundb/settings.ts b/src/plugins/pronoundb/settings.ts
new file mode 100644
index 0000000..4ccadaa
--- /dev/null
+++ b/src/plugins/pronoundb/settings.ts
@@ -0,0 +1,55 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2023 Vendicated and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+import { definePluginSettings } from "@api/settings";
+import { OptionType } from "@utils/types";
+
+import { PronounsFormat } from "./pronoundbUtils";
+
+export const settings = definePluginSettings({
+    pronounsFormat: {
+        type: OptionType.SELECT,
+        description: "The format for pronouns to appear in chat",
+        options: [
+            {
+                label: "Lowercase",
+                value: PronounsFormat.Lowercase,
+                default: true
+            },
+            {
+                label: "Capitalized",
+                value: PronounsFormat.Capitalized
+            }
+        ]
+    },
+    showSelf: {
+        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
+    }
+});
-- 
cgit