GoonCord/src/lib/api/native/loader.ts

259 lines
6.6 KiB
TypeScript
Raw Normal View History

import { VdThemeInfo } from "@lib/addons/themes";
import { removeCacheFile } from "./fs";
2024-02-23 00:33:40 +08:00
// @ts-ignore
2024-02-23 13:29:06 +08:00
const pyonLoaderIdentity = globalThis.__PYON_LOADER__;
2025-05-04 22:20:24 +03:00
2025-07-26 11:29:31 +03:00
// @ts-ignore
const rainLoaderIdentity = globalThis.__RAIN_LOADER__;
2025-05-04 12:11:23 +01:00
// @ts-ignore
2024-02-23 13:29:06 +08:00
const vendettaLoaderIdentity = globalThis.__vendetta_loader;
2024-02-23 00:33:40 +08:00
2024-02-23 15:11:35 +08:00
export interface VendettaLoaderIdentity {
name: string;
features: {
loaderConfig?: boolean;
devtools?: {
prop: string;
version: string;
},
themes?: {
prop: string;
2024-03-06 01:57:59 +08:00
};
};
2024-02-23 15:11:35 +08:00
}
2024-02-23 00:33:40 +08:00
export function isVendettaLoader() {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity != null;
2024-02-23 00:33:40 +08:00
}
export function isPyonLoader() {
2024-02-23 13:29:06 +08:00
return pyonLoaderIdentity != null;
2024-02-23 00:33:40 +08:00
}
2025-07-26 11:29:31 +03:00
export function isRa1nLoader() {
return rainLoaderIdentity != null;
}
2024-02-23 13:29:06 +08:00
function polyfillVendettaLoaderIdentity() {
2025-07-26 11:29:31 +03:00
if (!isPyonLoader() || isVendettaLoader() || !isRa1nLoader()) return null;
let loader: { name: string; features: Record<string, any> };
2024-02-23 00:33:40 +08:00
2025-07-26 11:29:31 +03:00
if (isRa1nLoader() == true) {
loader = {
name: rainLoaderIdentity.loaderName,
features: {} as Record<string, any>,
};
} else {
loader = {
name: pyonLoaderIdentity.loaderName,
features: {} as Record<string, any>,
};
2025-05-04 12:11:23 +01:00
}
2024-02-23 00:33:40 +08:00
if (isLoaderConfigSupported()) loader.features.loaderConfig = true;
if (isSysColorsSupported()) {
loader.features.syscolors = {
prop: "__vendetta_syscolors"
2024-03-06 01:57:59 +08:00
};
2024-02-23 00:33:40 +08:00
Object.defineProperty(globalThis, "__vendetta_syscolors", {
get: () => getSysColors(),
configurable: true
});
}
if (isThemeSupported()) {
loader.features.themes = {
prop: "__vendetta_theme"
2024-03-06 01:57:59 +08:00
};
2024-02-23 00:33:40 +08:00
Object.defineProperty(globalThis, "__vendetta_theme", {
2024-04-03 01:50:13 +08:00
// get: () => getStoredTheme(),
get: () => {
// PyonXposed only returns keys it parses, making custom keys like Themes+' to gone
const id = getStoredTheme()?.id;
if (!id) return null;
const { themes } = require("@lib/addons/themes");
2024-04-03 01:50:13 +08:00
return themes[id] ?? getStoredTheme() ?? null;
},
2024-02-23 00:33:40 +08:00
configurable: true
});
}
Object.defineProperty(globalThis, "__vendetta_loader", {
get: () => loader,
configurable: true
});
2024-02-23 15:11:35 +08:00
return loader as VendettaLoaderIdentity;
2024-02-23 00:33:40 +08:00
}
export function getLoaderIdentity() {
if (isPyonLoader()) {
return pyonLoaderIdentity;
} else if (isVendettaLoader()) {
return getVendettaLoaderIdentity();
2025-07-26 11:29:31 +03:00
} else if (isRa1nLoader()) {
return rainLoaderIdentity();
}
return null;
}
2024-02-23 15:11:35 +08:00
export function getVendettaLoaderIdentity(): VendettaLoaderIdentity | null {
2024-02-23 00:33:40 +08:00
// @ts-ignore
if (globalThis.__vendetta_loader) return globalThis.__vendetta_loader;
2024-02-23 13:29:06 +08:00
return polyfillVendettaLoaderIdentity();
2024-02-23 00:33:40 +08:00
}
// add to __vendetta_loader anyway
2024-02-23 13:29:06 +08:00
getVendettaLoaderIdentity();
2024-02-23 00:33:40 +08:00
export function getLoaderName() {
2024-02-23 13:29:06 +08:00
if (isPyonLoader()) return pyonLoaderIdentity.loaderName;
2025-07-26 11:29:31 +03:00
else if (isRa1nLoader()) return rainLoaderIdentity.loadername;
2024-02-23 13:29:06 +08:00
else if (isVendettaLoader()) return vendettaLoaderIdentity.name;
2024-02-23 00:33:40 +08:00
return "Unknown";
}
2024-04-30 17:07:23 +08:00
export function getLoaderVersion(): string | null {
if (isPyonLoader()) return pyonLoaderIdentity.loaderVersion;
2025-07-26 11:29:31 +03:00
else if (isRa1nLoader()) return rainLoaderIdentity.loaderVersion;
2024-04-30 17:07:23 +08:00
return null;
}
2024-02-23 00:33:40 +08:00
export function isLoaderConfigSupported() {
if (isPyonLoader()) {
return true;
} else if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity!!.features.loaderConfig;
2025-07-26 11:29:31 +03:00
} else if (isRa1nLoader()) {
return true;
2024-02-23 00:33:40 +08:00
}
return false;
}
export function isThemeSupported() {
if (isPyonLoader()) {
2024-02-23 13:29:06 +08:00
return pyonLoaderIdentity.hasThemeSupport;
2024-02-23 00:33:40 +08:00
} else if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity!!.features.themes != null;
2025-07-26 11:29:31 +03:00
} else if (isRa1nLoader()) {
return false; // Ra1n has theme support disabled, this is here just to make sure it doesnt think it does
2024-02-23 00:33:40 +08:00
}
return false;
}
export function getStoredTheme(): VdThemeInfo | null {
2024-02-23 00:33:40 +08:00
if (isPyonLoader()) {
2024-02-23 13:29:06 +08:00
return pyonLoaderIdentity.storedTheme;
2024-02-23 00:33:40 +08:00
} else if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
const themeProp = vendettaLoaderIdentity!!.features.themes?.prop;
2024-02-23 00:33:40 +08:00
if (!themeProp) return null;
// @ts-ignore
return globalThis[themeProp] || null;
}
return null;
}
export function getThemeFilePath() {
if (isPyonLoader()) {
2024-03-06 01:57:59 +08:00
return "pyoncord/current-theme.json";
2024-02-23 00:33:40 +08:00
} else if (isVendettaLoader()) {
return "vendetta_theme.json";
}
return null;
}
export function isReactDevToolsPreloaded() {
2024-04-16 13:14:58 +08:00
if (isPyonLoader()) {
return Boolean(window.__reactDevTools);
}
2025-07-26 11:29:31 +03:00
if (isRa1nLoader()) {
return false;
}
2024-04-16 13:14:58 +08:00
if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity!!.features.devtools != null;
2024-02-23 00:33:40 +08:00
}
return false;
}
export function getReactDevToolsProp(): string | null {
if (!isReactDevToolsPreloaded()) return null;
2024-04-16 13:14:58 +08:00
if (isPyonLoader()) {
window.__pyoncord_rdt = window.__reactDevTools.exports;
return "__pyoncord_rdt";
}
2024-02-23 00:33:40 +08:00
if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity!!.features.devtools!!.prop;
2024-02-23 00:33:40 +08:00
}
return null;
}
export function getReactDevToolsVersion() {
if (!isReactDevToolsPreloaded()) return null;
2024-04-16 13:14:58 +08:00
if (isPyonLoader()) {
return window.__reactDevTools.version || null;
}
2024-02-23 00:33:40 +08:00
if (isVendettaLoader()) {
2024-03-06 01:57:59 +08:00
return vendettaLoaderIdentity!!.features.devtools!!.version;
2024-02-23 00:33:40 +08:00
}
return null;
}
export function isSysColorsSupported() {
2024-02-23 13:29:06 +08:00
if (isPyonLoader()) return pyonLoaderIdentity.isSysColorsSupported;
2024-02-23 00:33:40 +08:00
else if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity!!.features.syscolors != null;
2024-02-23 00:33:40 +08:00
}
return false;
}
export function getSysColors() {
if (!isSysColorsSupported()) return null;
if (isPyonLoader()) {
2024-02-23 13:29:06 +08:00
return pyonLoaderIdentity.sysColors;
2024-02-23 00:33:40 +08:00
} else if (isVendettaLoader()) {
2024-02-23 13:29:06 +08:00
return vendettaLoaderIdentity!!.features.syscolors!!.prop;
2024-02-23 00:33:40 +08:00
}
return null;
}
export function getLoaderConfigPath() {
if (isPyonLoader()) {
return "pyoncord/loader.json";
} else if (isVendettaLoader()) {
return "vendetta_loader.json";
2025-07-26 11:29:31 +03:00
} else if (isRa1nLoader()) {
return "rain/loader.json";
2024-02-23 00:33:40 +08:00
}
return "loader.json";
}
export function isFontSupported() {
if (isPyonLoader()) return pyonLoaderIdentity.fontPatch === 2;
return false;
}
export async function clearBundle() {
// TODO: This should be not be hardcoded, maybe put in loader.json?
return void await removeCacheFile("bundle.js");
}