From 296336535f6d23c586c7e83edf0420b58cbf011a Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 14 Oct 2022 21:34:35 +0200 Subject: [PATCH] Fix modals, add wp.mapMangledModule --- src/Vencord.ts | 1 + src/plugins/petpet.ts | 6 +++--- src/utils/index.ts | 11 ++++++++++ src/utils/misc.tsx | 17 ++++------------ src/utils/modal.tsx | 25 +++++++++++------------ src/utils/proxyLazy.ts | 25 +++++++++++++++++++++++ src/webpack/webpack.ts | 46 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 102 insertions(+), 29 deletions(-) create mode 100644 src/utils/index.ts create mode 100644 src/utils/proxyLazy.ts diff --git a/src/Vencord.ts b/src/Vencord.ts index 9a0873e0c..48006210b 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -3,6 +3,7 @@ export * as Webpack from "./webpack"; export * as Api from "./api"; export * as Updater from "./utils/updater"; export * as QuickCss from "./utils/quickCss"; +export * as Util from "./utils"; import { popNotice, showNotice } from "./api/Notices"; import { Settings, PlainSettings } from "./api/settings"; diff --git a/src/plugins/petpet.ts b/src/plugins/petpet.ts index 0c4c29b18..9d25a2202 100644 --- a/src/plugins/petpet.ts +++ b/src/plugins/petpet.ts @@ -1,7 +1,7 @@ import { ApplicationCommandOptionType, findOption, ApplicationCommandInputType, Argument, CommandContext } from "../api/Commands"; import { Devs } from "../utils/constants"; import definePlugin from "../utils/types"; -import { lazy, lazyWebpack } from "../utils/misc"; +import { makeLazy, lazyWebpack } from "../utils/misc"; import { filters } from "../webpack"; const DRAFT_TYPE = 0; @@ -12,9 +12,9 @@ const FRAMES = 10; // https://github.com/mattdesl/gifenc // this lib is way better than gif.js and all other libs, they're all so terrible but this one is nice // @ts-ignore ts mad -const getGifEncoder = lazy(() => import("https://unpkg.com/gifenc@1.0.3/dist/gifenc.esm.js")); +const getGifEncoder = makeLazy(() => import("https://unpkg.com/gifenc@1.0.3/dist/gifenc.esm.js")); -const getFrames = lazy(() => Promise.all( +const getFrames = makeLazy(() => Promise.all( Array.from( { length: FRAMES }, (_, i) => loadImage(`https://raw.githubusercontent.com/VenPlugs/petpet/main/frames/pet${i}.gif`) diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 000000000..c5f4283d6 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,11 @@ +export * from "./ChangeList"; +export * from "./debounce"; +export * from "./misc"; +export * from "./proxyLazy"; + +export { default as IpcEvents } from "./IpcEvents"; +export { default as Logger } from "./logger"; + +export * as Constants from "./constants"; +export * as Discord from "./discord"; +export * as Modals from "./modal"; diff --git a/src/utils/misc.tsx b/src/utils/misc.tsx index b646ec1db..f6ea36cd5 100644 --- a/src/utils/misc.tsx +++ b/src/utils/misc.tsx @@ -1,15 +1,17 @@ import { FilterFn, find } from "../webpack"; import { React } from "../webpack/common"; +import { proxyLazy } from "./proxyLazy"; /** * Makes a lazy function. On first call, the value is computed. * On subsequent calls, the same computed value will be returned * @param factory Factory function */ -export function lazy(factory: () => T): () => T { +export function makeLazy(factory: () => T): () => T { let cache: T; return () => cache ?? (cache = factory()); } +export const lazy = makeLazy; /** * Do a lazy webpack search. Searches the module on first property access @@ -17,18 +19,7 @@ export function lazy(factory: () => T): () => T { * @returns A proxy to the webpack module. Not all traps are implemented, may produce unexpected results. */ export function lazyWebpack(filter: FilterFn): T { - const getMod = lazy(() => find(filter)); - - return new Proxy(() => null, { - get: (_, prop) => getMod()[prop], - set: (_, prop, value) => getMod()[prop] = value, - has: (_, prop) => prop in getMod(), - apply: (_, $this, args) => (getMod() as Function).apply($this, args), - ownKeys: () => Reflect.ownKeys(getMod()), - construct: (_, args, newTarget) => Reflect.construct(getMod(), args, newTarget), - deleteProperty: (_, prop) => delete getMod()[prop], - defineProperty: (_, property, attributes) => !!Object.defineProperty(getMod(), property, attributes) - }) as any as T; + return proxyLazy(() => find(filter)); } /** diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index b8e647cfb..9e5785de9 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -1,13 +1,12 @@ -// TODO: fix +import { filters } from "../webpack"; +import { lazyWebpack } from "./misc"; +import { mapMangledModuleLazy } from "../webpack/webpack"; -import Components from "discord-types/components"; -import { waitFor } from "../webpack"; - -export let Modal: Components.Modal; -export let modals: any; - -waitFor("openModalLazy", m => modals = m); -waitFor("ModalRoot", m => Modal = m); +const ModalRoot = lazyWebpack(filters.byCode("headerIdIsManaged:")); +const Modals = mapMangledModuleLazy("onCloseRequest:null!=", { + openModal: filters.byCode("onCloseRequest:null!="), + closeModal: filters.byCode("onCloseCallback&&") +}); let modalId = 1337; @@ -18,10 +17,10 @@ let modalId = 1337; */ export function openModal(Component: React.ComponentType, modalProps: Record) { let key = `Vencord${modalId++}`; - modals.openModal(props => ( - + Modals.openModal(props => ( + - + ), { modalKey: key }); return key; @@ -32,5 +31,5 @@ export function openModal(Component: React.ComponentType, modalProps: Record findByProps("blah"))); console.log(mod.blah); + */ +export function proxyLazy(factory: () => T): T { + const lazy = makeLazy(factory); + + return new Proxy(() => null, { + get: (_, prop) => lazy()[prop], + set: (_, prop, value) => lazy()[prop] = value, + has: (_, prop) => prop in lazy(), + apply: (_, $this, args) => (lazy() as Function).apply($this, args), + ownKeys: () => Reflect.ownKeys(lazy() as object), + construct: (_, args, newTarget) => Reflect.construct(lazy() as Function, args, newTarget), + deleteProperty: (_, prop) => delete lazy()[prop], + defineProperty: (_, property, attributes) => !!Object.defineProperty(lazy(), property, attributes) + }) as any as T; +} diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index ca987d0da..b8ccca90b 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -1,4 +1,5 @@ import type { WebpackInstance } from "discord-types/other"; +import { proxyLazy } from "../utils/proxyLazy"; export let _resolveReady: () => void; /** @@ -92,6 +93,51 @@ export function findAll(filter: FilterFn, getDefault = true) { return ret; } +/** + * Finds a mangled module by the provided code "code" (must be unique and can be anywhere in the module) + * then maps it into an easily usable module via the specified mappers + * @param code Code snippet + * @param mappers Mappers to create the non mangled exports + * @returns Unmangled exports as specified in mappers + * + * @example mapMangledModule("headerIdIsManaged:", { + * openModal: filters.byCode("headerIdIsManaged:"), + * closeModal: filters.byCode("key==") + * }) + */ +export function mapMangledModule(code: string, mappers: Record): Record { + const exports = {} as Record; + + // search every factory function + for (const id in wreq.m) { + const src = wreq.m[id].toString() as string; + if (src.includes(code)) { + const mod = wreq(id as any as number); + outer: + for (const key in mod) { + const member = mod[key]; + for (const newName in mappers) { + // if the current mapper matches this module + if (mappers[newName](member)) { + exports[newName] = member; + continue outer; + } + } + } + break; + } + } + + return exports; +} + +/** + * Same as {@link mapMangledModule} but lazy + */ +export function mapMangledModuleLazy(code: string, mappers: Record): Record { + return proxyLazy(() => mapMangledModule(code, mappers)); +} + export function findByProps(...props: string[]) { return find(filters.byProps(props)); }