better types? no ts-ignore, also filters.componentByCode is recursive now

This commit is contained in:
Nuckyz 2024-05-25 23:51:59 -03:00
parent 8eb4eab2b0
commit 999d6c812f
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
6 changed files with 54 additions and 40 deletions

View file

@ -1,6 +1,9 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"ignorePatterns": ["dist", "browser"],
"plugins": [
"@typescript-eslint",
@ -62,7 +65,14 @@
"no-constant-condition": ["error", { "checkLoops": false }],
"no-duplicate-imports": "error",
"no-extra-semi": "error",
"dot-notation": "error",
"dot-notation": "off",
"@typescript-eslint/dot-notation": [
"error",
{
"allowPrivateClassPropertyAccess": true,
"allowProtectedClassPropertyAccess": true
}
],
"no-useless-escape": [
"error",
{

View file

@ -289,10 +289,8 @@ async function runtime(token: string) {
});
// Monkey patch Logger to not log with custom css
// @ts-ignore
const originalLog = Vencord.Util.Logger.prototype._log;
// @ts-ignore
Vencord.Util.Logger.prototype._log = function (level, levelColor, args) {
const originalLog = Vencord.Util.Logger.prototype["_log"];
Vencord.Util.Logger.prototype["_log"] = function (level, levelColor, args) {
if (level === "warn" || level === "error")
return console[level]("[Vencord]", this.name + ":", ...args);

View file

@ -212,10 +212,9 @@ function computeWidthAndHeight(width: number, height: number) {
function withEmbeddedBy(message: Message, embeddedBy: string[]) {
return new Proxy(message, {
get(_, prop) {
get(target, prop, receiver) {
if (prop === "vencordEmbeddedBy") return embeddedBy;
// @ts-ignore ts so bad
return Reflect.get(...arguments);
return Reflect.get(target, prop, receiver);
}
});
}

View file

@ -14,7 +14,11 @@ export type ProxyLazy<T = AnyObject> = T & {
export const proxyLazyGet = Symbol.for("vencord.lazy.get");
export const proxyLazyCache = Symbol.for("vencord.lazy.cached");
export function makeLazy<T>(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): () => T {
export type LazyFunction<T> = (() => T) & {
$$vencordLazyFailed: () => boolean;
};
export function makeLazy<T>(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): LazyFunction<T> {
let tries = 0;
let cache: T;
@ -82,7 +86,6 @@ export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5, isChild
Object.assign(proxyDummy, {
[proxyLazyGet]() {
if (!proxyDummy[proxyLazyCache]) {
// @ts-ignore
if (!get.$$vencordLazyFailed()) {
proxyDummy[proxyLazyCache] = get();
}
@ -113,7 +116,10 @@ export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5, isChild
// `const { meow } = proxyLazy(() => ({ meow: [] }));`
if (!isChild && isSameTick) {
return proxyLazy(
() => Reflect.get(target[proxyLazyGet](), p, target[proxyLazyGet]()),
() => {
const lazyTarget = target[proxyLazyGet]();
return Reflect.get(lazyTarget, p, lazyTarget);
},
attempts,
true
);

View file

@ -27,7 +27,6 @@ export function LazyComponent<T extends object = any>(factory: () => React.Compo
let lazyFailedLogged = false;
const LazyComponent = (props: T) => {
// @ts-ignore
if (!get.$$vencordLazyFailed()) {
const ResultComponent = get();
if (ResultComponent != null) {
@ -36,7 +35,6 @@ export function LazyComponent<T extends object = any>(factory: () => React.Compo
}
if (InnerComponent === null && !lazyFailedLogged) {
// @ts-ignore
if (get.$$vencordLazyFailed()) {
lazyFailedLogged = true;
}

View file

@ -27,21 +27,22 @@ export const onceReady = new Promise<void>(r => _resolveReady = r);
export let wreq: WebpackInstance;
export let cache: WebpackInstance["c"];
export type FilterFn = (mod: any) => boolean;
export type FilterFn = ((mod: any) => boolean) & {
$$vencordProps?: string[];
};
export const filters = {
byProps: (...props: string[]): FilterFn => {
const filter = props.length === 1
const filter: FilterFn = props.length === 1
? m => m?.[props[0]] !== void 0
: m => props.every(p => m?.[p] !== void 0);
// @ts-ignore
filter.$$vencordProps = ["byProps", ...props];
return filter;
},
byCode: (...code: string[]): FilterFn => {
const filter = m => {
const filter: FilterFn = m => {
if (typeof m !== "function") return false;
const s = Function.prototype.toString.call(m);
for (const c of code) {
@ -55,29 +56,36 @@ export const filters = {
},
byStoreName: (name: string): FilterFn => {
const filter = m => m?.constructor?.displayName === name;
const filter: FilterFn = m => m?.constructor?.displayName === name;
filter.$$vencordProps = ["byStoreName", name];
return filter;
},
componentByCode: (...code: string[]): FilterFn => {
const filter = filters.byCode(...code);
const wrapper = m => {
if (filter(m)) return true;
if (!m?.$$typeof) return false;
if (m?.type && m.type.render) return filter(m.type.render); // memo + forwardRef
if (m?.type) return filter(m.type); // memos
if (m?.render) return filter(m.render); // forwardRefs
const byCodeFilter = filters.byCode(...code);
const filter: FilterFn = m => {
let inner = m;
while (inner != null) {
if (byCodeFilter(inner)) return true;
else if (!inner.$$typeof) return false;
else if (inner.type) inner = inner.type; // memos
else if (inner.render) inner = inner.render; // forwardRefs
else return false;
}
return false;
};
wrapper.$$vencordProps = ["componentByCode", ...code];
return wrapper;
filter.$$vencordProps = ["componentByCode", ...code];
return filter;
}
};
export type ModCallbackFn = (mod: any) => void;
export type ModCallbackFn = ((mod: any) => void) & {
$$vencordCallbackCalled?: () => boolean;
};
export type ModCallbackFnWithId = (mod: any, id: string) => void;
export const waitForSubscriptions = new Map<FilterFn, ModCallbackFn>();
@ -94,15 +102,15 @@ let devToolsOpen = false;
if (IS_DEV && IS_DISCORD_DESKTOP) {
// At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed
setTimeout(() => {
DiscordNative/* just to make sure */?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false);
DiscordNative?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false);
}, 0);
}
export const webpackSearchHistory = [] as Array<["waitFor" | "find" | "findComponent" | "findExportedComponent" | "findComponentByCode" | "findByProps" | "findByCode" | "findStore" | "extractAndLoadChunks" | "webpackDependantLazy" | "webpackDependantLazyComponent", any[]]>;
function printFilter(filter: FilterFn) {
if ("$$vencordProps" in filter) {
const props = filter.$$vencordProps as string[];
if (filter.$$vencordProps != null) {
const props = filter.$$vencordProps;
return `${props[0]}(${props.slice(1).map(arg => `"${arg}"`).join(", ")})`;
}
@ -127,16 +135,13 @@ export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect
const originalCallback = callback;
let callbackCalled = false;
callback = function () {
callback = function (this: unknown) {
callbackCalled = true;
// @ts-ignore
originalCallback(...arguments);
Reflect.apply(originalCallback, this, arguments);
};
// @ts-ignore
callback.$$vencordCallbackCalled = () => callbackCalled;
webpackSearchHistory.push(["waitFor", [callback, filter]]);
}
@ -277,7 +282,7 @@ export function findExportedComponent<T extends object = any>(...props: string[]
if (IS_DEV) {
WrapperComponent.$$vencordInner = () => InnerComponent;
webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...props]]);
webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...newProps]]);
}
if (InnerComponent !== null) return InnerComponent;
@ -309,7 +314,7 @@ export function findComponentByCode<T extends object = any>(...code: string[] |
const ComponentResult = findComponent<T>(filters.componentByCode(...newCode), parse, { isIndirect: true });
if (IS_DEV) {
webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...code]]);
webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...newCode]]);
}
return ComponentResult;
@ -475,7 +480,6 @@ export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBu
/**
* Find the id of the first module factory that includes all the given code.
* @returns string or null
*/
export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) {
outer:
@ -503,7 +507,6 @@ export const findModuleId = traceFunction("findModuleId", function findModuleId(
/**
* Find the first module factory that includes all the given code.
* @returns The module factory or null
*/
export function findModuleFactory(...code: string[]) {
const id = findModuleId(...code);