Half independent Vendetta api

This commit is contained in:
amsyarasyiq 2024-02-23 13:29:06 +08:00
parent 11f75aee79
commit dea9ecb084
6 changed files with 196 additions and 77 deletions

View file

@ -28,7 +28,7 @@
"esbuild": "^0.17.16",
"esbuild-plugin-alias": "^0.2.1",
"moment": "2.22.2",
"typescript": "^5.0.4"
"typescript": "^5.2.2"
},
"dependencies": {
"@swc/helpers": "0.5.0",

2
pnpm-lock.yaml generated
View file

@ -41,7 +41,7 @@ devDependencies:
specifier: 2.22.2
version: 2.22.2
typescript:
specifier: ^5.0.4
specifier: ^5.2.2
version: 5.2.2
packages:

View file

@ -8,7 +8,7 @@ import initSafeMode from "@ui/safeMode";
import initSettings from "@ui/settings";
import initFixes from "@lib/fixes";
import logger from "@lib/logger";
import windowObject from "@lib/windowObject";
import initWindowObject from "@lib/windowObject";
export default async () => {
// Load everything in parallel
@ -24,7 +24,7 @@ export default async () => {
]);
// Assign window object
window.vendetta = await windowObject(unloads);
initWindowObject(unloads);
// Once done, load plugins
unloads.push(await initPlugins());

View file

@ -1,23 +1,23 @@
import type { LoaderConfig, Theme } from "@types";
import type { LoaderConfig, LoaderIdentity, Theme } from "@types";
// @ts-ignore
const pyonLoaderConfig = globalThis.__PYON_LOADER__;
const pyonLoaderIdentity = globalThis.__PYON_LOADER__;
// @ts-ignore
const vendettaLoaderConfig = globalThis.__vendetta_loader;
const vendettaLoaderIdentity = globalThis.__vendetta_loader;
export function isVendettaLoader() {
return vendettaLoaderConfig != null;
return vendettaLoaderIdentity != null;
}
export function isPyonLoader() {
return pyonLoaderConfig != null;
return pyonLoaderIdentity != null;
}
function polyfillVendettaLoader() {
function polyfillVendettaLoaderIdentity() {
if (!isPyonLoader() || isVendettaLoader()) return null;
const loader = {
name: pyonLoaderConfig.loaderName,
name: pyonLoaderIdentity.loaderName,
features: {} as Record<string, any>
}
@ -48,21 +48,21 @@ function polyfillVendettaLoader() {
configurable: true
});
return loader as unknown as LoaderConfig;
return loader as LoaderIdentity;
}
export function getVendettaLoader(): LoaderConfig | null {
export function getVendettaLoaderIdentity(): LoaderIdentity | null {
// @ts-ignore
if (globalThis.__vendetta_loader) return globalThis.__vendetta_loader;
return polyfillVendettaLoader();
return polyfillVendettaLoaderIdentity();
}
// add to __vendetta_loader anyway
getVendettaLoader();
getVendettaLoaderIdentity();
export function getLoaderName() {
if (isPyonLoader()) return pyonLoaderConfig.loaderName;
else if (isVendettaLoader()) return vendettaLoaderConfig.name;
if (isPyonLoader()) return pyonLoaderIdentity.loaderName;
else if (isVendettaLoader()) return vendettaLoaderIdentity.name;
return "Unknown";
}
@ -71,7 +71,7 @@ export function isLoaderConfigSupported() {
if (isPyonLoader()) {
return true;
} else if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.loaderConfig;
return vendettaLoaderIdentity!!.features.loaderConfig;
}
return false;
@ -79,9 +79,9 @@ export function isLoaderConfigSupported() {
export function isThemeSupported() {
if (isPyonLoader()) {
return pyonLoaderConfig.hasThemeSupport;
return pyonLoaderIdentity.hasThemeSupport;
} else if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.themes != null;
return vendettaLoaderIdentity!!.features.themes != null;
}
return false;
@ -89,9 +89,9 @@ export function isThemeSupported() {
export function getStoredTheme(): Theme | null {
if (isPyonLoader()) {
return pyonLoaderConfig.storedTheme;
return pyonLoaderIdentity.storedTheme;
} else if (isVendettaLoader()) {
const themeProp = vendettaLoaderConfig!!.features.themes?.prop;
const themeProp = vendettaLoaderIdentity!!.features.themes?.prop;
if (!themeProp) return null;
// @ts-ignore
return globalThis[themeProp] || null;
@ -113,7 +113,7 @@ export function getThemeFilePath() {
export function isReactDevToolsPreloaded() {
if (isPyonLoader()) return false;
else if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.devtools != null;
return vendettaLoaderIdentity!!.features.devtools != null;
}
return false;
@ -123,7 +123,7 @@ export function getReactDevToolsProp(): string | null {
if (!isReactDevToolsPreloaded()) return null;
if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.devtools!!.prop;
return vendettaLoaderIdentity!!.features.devtools!!.prop;
}
return null;
@ -133,16 +133,16 @@ export function getReactDevToolsVersion() {
if (!isReactDevToolsPreloaded()) return null;
if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.devtools!!.version
return vendettaLoaderIdentity!!.features.devtools!!.version
}
return null;
}
export function isSysColorsSupported() {
if (isPyonLoader()) return pyonLoaderConfig.isSysColorsSupported;
if (isPyonLoader()) return pyonLoaderIdentity.isSysColorsSupported;
else if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.syscolors != null;
return vendettaLoaderIdentity!!.features.syscolors != null;
}
return false;
@ -151,9 +151,9 @@ export function isSysColorsSupported() {
export function getSysColors() {
if (!isSysColorsSupported()) return null;
if (isPyonLoader()) {
return pyonLoaderConfig.sysColors;
return pyonLoaderIdentity.sysColors;
} else if (isVendettaLoader()) {
return vendettaLoaderConfig!!.features.syscolors!!.prop;
return vendettaLoaderIdentity!!.features.syscolors!!.prop;
}
return null;

163
src/lib/vendettaObject.ts Normal file
View file

@ -0,0 +1,163 @@
import { VendettaObject } from "@types";
import patcher from "@lib/patcher";
import { getVendettaLoaderIdentity } from "@lib/loader";
import settings, { loaderConfig } from "@lib/settings";
import * as debug from "@lib/debug";
import * as plugins from "@lib/plugins";
import * as themes from "@lib/themes";
import * as commands from "@lib/commands";
import * as storage from "@lib/storage";
import * as metro from "@metro/filters";
import * as common from "@metro/common";
import * as components from "@ui/components";
import * as toasts from "@ui/toasts";
import * as alerts from "@ui/alerts";
import * as assets from "@ui/assets";
import * as color from "@ui/color";
import * as utils from "@lib/utils";
export const createVendettaObject = (unloads: any[]): VendettaObject => ({
patcher: {
before: patcher.before,
after: patcher.after,
instead: patcher.instead
},
metro: {
find: (filter) => metro.find(filter),
findAll: (filter) => metro.findAll(filter),
findByProps: (filter) => metro.findByProps(filter),
findByPropsAll: (filter) => metro.findByPropsAll(filter),
findByName: (name, defaultExp?) => metro.findByName(name, defaultExp),
findByNameAll: (name, defaultExp?) => metro.findByNameAll(name, defaultExp),
findByDisplayName: (displayName, defaultExp?) => metro.findByDisplayName(displayName, defaultExp),
findByDisplayNameAll: (displayName, defaultExp?) => metro.findByDisplayNameAll(displayName, defaultExp),
findByTypeName: (typeName, defaultExp?) => metro.findByTypeName(typeName, defaultExp),
findByTypeNameAll: (typeName, defaultExp?) => metro.findByTypeNameAll(typeName, defaultExp),
findByStoreName: (name: string) => metro.findByStoreName(name),
common: {
constants: common.constants,
channels: common.channels,
i18n: common.i18n,
url: common.url,
toasts: common.toasts,
stylesheet: common.stylesheet,
clipboard: common.clipboard,
assets: common.assets,
invites: common.invites,
commands: common.commands,
navigation: common.navigation,
navigationStack: common.navigationStack,
NavigationNative: common.NavigationNative,
Flux: common.Flux,
FluxDispatcher: common.FluxDispatcher,
React: common.React,
ReactNative: common.ReactNative,
moment: common.moment,
chroma: common.chroma,
lodash: common.lodash,
util: common.util
}
},
constants: {
DISCORD_SERVER: "https://discord.gg/n9QQ4XhhJP",
GITHUB: "https://github.com/vendetta-mod",
PROXY_PREFIX: "https://vd-plugins.github.io/proxy",
HTTP_REGEX: /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/,
HTTP_REGEX_MULTI: /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g,
DISCORD_SERVER_ID: "1015931589865246730",
PLUGINS_CHANNEL_ID: "1091880384561684561",
THEMES_CHANNEL_ID: "1091880434939482202",
},
utils: {
findInReactTree: (tree, filter) => utils.findInReactTree(tree, filter),
findInTree: (tree, filter, options) => utils.findInTree(tree, filter, options),
safeFetch: (input, options?, timeout?) => utils.safeFetch(input, options, timeout),
unfreeze: (obj: object) => utils.unfreeze(obj),
without: (object, ...keys) => utils.without(object, ...keys)
},
debug: {
connectToDebugger: (url: string) => debug.connectToDebugger(url),
getDebugInfo: () => debug.getDebugInfo()
},
ui: {
components: {
Forms: components.Forms,
General: components.General,
Alert: components.Alert,
Button: components.Button,
HelpMessage: components.HelpMessage,
SafeAreaView: components.SafeAreaView,
Summary: components.Summary,
ErrorBoundary: components.ErrorBoundary,
Codeblock: components.Codeblock,
Search: components.Search
},
toasts: {
showToast: (content: string, asset?: number) => toasts.showToast(content, asset)
},
alerts: {
showConfirmationAlert: (options) => alerts.showConfirmationAlert(options),
showCustomAlert: (component, props: any) => alerts.showCustomAlert(component, props),
showInputAlert: (options) => alerts.showInputAlert(options)
},
assets: {
all: assets.all,
find: (filter: (a: any) => void) => assets.find(filter),
getAssetByName: (name: string) => assets.getAssetByName(name),
getAssetByID: (id: number) => assets.getAssetByID(id),
getAssetIDByName: (name: string) => assets.getAssetIDByName(name)
},
semanticColors: color.semanticColors,
rawColors: color.rawColors
},
plugins: {
plugins: plugins.plugins,
fetchPlugin: (id: string) => plugins.fetchPlugin(id),
installPlugin: (id: string, enabled?: boolean | undefined) => plugins.installPlugin(id, enabled),
startPlugin: (id: string) => plugins.startPlugin(id),
stopPlugin: (id: string, disable?: boolean | undefined) => plugins.stopPlugin(id, disable),
removePlugin: (id: string) => plugins.removePlugin(id),
getSettings: (id: string) => plugins.getSettings(id)
},
themes: {
themes: themes.themes,
fetchTheme: (id: string, selected?: boolean) => themes.fetchTheme(id, selected),
installTheme: (id: string) => themes.installTheme(id),
selectTheme: (id: string) => themes.selectTheme(id),
removeTheme: (id: string) => themes.removeTheme(id),
getCurrentTheme: () => themes.getThemeFromLoader(),
updateThemes: () => themes.updateThemes()
},
commands: {
registerCommand: commands.registerCommand
},
storage: {
createProxy: (target) => storage.createProxy(target),
useProxy: <T>(_storage: T) => storage.useProxy(_storage),
createStorage: (backend: any) => storage.createStorage(backend),
wrapSync: (store: any) => storage.wrapSync(store),
awaitSyncWrapper: (store: any) => storage.awaitSyncWrapper(store),
createMMKVBackend: (store: string) => storage.createMMKVBackend(store),
createFileBackend: (file: string) => storage.createFileBackend(file)
},
settings,
loader: {
identity: getVendettaLoaderIdentity() ?? void 0,
config: loaderConfig,
},
logger: {
log: (...message) => console.log(...message),
info: (...message) => console.info(...message),
warn: (...message) => console.warn(...message),
error: (...message) => console.error(...message),
time: (...message) => console.time(...message),
trace: (...message) => console.trace(...message),
verbose: (...message) => console.log(...message)
},
version: debug.versionHash,
unload: () => {
unloads.filter(i => typeof i === "function").forEach(p => p());
// @ts-expect-error explode
delete window.vendetta;
},
});

View file

@ -1,49 +1,5 @@
import { VendettaObject } from "@types";
import patcher from "@lib/patcher";
import logger from "@lib/logger";
import settings, { loaderConfig } from "@lib/settings";
import * as constants from "@lib/constants";
import * as debug from "@lib/debug";
import * as plugins from "@lib/plugins";
import * as themes from "@lib/themes";
import * as commands from "@lib/commands";
import * as storage from "@lib/storage";
import * as metro from "@metro/filters";
import * as common from "@metro/common";
import * as components from "@ui/components";
import * as toasts from "@ui/toasts";
import * as alerts from "@ui/alerts";
import * as assets from "@ui/assets";
import * as color from "@ui/color";
import * as utils from "@lib/utils";
import { createVendettaObject } from "./vendettaObject";
export default async (unloads: any[]): Promise<VendettaObject> => ({
patcher: utils.without(patcher, "unpatchAll"),
metro: { ...metro, common: { ...common } },
constants,
utils,
debug: utils.without(debug, "versionHash", "patchLogHook", "toggleSafeMode"),
ui: {
components,
toasts,
alerts,
assets,
...color,
},
plugins: utils.without(plugins, "initPlugins", "evalPlugin"),
themes: utils.without(themes, "initThemes"),
commands: utils.without(commands, "patchCommands"),
storage,
settings,
loader: {
identity: window.__vendetta_loader,
config: loaderConfig,
},
logger,
version: debug.versionHash,
unload: () => {
unloads.filter(i => typeof i === "function").forEach(p => p());
// @ts-expect-error explode
delete window.vendetta;
},
});
export default function initWindowObject(unloads: any[]) {
window.vendetta = createVendettaObject(unloads);
}