LazyComponents: Allow accessing inner; Improve typings
This commit is contained in:
parent
5d290ecd35
commit
08f1b6a3c9
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
import { SYM_PROXY_INNER_GET, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
||||||
import * as Webpack from "@webpack";
|
import * as Webpack from "@webpack";
|
||||||
|
@ -64,8 +65,8 @@ async function runReporter() {
|
||||||
result = findResult[SYM_PROXY_INNER_VALUE];
|
result = findResult[SYM_PROXY_INNER_VALUE];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findResult.$$vencordInner != null) {
|
if (findResult[SYM_LAZY_COMPONENT_INNER] != null) {
|
||||||
result = findResult.$$vencordInner();
|
result = findResult[SYM_LAZY_COMPONENT_INNER]();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
import { LazyComponentType } from "@utils/lazyReact";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByProps, findComponentByCode } from "@webpack";
|
import { findByProps, findComponentByCode } from "@webpack";
|
||||||
|
@ -56,7 +57,7 @@ const PermissionUtil = findByProps("computePermissions", "canEveryoneRole") as {
|
||||||
computePermissions({ ...args }): bigint;
|
computePermissions({ ...args }): bigint;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Tag = findComponentByCode(".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP_OFFICIAL,") as React.ComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record<string, number>; };
|
const Tag = findComponentByCode(".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP_OFFICIAL,") as LazyComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record<string, number>; };
|
||||||
|
|
||||||
const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot();
|
const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot();
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
import { makeLazy } from "./lazy";
|
import { makeLazy } from "./lazy";
|
||||||
|
|
||||||
|
export type LazyComponentType<T extends object = {}> = React.ComponentType<T> & Record<PropertyKey, any>;
|
||||||
|
|
||||||
|
export const SYM_LAZY_COMPONENT_INNER = Symbol.for("vencord.lazyComponent.inner");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A lazy component. The factory method is called on first render.
|
* A lazy component. The factory method is called on first render.
|
||||||
*
|
*
|
||||||
|
@ -13,10 +17,10 @@ import { makeLazy } from "./lazy";
|
||||||
* @param attempts How many times to try to get the component before giving up
|
* @param attempts How many times to try to get the component before giving up
|
||||||
* @returns Result of factory function
|
* @returns Result of factory function
|
||||||
*/
|
*/
|
||||||
export function LazyComponent<T extends object = any>(factory: () => React.ComponentType<T>, attempts = 5) {
|
export function LazyComponent<T extends object = {}>(factory: () => LazyComponentType<T>, attempts = 5) {
|
||||||
const get = makeLazy(factory, attempts, { isIndirect: true });
|
const get = makeLazy(factory, attempts, { isIndirect: true });
|
||||||
|
|
||||||
let InnerComponent = null as React.ComponentType<T> | null;
|
let InnerComponent = null as LazyComponentType<T> | null;
|
||||||
|
|
||||||
let lazyFailedLogged = false;
|
let lazyFailedLogged = false;
|
||||||
const LazyComponent = (props: T) => {
|
const LazyComponent = (props: T) => {
|
||||||
|
@ -39,5 +43,7 @@ export function LazyComponent<T extends object = any>(factory: () => React.Compo
|
||||||
return InnerComponent && <InnerComponent {...props} />;
|
return InnerComponent && <InnerComponent {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
return LazyComponent as React.ComponentType<T>;
|
LazyComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;
|
||||||
|
|
||||||
|
return LazyComponent as LazyComponentType<T>;
|
||||||
}
|
}
|
||||||
|
|
2
src/webpack/common/types/menu.d.ts
vendored
2
src/webpack/common/types/menu.d.ts
vendored
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
import type { ComponentType, CSSProperties, MouseEvent, PropsWithChildren, ReactNode, UIEvent } from "react";
|
import type { ComponentType, CSSProperties, MouseEvent, PropsWithChildren, ReactNode, UIEvent } from "react";
|
||||||
|
|
||||||
type RC<C> = ComponentType<PropsWithChildren<C & Record<string, any>>>;
|
type RC<C> = ComponentType<PropsWithChildren<C & Record<PropertyKey, any>>>;
|
||||||
|
|
||||||
export interface Menu {
|
export interface Menu {
|
||||||
Menu: RC<{
|
Menu: RC<{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { makeLazy, proxyLazy } from "@utils/lazy";
|
import { makeLazy, proxyLazy } from "@utils/lazy";
|
||||||
import { LazyComponent } from "@utils/lazyReact";
|
import { LazyComponent, LazyComponentType, SYM_LAZY_COMPONENT_INNER } from "@utils/lazyReact";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { canonicalizeMatch } from "@utils/patches";
|
import { canonicalizeMatch } from "@utils/patches";
|
||||||
import { ProxyInner, proxyInner, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
import { ProxyInner, proxyInner, SYM_PROXY_INNER_VALUE } from "@utils/proxyInner";
|
||||||
|
@ -196,13 +196,13 @@ export function find<T = AnyObject>(filter: FilterFn, callback: (mod: any) => an
|
||||||
* @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component
|
* @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component
|
||||||
* @returns The component if found, or a noop component
|
* @returns The component if found, or a noop component
|
||||||
*/
|
*/
|
||||||
export function findComponent<T extends object = any>(filter: FilterFn, parse: (component: any) => React.ComponentType<T> = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) {
|
export function findComponent<T extends object = {}>(filter: FilterFn, parse: (component: any) => LazyComponentType<T> = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) {
|
||||||
if (typeof filter !== "function")
|
if (typeof filter !== "function")
|
||||||
throw new Error("Invalid filter. Expected a function got " + typeof filter);
|
throw new Error("Invalid filter. Expected a function got " + typeof filter);
|
||||||
if (typeof parse !== "function")
|
if (typeof parse !== "function")
|
||||||
throw new Error("Invalid component parse. Expected a function got " + typeof parse);
|
throw new Error("Invalid component parse. Expected a function got " + typeof parse);
|
||||||
|
|
||||||
let InnerComponent = null as React.ComponentType<T> | null;
|
let InnerComponent = null as LazyComponentType<T> | null;
|
||||||
|
|
||||||
let findFailedLogged = false;
|
let findFailedLogged = false;
|
||||||
const WrapperComponent = (props: T) => {
|
const WrapperComponent = (props: T) => {
|
||||||
|
@ -214,23 +214,21 @@ export function findComponent<T extends object = any>(filter: FilterFn, parse: (
|
||||||
return InnerComponent && <InnerComponent {...props} />;
|
return InnerComponent && <InnerComponent {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;
|
||||||
|
|
||||||
waitFor(filter, (v: any) => {
|
waitFor(filter, (v: any) => {
|
||||||
const parsedComponent = parse(v);
|
const parsedComponent = parse(v);
|
||||||
InnerComponent = parsedComponent;
|
InnerComponent = parsedComponent;
|
||||||
Object.assign(WrapperComponent, parsedComponent);
|
Object.assign(WrapperComponent, parsedComponent);
|
||||||
}, { isIndirect: true });
|
}, { isIndirect: true });
|
||||||
|
|
||||||
if (IS_REPORTER) {
|
if (IS_REPORTER && !isIndirect) {
|
||||||
WrapperComponent.$$vencordInner = () => InnerComponent;
|
|
||||||
|
|
||||||
if (!isIndirect) {
|
|
||||||
webpackSearchHistory.push(["findComponent", [WrapperComponent, filter]]);
|
webpackSearchHistory.push(["findComponent", [WrapperComponent, filter]]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (InnerComponent !== null) return InnerComponent;
|
if (InnerComponent !== null) return InnerComponent;
|
||||||
|
|
||||||
return WrapperComponent as React.ComponentType<T>;
|
return WrapperComponent as LazyComponentType<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -243,13 +241,13 @@ export function findComponent<T extends object = any>(filter: FilterFn, parse: (
|
||||||
* @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component
|
* @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component
|
||||||
* @returns The component if found, or a noop component
|
* @returns The component if found, or a noop component
|
||||||
*/
|
*/
|
||||||
export function findExportedComponent<T extends object = any>(...props: string[] | [...string[], (component: any) => React.ComponentType<T>]) {
|
export function findExportedComponent<T extends object = {}>(...props: string[] | [...string[], (component: any) => LazyComponentType<T>]) {
|
||||||
const parse = (typeof props.at(-1) === "function" ? props.pop() : m => m) as (component: any) => React.ComponentType<T>;
|
const parse = (typeof props.at(-1) === "function" ? props.pop() : m => m) as (component: any) => LazyComponentType<T>;
|
||||||
const newProps = props as string[];
|
const newProps = props as string[];
|
||||||
|
|
||||||
const filter = filters.byProps(...newProps);
|
const filter = filters.byProps(...newProps);
|
||||||
|
|
||||||
let InnerComponent = null as React.ComponentType<T> | null;
|
let InnerComponent = null as LazyComponentType<T> | null;
|
||||||
|
|
||||||
let findFailedLogged = false;
|
let findFailedLogged = false;
|
||||||
const WrapperComponent = (props: T) => {
|
const WrapperComponent = (props: T) => {
|
||||||
|
@ -261,6 +259,7 @@ export function findExportedComponent<T extends object = any>(...props: string[]
|
||||||
return InnerComponent && <InnerComponent {...props} />;
|
return InnerComponent && <InnerComponent {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent;
|
||||||
|
|
||||||
waitFor(filter, (v: any) => {
|
waitFor(filter, (v: any) => {
|
||||||
const parsedComponent = parse(v[newProps[0]]);
|
const parsedComponent = parse(v[newProps[0]]);
|
||||||
|
@ -269,13 +268,12 @@ export function findExportedComponent<T extends object = any>(...props: string[]
|
||||||
}, { isIndirect: true });
|
}, { isIndirect: true });
|
||||||
|
|
||||||
if (IS_REPORTER) {
|
if (IS_REPORTER) {
|
||||||
WrapperComponent.$$vencordInner = () => InnerComponent;
|
|
||||||
webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]);
|
webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InnerComponent !== null) return InnerComponent;
|
if (InnerComponent !== null) return InnerComponent;
|
||||||
|
|
||||||
return WrapperComponent as React.ComponentType<T>;
|
return WrapperComponent as LazyComponentType<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -288,8 +286,8 @@ export function findExportedComponent<T extends object = any>(...props: string[]
|
||||||
* @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component
|
* @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component
|
||||||
* @returns The component if found, or a noop component
|
* @returns The component if found, or a noop component
|
||||||
*/
|
*/
|
||||||
export function findComponentByCode<T extends object = any>(...code: string[] | [...string[], (component: any) => React.ComponentType<T>]) {
|
export function findComponentByCode<T extends object = {}>(...code: string[] | [...string[], (component: any) => LazyComponentType<T>]) {
|
||||||
const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: any) => React.ComponentType<T>;
|
const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: any) => LazyComponentType<T>;
|
||||||
const newCode = code as string[];
|
const newCode = code as string[];
|
||||||
|
|
||||||
const ComponentResult = findComponent<T>(filters.componentByCode(...newCode), parse, { isIndirect: true });
|
const ComponentResult = findComponent<T>(filters.componentByCode(...newCode), parse, { isIndirect: true });
|
||||||
|
@ -518,7 +516,7 @@ export function webpackDependantLazy<T = AnyObject>(factory: () => T, attempts?:
|
||||||
* @param attempts How many times to try to get the component before giving up
|
* @param attempts How many times to try to get the component before giving up
|
||||||
* @returns Result of factory function
|
* @returns Result of factory function
|
||||||
*/
|
*/
|
||||||
export function webpackDependantLazyComponent<T extends object = any>(factory: () => any, attempts?: number) {
|
export function webpackDependantLazyComponent<T extends object = {}>(factory: () => any, attempts?: number) {
|
||||||
if (IS_REPORTER) webpackSearchHistory.push(["webpackDependantLazyComponent", [factory]]);
|
if (IS_REPORTER) webpackSearchHistory.push(["webpackDependantLazyComponent", [factory]]);
|
||||||
|
|
||||||
return LazyComponent<T>(factory, attempts);
|
return LazyComponent<T>(factory, attempts);
|
||||||
|
|
Loading…
Reference in a new issue