2024-10-23 11:16:47 +08:00
|
|
|
import { VdThemeInfo } from "@lib/addons/themes";
|
2024-09-15 04:24:18 +07:00
|
|
|
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;
|
|
|
|
|
|
2024-10-13 00:35:36 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2024-02-28 14:09:42 +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();
|
2024-02-28 14:09:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 11:16:47 +08:00
|
|
|
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()) {
|
2025-12-23 15:46:19 +02:00
|
|
|
return Boolean(window.__REACT_DEVTOOLS__);
|
2025-07-26 11:29:31 +03:00
|
|
|
}
|
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()) {
|
2025-12-23 15:46:19 +02:00
|
|
|
window.__pyoncord_rdt = window.__REACT_DEVTOOLS__.exports;
|
2024-04-16 13:14:58 +08:00
|
|
|
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()) {
|
2025-12-23 15:46:19 +02:00
|
|
|
return window.__REACT_DEVTOOLS__.version || null;
|
2024-04-16 13:14:58 +08:00
|
|
|
}
|
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() {
|
2025-11-01 19:09:59 +02:00
|
|
|
return true;
|
2024-02-23 00:33:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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";
|
|
|
|
|
}
|
2024-05-18 02:55:20 +08:00
|
|
|
|
|
|
|
|
export function isFontSupported() {
|
|
|
|
|
if (isPyonLoader()) return pyonLoaderIdentity.fontPatch === 2;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-09-15 04:24:18 +07:00
|
|
|
|
|
|
|
|
export async function clearBundle() {
|
|
|
|
|
// TODO: This should be not be hardcoded, maybe put in loader.json?
|
|
|
|
|
return void await removeCacheFile("bundle.js");
|
|
|
|
|
}
|