diff options
author | Nuckyz <61953774+Nuckyz@users.noreply.github.com> | 2023-04-14 21:47:03 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-15 02:47:03 +0200 |
commit | 96f640da674e89824881070c4081b7aee212e619 (patch) | |
tree | 9d8dbdf97313c79410c8d1a2b380116d2b7d3a86 | |
parent | e8809fc57bd1c679e9a84ae6adc949655e3a86ec (diff) | |
download | Vencord-96f640da674e89824881070c4081b7aee212e619.tar.gz Vencord-96f640da674e89824881070c4081b7aee212e619.tar.bz2 Vencord-96f640da674e89824881070c4081b7aee212e619.zip |
Make Context Menu API support hooks (#902)
Co-authored-by: V <vendicated@riseup.net>
-rw-r--r-- | src/api/ContextMenu.ts | 26 | ||||
-rw-r--r-- | src/plugins/devCompanion.dev.tsx | 4 | ||||
-rw-r--r-- | src/plugins/emoteCloner.tsx | 4 | ||||
-rw-r--r-- | src/plugins/imageZoom/index.tsx | 2 | ||||
-rw-r--r-- | src/plugins/messageLogger/index.tsx | 2 | ||||
-rw-r--r-- | src/plugins/pinDms/contextMenus.tsx | 4 | ||||
-rw-r--r-- | src/plugins/reverseImageSearch.tsx | 2 | ||||
-rw-r--r-- | src/plugins/searchReply.tsx | 3 | ||||
-rw-r--r-- | src/plugins/settings.tsx | 2 | ||||
-rw-r--r-- | src/plugins/viewIcons.tsx | 4 |
10 files changed, 29 insertions, 24 deletions
diff --git a/src/api/ContextMenu.ts b/src/api/ContextMenu.ts index 4e52131..4d1d577 100644 --- a/src/api/ContextMenu.ts +++ b/src/api/ContextMenu.ts @@ -19,17 +19,20 @@ import Logger from "@utils/Logger"; import type { ReactElement } from "react"; +type ContextMenuPatchCallbackReturn = (() => void) | void; /** * @param children The rendered context menu elements * @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example + * @returns A callback which is only ran once used to modify the context menu elements (Use to avoid duplicates) */ -export type NavContextMenuPatchCallback = (children: Array<React.ReactElement>, ...args: Array<any>) => void; +export type NavContextMenuPatchCallback = (children: Array<React.ReactElement>, ...args: Array<any>) => ContextMenuPatchCallbackReturn; /** - * @param The navId of the context menu being patched + * @param navId The navId of the context menu being patched * @param children The rendered context menu elements * @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example + * @returns A callback which is only ran once used to modify the context menu elements (Use to avoid duplicates) */ -export type GlobalContextMenuPatchCallback = (navId: string, children: Array<React.ReactElement>, ...args: Array<any>) => void; +export type GlobalContextMenuPatchCallback = (navId: string, children: Array<React.ReactElement>, ...args: Array<any>) => ContextMenuPatchCallbackReturn; const ContextMenuLogger = new Logger("ContextMenu"); @@ -78,6 +81,7 @@ export function removeContextMenuPatch<T extends string | Array<string>>(navId: /** * Remove a global context menu patch + * @param patch The patch to be removed * @returns Wheter the patch was sucessfully removed */ export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallback): boolean { @@ -87,12 +91,13 @@ export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallba /** * A helper function for finding the children array of a group nested inside a context menu based on the id of one of its childs * @param id The id of the child + * @param children The context menu children */ -export function findGroupChildrenByChildId(id: string, children: Array<React.ReactElement>, itemsArray?: Array<React.ReactElement>): Array<React.ReactElement> | null { +export function findGroupChildrenByChildId(id: string, children: Array<React.ReactElement>, _itemsArray?: Array<React.ReactElement>): Array<React.ReactElement> | null { for (const child of children) { if (child == null) continue; - if (child.props?.id === id) return itemsArray ?? null; + if (child.props?.id === id) return _itemsArray ?? null; let nextChildren = child.props?.children; if (nextChildren) { @@ -121,9 +126,6 @@ interface ContextMenuProps { const patchedMenus = new WeakSet(); export function _patchContextMenu(props: ContextMenuProps) { - if (patchedMenus.has(props)) return; - patchedMenus.add(props); - props.contextMenuApiArguments ??= []; const contextMenuPatches = navPatches.get(props.navId); @@ -132,7 +134,8 @@ export function _patchContextMenu(props: ContextMenuProps) { if (contextMenuPatches) { for (const patch of contextMenuPatches) { try { - patch(props.children, ...props.contextMenuApiArguments); + const callback = patch(props.children, ...props.contextMenuApiArguments); + if (!patchedMenus.has(props)) callback?.(); } catch (err) { ContextMenuLogger.error(`Patch for ${props.navId} errored,`, err); } @@ -141,9 +144,12 @@ export function _patchContextMenu(props: ContextMenuProps) { for (const patch of globalPatches) { try { - patch(props.navId, props.children, ...props.contextMenuApiArguments); + const callback = patch(props.navId, props.children, ...props.contextMenuApiArguments); + if (!patchedMenus.has(props)) callback?.(); } catch (err) { ContextMenuLogger.error("Global patch errored,", err); } } + + patchedMenus.add(props); } diff --git a/src/plugins/devCompanion.dev.tsx b/src/plugins/devCompanion.dev.tsx index 67388c8..15cb2b0 100644 --- a/src/plugins/devCompanion.dev.tsx +++ b/src/plugins/devCompanion.dev.tsx @@ -238,8 +238,8 @@ function initWs(isManual = false) { }); } -const contextMenuPatch: NavContextMenuPatchCallback = kids => { - kids.unshift( +const contextMenuPatch: NavContextMenuPatchCallback = children => () => { + children.unshift( <Menu.MenuItem id={NAV_ID} label="Reconnect Dev Companion" diff --git a/src/plugins/emoteCloner.tsx b/src/plugins/emoteCloner.tsx index 809518c..7b8261e 100644 --- a/src/plugins/emoteCloner.tsx +++ b/src/plugins/emoteCloner.tsx @@ -210,7 +210,7 @@ function isGifUrl(url: string) { return new URL(url).pathname.endsWith(".gif"); } -const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => { +const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { const { favoriteableId, itemHref, itemSrc, favoriteableType } = props ?? {}; if (!favoriteableId || favoriteableType !== "emoji") return; @@ -223,7 +223,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) = if (group) group.push(buildMenuItem(favoriteableId, name, isGifUrl(itemHref ?? itemSrc))); }; -const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => { +const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => () => { const { id, name, type } = props?.target?.dataset ?? {}; if (!id || !name || type !== "emoji") return; diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index d65df08..9007bf4 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -75,7 +75,7 @@ export const settings = definePluginSettings({ }); -const imageContextMenuPatch: NavContextMenuPatchCallback = (children, _) => { +const imageContextMenuPatch: NavContextMenuPatchCallback = children => () => { children.push( <Menu.MenuGroup id="image-zoom"> {/* thanks SpotifyControls */} diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index 808fd34..5ff514e 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -44,7 +44,7 @@ function addDeleteStyle() { } const MENU_ITEM_ID = "message-logger-remove-history"; -const patchMessageContextMenu: NavContextMenuPatchCallback = (children, props) => { +const patchMessageContextMenu: NavContextMenuPatchCallback = (children, props) => () => { const { message } = props; const { deleted, editHistory, id, channel_id } = message; diff --git a/src/plugins/pinDms/contextMenus.tsx b/src/plugins/pinDms/contextMenus.tsx index b04ba8c..d75c9f9 100644 --- a/src/plugins/pinDms/contextMenus.tsx +++ b/src/plugins/pinDms/contextMenus.tsx @@ -49,13 +49,13 @@ function PinMenuItem(channelId: string) { ); } -const GroupDMContext: NavContextMenuPatchCallback = (children, props) => { +const GroupDMContext: NavContextMenuPatchCallback = (children, props) => () => { const container = findGroupChildrenByChildId("leave-channel", children); if (container) container.unshift(PinMenuItem(props.channel.id)); }; -const UserContext: NavContextMenuPatchCallback = (children, props) => { +const UserContext: NavContextMenuPatchCallback = (children, props) => () => { const container = findGroupChildrenByChildId("close-dm", children); if (container) { const idx = container.findIndex(c => c?.props?.id === "close-dm"); diff --git a/src/plugins/reverseImageSearch.tsx b/src/plugins/reverseImageSearch.tsx index 74b2619..deaa280 100644 --- a/src/plugins/reverseImageSearch.tsx +++ b/src/plugins/reverseImageSearch.tsx @@ -34,7 +34,7 @@ function search(src: string, engine: string) { open(engine + encodeURIComponent(src), "_blank"); } -const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => { +const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { if (!props) return; const { reverseImageSearchType, itemHref, itemSrc } = props; diff --git a/src/plugins/searchReply.tsx b/src/plugins/searchReply.tsx index 8c7b473..cb09f5b 100644 --- a/src/plugins/searchReply.tsx +++ b/src/plugins/searchReply.tsx @@ -28,7 +28,7 @@ const ReplyIcon = LazyComponent(() => findByCode("M10 8.26667V4L3 11.4667L10 18. const replyFn = findByCodeLazy("showMentionToggle", "TEXTAREA_FOCUS", "shiftKey"); -const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => { +const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => () => { // make sure the message is in the selected channel if (SelectedChannelStore.getChannelId() !== message.channel_id) return; @@ -61,7 +61,6 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { messag /> )); } - }; diff --git a/src/plugins/settings.tsx b/src/plugins/settings.tsx index 74d0496..5dec83c 100644 --- a/src/plugins/settings.tsx +++ b/src/plugins/settings.tsx @@ -41,7 +41,7 @@ export default definePlugin({ // doesn't contain our sections. This patches the actions of our // sections to manually use SettingsRouter (which only works on desktop // but the context menu is usually not available on mobile anyway) - addContextMenuPatch("user-settings-cog", children => { + addContextMenuPatch("user-settings-cog", children => () => { const section = children.find(c => Array.isArray(c) && c.some(it => it?.props?.id === "VencordSettings")) as any; section?.forEach(c => { if (c?.props?.id?.startsWith("Vencord")) { diff --git a/src/plugins/viewIcons.tsx b/src/plugins/viewIcons.tsx index 85105c5..7519d74 100644 --- a/src/plugins/viewIcons.tsx +++ b/src/plugins/viewIcons.tsx @@ -81,7 +81,7 @@ function openImage(url: string) { )); } -const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => { +const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => () => { const memberAvatar = GuildMemberStore.getMember(guildId!, user.id)?.avatar || null; children.splice(1, 0, ( @@ -106,7 +106,7 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U )); }; -const GuildContext: NavContextMenuPatchCallback = (children, { guild: { id, icon, banner } }: GuildContextProps) => { +const GuildContext: NavContextMenuPatchCallback = (children, { guild: { id, icon, banner } }: GuildContextProps) => () => { if (!banner && !icon) return; // before copy id (if it exists) |