PronounDB: Add support for compact mode & clean up (#604)
This commit is contained in:
		
							parent
							
								
									e143260891
								
							
						
					
					
						commit
						b90392576e
					
				
					 6 changed files with 102 additions and 30 deletions
				
			
		|  | @ -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<string, string> = 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 <PronounsChatComponent message={message} />; | ||||
| } | ||||
| 
 | ||||
| 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 <CompactPronounsChatComponent message={message} />; | ||||
| } | ||||
| 
 | ||||
| function PronounsChatComponent({ message }: { message: Message; }) { | ||||
|     const result = awaitAndFormatPronouns(message.author.id); | ||||
|     if (result != null) { | ||||
|         return ( | ||||
|             <span | ||||
|                 className={classes(styles.timestampInline, styles.timestamp)} | ||||
|             >• {formatPronouns(result)}</span> | ||||
|             >• {result}</span> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     return null; | ||||
| } | ||||
| 
 | ||||
| export function CompactPronounsChatComponent({ message }: { message: Message; }) { | ||||
|     const result = awaitAndFormatPronouns(message.author.id); | ||||
|     if (result != null) { | ||||
|         return ( | ||||
|             <span | ||||
|                 className={classes(styles.timestampInline, styles.timestamp, "vc-pronoundb-compact")} | ||||
|             >• {result}</span> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<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; | ||||
|     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 <Component {...leProps} />; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,11 +16,13 @@ | |||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| 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\)\((?<PronounComponent>.{1,2}\..),(?<pronounProps>{currentPronouns.+?:(?<fullProps>.{1,2})\.pronouns.+?})\)/, | ||||
|                 match: /\(0,.\.jsx\)\((?<PronounComponent>\i\..),(?<pronounProps>{currentPronouns.+?:(?<fullProps>\i)\.pronouns.+?})\)/, | ||||
|                 replace: "$<fullProps>&&$self.PronounsProfileWrapper($<PronounComponent>,$<pronounProps>,$<fullProps>)" | ||||
|             } | ||||
|         }, | ||||
|  | @ -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 | ||||
| }); | ||||
|  |  | |||
|  | @ -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<PronounCode> { | ||||
|     return new Promise(res => { | ||||
|  |  | |||
							
								
								
									
										9
									
								
								src/plugins/pronoundb/styles.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/plugins/pronoundb/styles.css
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| .vc-pronoundb-compact { | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| [class*="compact"] .vc-pronoundb-compact { | ||||
|     display: inline-block; | ||||
|     margin-left: -2px; | ||||
|     margin-right: 0.25rem; | ||||
| } | ||||
|  | @ -205,5 +205,9 @@ export const Devs = /* #__PURE__*/ Object.freeze({ | |||
|     cloudburst: { | ||||
|         name: "cloudburst", | ||||
|         id: 892128204150685769n | ||||
|     }, | ||||
|     TheKodeToad: { | ||||
|         name: "TheKodeToad", | ||||
|         id: 706152404072267788n | ||||
|     } | ||||
| }); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue