From 3e24b833bb8a851c119f9b7cff9f0482ad5dbd4f Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 00:58:43 +0200 Subject: [PATCH 01/13] fix image modals --- components/ImageModalWrapper.jsx | 4 ++-- modules/Patcher/Overlay.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/ImageModalWrapper.jsx b/components/ImageModalWrapper.jsx index 52a6a17..eeb45f2 100644 --- a/components/ImageModalWrapper.jsx +++ b/components/ImageModalWrapper.jsx @@ -2,7 +2,7 @@ const { React, getModule } = require('powercord/webpack'); const { sleep } = require('powercord/util'); const Lens = require('../tools/Lens/Index'); -const { imageWrapper, imagePlaceholder } = getModule([ 'imageWrapper', 'imagePlaceholder' ], false); +const { imageWrapper, imagePlaceholderOverlay } = getModule([ 'imageWrapper' ], false); // noinspection JSIgnoredPromiseFromCall module.exports = class ImageModalWrapper extends React.PureComponent { @@ -45,7 +45,7 @@ module.exports = class ImageModalWrapper extends React.PureComponent { async waitFor () { const elem = this.imgRef.current?.querySelector(`.${imageWrapper} > img, video, canvas`); - if (!elem || elem?.classList?.contains(imagePlaceholder)) { + if (!elem || elem?.classList?.contains(imagePlaceholderOverlay)) { await sleep(5); return this.waitFor(); } diff --git a/modules/Patcher/Overlay.js b/modules/Patcher/Overlay.js index b22fb92..a37c442 100644 --- a/modules/Patcher/Overlay.js +++ b/modules/Patcher/Overlay.js @@ -38,9 +38,9 @@ module.exports = class Overlay { imageModalRender (_, res, opts) { const { wrapper, downloadLink } = imageModalClasses; const Sticker = getModuleByDisplayName('Sticker', false); - const Wrapper = findInReactTree(res, ({ className }) => className === wrapper).children; - const LazyImageIndex = Wrapper.findIndex(({ type }) => type?.displayName === 'LazyImage'); - const footerIndex = Wrapper.findIndex(({ props }) => props?.className === downloadLink); + const Wrapper = findInReactTree(res, ({ props }) => props.className === wrapper).props.children; + const LazyImageIndex = Wrapper.findIndex((c) => c?.type?.displayName === 'LazyImage'); + const footerIndex = Wrapper.findIndex((c) => c?.props?.className === downloadLink); const LazyImage = Wrapper[LazyImageIndex]; if (LazyImage) { From 39d4d71dd4e4c9d09067b3987ec78316b982f22a Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 01:20:27 +0200 Subject: [PATCH 02/13] fix images context menu --- modules/Patcher/General.js | 3 ++- utils/openImageModal.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 50d5425..3777225 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -142,7 +142,7 @@ module.exports = class General { if (hideNativeButtons) { for (let i = menu.length - 1; i >= 0; i -= 1) { const e = menu[i]; - if (Array.isArray(e.props.children) && e.props.children[0]) { + if (Array.isArray(e?.props?.children) && e?.props?.children[0]) { if (e.props.children[0].key === 'copy-image' || e.props.children[0].key === 'copy-native-link') { menu.splice(i, 1); } @@ -153,6 +153,7 @@ module.exports = class General { if (target.tagName === 'CANVAS') { menu.splice(menu.length - 1, 0, Button.renderSticker(stickerItems[0].id, settings)); } else { + console.log(target) const [ e, src ] = this.getImage(target); initButton(menu, { images: { diff --git a/utils/openImageModal.js b/utils/openImageModal.js index fdcf921..a3de89f 100644 --- a/utils/openImageModal.js +++ b/utils/openImageModal.js @@ -4,7 +4,7 @@ const { React, getModule, getModuleByDisplayName, i18n: { Messages } } = require const { openModal } = getModule([ 'openModal', 'openModalLazy' ], false); const ImageModal = getModuleByDisplayName('ImageModal', false); -const MaskedLink = getModuleByDisplayName('MaskedLink', false); +const Anchor = getModuleByDisplayName('Anchor', false); const { ModalRoot, ModalSize } = getModule([ 'ModalRoot' ], false); const classes = getModule([ 'modal', 'image' ], false); @@ -26,7 +26,7 @@ module.exports = ({ original, src, width, height, stickerAssets }) => src, height, width, - renderLinkComponent: (p) => React.createElement(MaskedLink, p), + renderLinkComponent: (p) => React.createElement(Anchor, p), original: original || src, stickerAssets }), From a3efc156549051308c0a615192ca019f8e0b07c4 Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 01:20:56 +0200 Subject: [PATCH 03/13] remove logging --- modules/Patcher/General.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 3777225..7053c2d 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -153,7 +153,6 @@ module.exports = class General { if (target.tagName === 'CANVAS') { menu.splice(menu.length - 1, 0, Button.renderSticker(stickerItems[0].id, settings)); } else { - console.log(target) const [ e, src ] = this.getImage(target); initButton(menu, { images: { From 5101f83415569f868d67526af643aabbf6939040 Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 02:32:56 +0200 Subject: [PATCH 04/13] fix guild image context menu --- modules/Patcher/General.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 7053c2d..7bf6087 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -33,7 +33,7 @@ module.exports = class General { UserGenericContextMenu: (...args) => this.contextMenuPatch.user.call(this, ...args, (r) => r[0].props.children), GroupDMUserContextMenu: this.contextMenuPatch.user, GroupDMContextMenu: this.contextMenuPatch.groupDM, - GuildContextMenu: this.contextMenuPatch.guild, + GuildContextMenuWrapper: this.contextMenuPatch.guild, GuildChannelListContextMenu: this.contextMenuPatch.guildChannelList, DeveloperContextMenu: this.contextMenuPatch.developer, NativeImageContextMenu: this.contextMenuPatch.image @@ -128,7 +128,15 @@ module.exports = class General { get contextMenuPatch () { function initButton (menu, args) { - menu.splice(menu.length - 1, 0, Button.render(args)); + if (!Array.isArray(menu)) { + const renderContextMenu = menu.type; + menu.type = (props) => { + const contextMenu = renderContextMenu(props); + contextMenu.props.children.splice(contextMenu.props.children.length - 1, 0, Button.render(args)) + return contextMenu + } + } + else menu.splice(menu.length - 1, 0, Button.render(args)); return menu; } @@ -214,7 +222,6 @@ module.exports = class General { webp: { src: ImageResolve.getGuildIconURL(params) }, gif: ImageResolve.isAnimatedIconHash(guild.icon) ? { src: ImageResolve.getGuildIconURL({ ...params, canAnimate: true }) } : null }; - if (images.webp.src) { initButton(res.props.children, { images, settings }); } @@ -261,7 +268,6 @@ module.exports = class General { height: 918 } }; - initButton(res.props.children, { images, settings }); } return res; From 13abef6695dcf2e13cbd9ece0ffd0f04c0203eb1 Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 03:03:48 +0200 Subject: [PATCH 05/13] avoid crash as I don't know how to fix it --- modules/Patcher/General.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 7bf6087..4438ad1 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -73,9 +73,8 @@ module.exports = class General { return (config) => { const menu = render(config); - const CMName = (menu?.type?.displayName) - ? menu.type.displayName - : menu.type(config).props.children.type.displayName; + console.log(config) + const CMName = menu?.type?.displayName if (CMName) { const moduleByDisplayName = getModuleByDisplayName(CMName, false); @@ -128,7 +127,7 @@ module.exports = class General { get contextMenuPatch () { function initButton (menu, args) { - if (!Array.isArray(menu)) { + if (!Array.isArray(menu)) { // if is guild context menu const renderContextMenu = menu.type; menu.type = (props) => { const contextMenu = renderContextMenu(props); From 85359ccc69f680de22c181d2c43095693b0793b3 Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:26:40 +0200 Subject: [PATCH 06/13] partially fix user context menus? --- modules/Patcher/General.js | 47 ++++++++++++++++++++++++++++---------- utils/inject2.js | 3 ++- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 4438ad1..2c4ffc4 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -15,6 +15,7 @@ module.exports = class General { constructor (settings) { this.settings = settings; this.uninjectIDs = []; + this.clickedUsers = []; this.modalIsOpen = false; } @@ -30,7 +31,7 @@ module.exports = class General { MessageContextMenu: this.contextMenuPatch.message, GuildChannelUserContextMenu: this.contextMenuPatch.user, DMUserContextMenu: this.contextMenuPatch.user, - UserGenericContextMenu: (...args) => this.contextMenuPatch.user.call(this, ...args, (r) => r[0].props.children), + AnalyticsContext: (...args) => this.contextMenuPatch.user.call(this, ...args, (r) => r[0].props.children), GroupDMUserContextMenu: this.contextMenuPatch.user, GroupDMContextMenu: this.contextMenuPatch.groupDM, GuildContextMenuWrapper: this.contextMenuPatch.guild, @@ -73,8 +74,29 @@ module.exports = class General { return (config) => { const menu = render(config); - console.log(config) - const CMName = menu?.type?.displayName + const CMName = menu?.type?.displayName; + + if (!CMName && menu?.props?.user) { + const renderContextMenu = menu.type; + console.log(menu) + menu.type = (props) => { + const contextMenu = renderContextMenu(props); + const renderMenu2 = contextMenu.props.children.type; + contextMenu.props.children.type = (props2) => { + const trueContextMenu = renderMenu2(props2); + + const displayName = trueContextMenu?.type?.displayName; + const moduleByDisplayName = getModuleByDisplayName(displayName, false); + if (moduleByDisplayName !== null) { + this.injectWithSettings(`${displayName}.default`, menus[displayName]); + } + + return trueContextMenu; + } + return contextMenu; + } + return menu; + } if (CMName) { const moduleByDisplayName = getModuleByDisplayName(CMName, false); @@ -127,12 +149,12 @@ module.exports = class General { get contextMenuPatch () { function initButton (menu, args) { - if (!Array.isArray(menu)) { // if is guild context menu + if (!Array.isArray(menu)) { const renderContextMenu = menu.type; menu.type = (props) => { const contextMenu = renderContextMenu(props); - contextMenu.props.children.splice(contextMenu.props.children.length - 1, 0, Button.render(args)) - return contextMenu + contextMenu.props.children.splice(contextMenu.props.children.length - 1, 0, Button.render(args)); + return contextMenu; } } else menu.splice(menu.length - 1, 0, Button.render(args)); @@ -177,7 +199,9 @@ module.exports = class General { return res; }, - user ([ { user, guildId } ], res, settings, getUserContext = (e) => e) { + user ([ { children } ], res, settings, getUserContext = (e) => e) { + if (!children?.props?.user) return children; + const { user, guildId } = children?.props; const { getGuild } = getModule([ 'getGuild' ], false); const guildMemberAvatarURLParams = { userId: user.id, guildId }; const guildMemberAvatars = Object.entries(user.guildMemberAvatars); @@ -203,11 +227,10 @@ module.exports = class General { }; if (user.discriminator !== '0000') { - const menu = findInReactTree(res, ({ props }) => props?.navId === 'user-context').props.children; - initButton(getUserContext(menu), { images, settings }); + initButton(children, { images, settings }); } - return res; + return children; }, guild ([ { guild } ], res, settings) { const params = { @@ -369,8 +392,8 @@ module.exports = class General { } injectWithSettings (funcPath, patch) { - const id = inject2(funcPath, (...args) => patch.call(this, ...args, this.settings)); - this.uninjectIDs.push(id); + const id = inject2(funcPath, (...args) => patch.call(this, ...args, this.settings), this.uninjectIDs); + if (!this.uninjectIDs.includes(id)) this.uninjectIDs.push(id); } getImage (target) { diff --git a/utils/inject2.js b/utils/inject2.js index 1fa52bd..d70b7e8 100644 --- a/utils/inject2.js +++ b/utils/inject2.js @@ -5,11 +5,12 @@ const { inject } = require('powercord/injector'); * @param {String|Object} funcPath (ex ModuleName.default) * @param {function} patch */ -module.exports = function inject2 (funcPath, patch) { +module.exports = function inject2 (funcPath, patch, listInjectID = null) { const path = funcPath.split('.'); const moduleName = path.shift(); const method = path.pop(); const injectId = `image-tools${moduleName.replace(/[A-Z]/g, (l) => `-${l.toLowerCase()}`)}`; + if (listInjectID?.includes(injectId)) return injectId; const module = getModule((m) => m?.default?.displayName === moduleName, false); const injectTo = getModulePath(); // eslint-disable-line no-use-before-define From bb7e145a5ff302ce89ab10e472de26fe2bcf49fc Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Tue, 6 Sep 2022 23:31:24 +0200 Subject: [PATCH 07/13] avoid crash --- modules/Patcher/General.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 2c4ffc4..d8cbd90 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -15,7 +15,7 @@ module.exports = class General { constructor (settings) { this.settings = settings; this.uninjectIDs = []; - this.clickedUsers = []; + this.usedMenus = []; this.modalIsOpen = false; } @@ -76,27 +76,29 @@ module.exports = class General { const menu = render(config); const CMName = menu?.type?.displayName; - if (!CMName && menu?.props?.user) { + if (!CMName && menu?.props?.user && !this.usedMenus.includes(menu?.props?.user?.id)) { const renderContextMenu = menu.type; - console.log(menu) menu.type = (props) => { const contextMenu = renderContextMenu(props); const renderMenu2 = contextMenu.props.children.type; - contextMenu.props.children.type = (props2) => { - const trueContextMenu = renderMenu2(props2); - const displayName = trueContextMenu?.type?.displayName; - const moduleByDisplayName = getModuleByDisplayName(displayName, false); - if (moduleByDisplayName !== null) { - this.injectWithSettings(`${displayName}.default`, menus[displayName]); + contextMenu.props.children.type = (props2) => { + const trueContextMenu = renderMenu2(props2); + + const displayName = trueContextMenu?.type?.displayName; + const moduleByDisplayName = getModuleByDisplayName(displayName, false); + if (moduleByDisplayName !== null) { + this.injectWithSettings(`${displayName}.default`, menus[displayName]); + } + + return trueContextMenu; } - return trueContextMenu; - } return contextMenu; } + return menu; - } + }; if (CMName) { const moduleByDisplayName = getModuleByDisplayName(CMName, false); @@ -117,6 +119,7 @@ module.exports = class General { } else if (module !== null) { menu.type = module.default; } + } if (!Object.keys(menus).length) { uninject(id); @@ -150,12 +153,14 @@ module.exports = class General { get contextMenuPatch () { function initButton (menu, args) { if (!Array.isArray(menu)) { + if (menu?.props?.user && this.usedMenus.filter(id => id === menu.props.user.id).length > 1) return menu; // for some reason, it has to be done twice in order for the context menu to appear. In some servers it does not appear at all, the reason is unknown for me, so this partially works. const renderContextMenu = menu.type; menu.type = (props) => { const contextMenu = renderContextMenu(props); contextMenu.props.children.splice(contextMenu.props.children.length - 1, 0, Button.render(args)); return contextMenu; } + if (menu?.props?.user) this.usedMenus.push(menu.props.user.id); } else menu.splice(menu.length - 1, 0, Button.render(args)); return menu; @@ -199,7 +204,7 @@ module.exports = class General { return res; }, - user ([ { children } ], res, settings, getUserContext = (e) => e) { + user ([ { children } ], res, settings) { if (!children?.props?.user) return children; const { user, guildId } = children?.props; const { getGuild } = getModule([ 'getGuild' ], false); @@ -227,7 +232,7 @@ module.exports = class General { }; if (user.discriminator !== '0000') { - initButton(children, { images, settings }); + initButton.call(this, children, { images, settings }); } return children; From 559f3b0e6573bfe5e6edd5ba568ba7e77862ed54 Mon Sep 17 00:00:00 2001 From: Xinos Date: Fri, 9 Sep 2022 18:59:30 +0700 Subject: [PATCH 08/13] use _.memorize instead of this.usedMenus --- modules/Patcher/General.js | 113 ++++++++++++++----------------------- 1 file changed, 43 insertions(+), 70 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index d8cbd90..911d456 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -15,7 +15,6 @@ module.exports = class General { constructor (settings) { this.settings = settings; this.uninjectIDs = []; - this.usedMenus = []; this.modalIsOpen = false; } @@ -29,10 +28,7 @@ module.exports = class General { this.injectToGetImageSrc('image-tools-media-proxy-sizes'); this.patchOpenContextMenuLazy('image-tools-open-context-menu-lazy', { MessageContextMenu: this.contextMenuPatch.message, - GuildChannelUserContextMenu: this.contextMenuPatch.user, - DMUserContextMenu: this.contextMenuPatch.user, - AnalyticsContext: (...args) => this.contextMenuPatch.user.call(this, ...args, (r) => r[0].props.children), - GroupDMUserContextMenu: this.contextMenuPatch.user, + AnalyticsContext: this.contextMenuPatch.user, GroupDMContextMenu: this.contextMenuPatch.groupDM, GuildContextMenuWrapper: this.contextMenuPatch.guild, GuildChannelListContextMenu: this.contextMenuPatch.guildChannelList, @@ -68,59 +64,30 @@ module.exports = class General { } patchOpenContextMenuLazy (id, menus) { + const injectWithSettingsBind = this.injectWithSettings.bind(this); + const memorizeRender = window._.memoize((render, patch) => (...renderArgs) => ( + patch(render(...renderArgs)) + )); + inject(id, getModule([ 'openContextMenuLazy' ], false), 'openContextMenuLazy', ([ event, lazyRender, params ]) => { const wrapLazyRender = async () => { const render = await lazyRender(event); return (config) => { const menu = render(config); - const CMName = menu?.type?.displayName; - - if (!CMName && menu?.props?.user && !this.usedMenus.includes(menu?.props?.user?.id)) { - const renderContextMenu = menu.type; - menu.type = (props) => { - const contextMenu = renderContextMenu(props); - const renderMenu2 = contextMenu.props.children.type; - - contextMenu.props.children.type = (props2) => { - const trueContextMenu = renderMenu2(props2); - - const displayName = trueContextMenu?.type?.displayName; - const moduleByDisplayName = getModuleByDisplayName(displayName, false); - if (moduleByDisplayName !== null) { - this.injectWithSettings(`${displayName}.default`, menus[displayName]); - } - - return trueContextMenu; - } - - return contextMenu; - } - - return menu; - }; - - if (CMName) { - const moduleByDisplayName = getModuleByDisplayName(CMName, false); - const module = getModule((m) => m.default === menu.type || m.__powercordOriginal_default === menu.type, false); - - if (CMName in menus) { - if (moduleByDisplayName !== null) { - this.injectWithSettings(`${CMName}.default`, menus[CMName]); - } else if (module !== null) { - wrapAndInjectWithSettings.call(this, CMName, menus[CMName], module); - } - - delete menus[CMName]; - } - - if (moduleByDisplayName !== null) { - menu.type = moduleByDisplayName; - } else if (module !== null) { - menu.type = module.default; - } + if (menu?.type?.displayName) { + patchMenu(menu?.type?.displayName, menu); + } else { + menu.type = memorizeRender(menu.type, (res) => { + res.props.children.type = memorizeRender(res.props.children.type, (res2) => { + patchMenu(res2?.type?.displayName, menu); + return res2; + }); + return res; + }); } + if (!Object.keys(menus).length) { uninject(id); } @@ -135,40 +102,43 @@ module.exports = class General { this.uninjectIDs.push(id); - function wrapAndInjectWithSettings (CMName, patch, module) { - const injectId = `image-tools${CMName.replace(/[A-Z]/g, (l) => `-${l.toLowerCase()}`)}`; - const memorizeRender = window._.memoize((render) => (...renderArgs) => ( - patch.call(this, renderArgs, render(...renderArgs), this.settings) - )); + function patchMenu (name, menu) { + const moduleByDisplayName = getModuleByDisplayName(name, false); + const module = getModule((m) => m.default === menu.type || m.__powercordOriginal_default === menu.type, false); - inject(injectId, module, 'default', (args, res) => { - res.props.children.type = memorizeRender(res.props.children.type); - return res; - }); + if (name && name in menus) { + if (moduleByDisplayName !== null) { + injectWithSettingsBind(`${name}.default`, menus[name]); + } + delete menus[name]; - this.uninjectIDs.push(injectId); + if (moduleByDisplayName !== null) { + menu.type = moduleByDisplayName; + } else if (module !== null) { + menu.type = module.default; + } + } } } get contextMenuPatch () { function initButton (menu, args) { - if (!Array.isArray(menu)) { - if (menu?.props?.user && this.usedMenus.filter(id => id === menu.props.user.id).length > 1) return menu; // for some reason, it has to be done twice in order for the context menu to appear. In some servers it does not appear at all, the reason is unknown for me, so this partially works. + if (Array.isArray(menu)) { + menu.splice(menu.length - 1, 0, Button.render(args)); + } else { const renderContextMenu = menu.type; menu.type = (props) => { const contextMenu = renderContextMenu(props); contextMenu.props.children.splice(contextMenu.props.children.length - 1, 0, Button.render(args)); return contextMenu; - } - if (menu?.props?.user) this.usedMenus.push(menu.props.user.id); + }; } - else menu.splice(menu.length - 1, 0, Button.render(args)); return menu; } return { message ([ { target, message: { content, stickerItems } } ], res, settings) { - if ((target.tagName === 'IMG') || (target.getAttribute("data-role") === 'img') || (target.getAttribute("data-type") === 'sticker' && stickerItems.length)) { + if ((target.tagName === 'IMG') || (target.getAttribute('data-role') === 'img') || (target.getAttribute('data-type') === 'sticker' && stickerItems.length)) { const { width, height } = target; const menu = res.props.children; const hideNativeButtons = settings.get('hideNativeButtons', true); @@ -205,8 +175,11 @@ module.exports = class General { }, user ([ { children } ], res, settings) { - if (!children?.props?.user) return children; - const { user, guildId } = children?.props; + if (!children?.props?.user) { + return children; + } + + const { user, guildId } = children.props; const { getGuild } = getModule([ 'getGuild' ], false); const guildMemberAvatarURLParams = { userId: user.id, guildId }; const guildMemberAvatars = Object.entries(user.guildMemberAvatars); @@ -397,8 +370,8 @@ module.exports = class General { } injectWithSettings (funcPath, patch) { - const id = inject2(funcPath, (...args) => patch.call(this, ...args, this.settings), this.uninjectIDs); - if (!this.uninjectIDs.includes(id)) this.uninjectIDs.push(id); + const id = inject2(funcPath, (...args) => patch.call(this, ...args, this.settings)); + this.uninjectIDs.push(id); } getImage (target) { From 47afe158a2ac8f6fa2b90a84fff385bf375803ff Mon Sep 17 00:00:00 2001 From: Xinos Date: Fri, 9 Sep 2022 19:33:10 +0700 Subject: [PATCH 09/13] use memorizeRender for initButton --- modules/Patcher/General.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 911d456..6840717 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -8,6 +8,9 @@ const LensSettings = require('../../tools/Lens/Settings.jsx'); const inject2 = require('../../utils/inject2.js'); const { default: ImageResolve } = getModule([ 'getUserAvatarURL' ], false); +const initMemorizeRender = () => window._.memoize((render, patch) => (...renderArgs) => ( + patch(render(...renderArgs)) +)); /* eslint-disable no-use-before-define, object-property-newline,no-undefined */ // noinspection JSUnusedGlobalSymbols @@ -65,9 +68,7 @@ module.exports = class General { patchOpenContextMenuLazy (id, menus) { const injectWithSettingsBind = this.injectWithSettings.bind(this); - const memorizeRender = window._.memoize((render, patch) => (...renderArgs) => ( - patch(render(...renderArgs)) - )); + const memorizeRender = initMemorizeRender(); inject(id, getModule([ 'openContextMenuLazy' ], false), 'openContextMenuLazy', ([ event, lazyRender, params ]) => { const wrapLazyRender = async () => { @@ -122,16 +123,19 @@ module.exports = class General { } get contextMenuPatch () { + const memorizeRender = initMemorizeRender(); + function initButton (menu, args) { + const btn = Button.render(args); + memorizeRender.cache.clear(); + if (Array.isArray(menu)) { - menu.splice(menu.length - 1, 0, Button.render(args)); + menu.splice(menu.length - 1, 0, btn); } else { - const renderContextMenu = menu.type; - menu.type = (props) => { - const contextMenu = renderContextMenu(props); - contextMenu.props.children.splice(contextMenu.props.children.length - 1, 0, Button.render(args)); - return contextMenu; - }; + menu.type = memorizeRender(menu.type, (res) => { + res.props.children.splice(res.props.children.length - 1, 0, btn); + return res; + }); } return menu; } From e5930f9a19043a04349389f4f31afb8df2ced170 Mon Sep 17 00:00:00 2001 From: Xinos Date: Fri, 9 Sep 2022 19:49:31 +0700 Subject: [PATCH 10/13] cleanup --- modules/Patcher/General.js | 13 +++---------- utils/inject2.js | 7 +++---- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index 6840717..e67b02b 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -78,11 +78,11 @@ module.exports = class General { const menu = render(config); if (menu?.type?.displayName) { - patchMenu(menu?.type?.displayName, menu); + patchMenu(menu.type.displayName); } else { menu.type = memorizeRender(menu.type, (res) => { res.props.children.type = memorizeRender(res.props.children.type, (res2) => { - patchMenu(res2?.type?.displayName, menu); + patchMenu(res2?.type?.displayName); return res2; }); return res; @@ -103,21 +103,14 @@ module.exports = class General { this.uninjectIDs.push(id); - function patchMenu (name, menu) { + function patchMenu (name) { const moduleByDisplayName = getModuleByDisplayName(name, false); - const module = getModule((m) => m.default === menu.type || m.__powercordOriginal_default === menu.type, false); if (name && name in menus) { if (moduleByDisplayName !== null) { injectWithSettingsBind(`${name}.default`, menus[name]); } delete menus[name]; - - if (moduleByDisplayName !== null) { - menu.type = moduleByDisplayName; - } else if (module !== null) { - menu.type = module.default; - } } } } diff --git a/utils/inject2.js b/utils/inject2.js index d70b7e8..1ff39ab 100644 --- a/utils/inject2.js +++ b/utils/inject2.js @@ -5,21 +5,20 @@ const { inject } = require('powercord/injector'); * @param {String|Object} funcPath (ex ModuleName.default) * @param {function} patch */ -module.exports = function inject2 (funcPath, patch, listInjectID = null) { +module.exports = function inject2 (funcPath, patch) { const path = funcPath.split('.'); const moduleName = path.shift(); const method = path.pop(); const injectId = `image-tools${moduleName.replace(/[A-Z]/g, (l) => `-${l.toLowerCase()}`)}`; - if (listInjectID?.includes(injectId)) return injectId; const module = getModule((m) => m?.default?.displayName === moduleName, false); const injectTo = getModulePath(); // eslint-disable-line no-use-before-define if (module === null) { const id = 'image-tools'; const { plugins } = powercord.pluginManager; - const out = (plugins.has(id)) ? plugins.get(id) : global.console; + const log = (plugins.has(id)) ? plugins.get(id) : global.console; - out.error(`Module ${moduleName} not found`); + log.error(`Module ${moduleName} not found`); return; } From 2e589aa9dea60839c654016fa4abd2ccc13ed040 Mon Sep 17 00:00:00 2001 From: k2helix <49949593+k2helix@users.noreply.github.com> Date: Fri, 9 Sep 2022 18:50:41 +0200 Subject: [PATCH 11/13] avoid crash if guild has Apps context menu --- modules/Patcher/General.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index e67b02b..fb0545d 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -80,6 +80,10 @@ module.exports = class General { if (menu?.type?.displayName) { patchMenu(menu.type.displayName); } else { + const { getGuild } = getModule([ 'getGuild' ], false); + if (getGuild(menu?.props?.guildId).applicationCommandCounts[2]) { + return menu; // avoid infinite loop if there are context menu commands in the guild + } menu.type = memorizeRender(menu.type, (res) => { res.props.children.type = memorizeRender(res.props.children.type, (res2) => { patchMenu(res2?.type?.displayName); From 9f6b1db2b906b870768c3203701cee5a2033bbc5 Mon Sep 17 00:00:00 2001 From: Xinos Date: Sat, 10 Sep 2022 00:08:11 +0700 Subject: [PATCH 12/13] avoid crash if guild has Apps context menu 2 --- modules/Patcher/General.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index fb0545d..ad73c3b 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -80,10 +80,6 @@ module.exports = class General { if (menu?.type?.displayName) { patchMenu(menu.type.displayName); } else { - const { getGuild } = getModule([ 'getGuild' ], false); - if (getGuild(menu?.props?.guildId).applicationCommandCounts[2]) { - return menu; // avoid infinite loop if there are context menu commands in the guild - } menu.type = memorizeRender(menu.type, (res) => { res.props.children.type = memorizeRender(res.props.children.type, (res2) => { patchMenu(res2?.type?.displayName); @@ -186,6 +182,14 @@ module.exports = class General { const guildMemberAvatars = Object.entries(user.guildMemberAvatars); const currentGuildId = guildMemberAvatars.findIndex(([ id ]) => id === guildId); const isCurrentGuild = currentGuildId !== -1; + + // @TODO (temporarily ?) + // avoid infinite loop if there are context menu commands in the guild + if (guildId) { + if (2 in getGuild(guildId).applicationCommandCounts) { + return children; + } + } if (isCurrentGuild) { guildMemberAvatars.splice(0, 0, guildMemberAvatars.splice(currentGuildId, 1)[0]); } From e4ec378212602d3e890c98022ad9aa7bc1316390 Mon Sep 17 00:00:00 2001 From: Xinos Date: Sat, 10 Sep 2022 01:04:46 +0700 Subject: [PATCH 13/13] discord no longer hovering over UserBanner --- modules/Patcher/General.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/modules/Patcher/General.js b/modules/Patcher/General.js index ad73c3b..8f255a2 100644 --- a/modules/Patcher/General.js +++ b/modules/Patcher/General.js @@ -26,7 +26,6 @@ module.exports = class General { this.isModalOpen = false; return this.overlayCallback(...args, () => this.isModalOpen = true); }); - this.injectWithSettings('UserBanner.default', this.initNewContextMenu.userBanner); this.injectWithSettings('CustomStatus.default', this.initNewContextMenu.customStatus); this.injectToGetImageSrc('image-tools-media-proxy-sizes'); this.patchOpenContextMenuLazy('image-tools-open-context-menu-lazy', { @@ -320,23 +319,6 @@ module.exports = class General { } return { - userBanner ([ { user } ], res, settings) { - if (!res.props.onContextMenu) { // @todo else ? - if (user.banner) { - const size = { width: 2048, - height: 918 }; - const images = { - png: { src: this.fixUrlSize(ImageResolve.getUserBannerURL(user, false)).replace('.webp', '.png'), ...size }, - webp: { src: this.fixUrlSize(ImageResolve.getUserBannerURL(user, false)), ...size }, - gif: ImageResolve.hasAnimatedUserBanner(user) ? { src: this.fixUrlSize(ImageResolve.getUserBannerURL(user, true)), ...size } : null - }; - - res.props.onContextMenu = (e) => genContextMenu(e, 'user-banner', { images, settings }); - } - } - return res; - }, - customStatus (args, res, settings) { if (!res.props.onContextMenu) { // @todo else ? res.props.onContextMenu = (event) => {