diff --git a/build.mjs b/build.mjs
index 6ee549c..fbeb166 100644
--- a/build.mjs
+++ b/build.mjs
@@ -1,11 +1,16 @@
import { build } from "esbuild";
+import { promisify } from "util";
+import { exec as _exec } from "child_process";
+import { replace } from "esbuild-plugin-replace";
import alias from "esbuild-plugin-alias";
import esg from "esbuild-plugin-external-global";
import fs from "fs/promises";
import path from "path";
+const exec = promisify(_exec);
const tsconfig = JSON.parse(await fs.readFile("./tsconfig.json"));
const aliases = Object.fromEntries(Object.entries(tsconfig.compilerOptions.paths).map(([alias, [target]]) => [alias, path.resolve(target)]));
+const commit = (await exec("git rev-parse HEAD")).stdout.trim().substring(0, 7) || "custom";
try {
await build({
@@ -19,6 +24,9 @@ try {
alias(aliases),
esg.externalGlobalPlugin({
"react": "window.React",
+ }),
+ replace({
+ "__vendettaVersion": commit,
})
],
legalComments: "external",
diff --git a/package.json b/package.json
index 6199fe2..d16dbea 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"esbuild": "^0.15.11",
"esbuild-plugin-alias": "^0.2.1",
"esbuild-plugin-external-global": "^1.0.1",
+ "esbuild-plugin-replace": "^1.3.0",
"redux": "^4.2.0",
"typescript": "^4.8.4",
"zustand": "^4.1.2"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6f707b1..a5dcf49 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,6 +7,7 @@ specifiers:
esbuild: ^0.15.11
esbuild-plugin-alias: ^0.2.1
esbuild-plugin-external-global: ^1.0.1
+ esbuild-plugin-replace: ^1.3.0
redux: ^4.2.0
spitroast: ^1.4.2
typescript: ^4.8.4
@@ -22,6 +23,7 @@ devDependencies:
esbuild: 0.15.11
esbuild-plugin-alias: 0.2.1
esbuild-plugin-external-global: 1.0.1
+ esbuild-plugin-replace: 1.3.0
redux: 4.2.0
typescript: 4.8.4
zustand: 4.1.2
@@ -242,6 +244,12 @@ packages:
resolution: {integrity: sha512-NDzYHRoShpvLqNcrgV8ZQh61sMIFAry5KLTQV83BPG5iTXCCu7h72SCfJ97bW0GqtuqDD/1aqLbKinI/rNgUsg==}
dev: true
+ /esbuild-plugin-replace/1.3.0:
+ resolution: {integrity: sha512-i9v5FDfKUaxzpCLn+avq3I6lxJDL5616/tzP93/GFAI7REFwkMTy/pilEIvqlH8RTVpjlwJDOqUOYvJOf5jnXg==}
+ dependencies:
+ magic-string: 0.25.9
+ dev: true
+
/esbuild-sunos-64/0.15.11:
resolution: {integrity: sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==}
engines: {node: '>=12'}
@@ -313,6 +321,12 @@ packages:
engines: {node: '>=8'}
dev: true
+ /magic-string/0.25.9:
+ resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+ dependencies:
+ sourcemap-codec: 1.4.8
+ dev: true
+
/merge-options/3.0.4:
resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==}
engines: {node: '>=10'}
@@ -330,6 +344,11 @@ packages:
resolution: {integrity: sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==}
dev: true
+ /sourcemap-codec/1.4.8:
+ resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ deprecated: Please use @jridgewell/sourcemap-codec instead
+ dev: true
+
/spitroast/1.4.2:
resolution: {integrity: sha512-iEBsKg3EXTQj2nikYIMtOE5YSqbI5CtRxVYI+Gh+9HeQxf4u86UWF5yC5eTVAoReZSogbD2M37JYG8TYGBnFTg==}
dev: false
diff --git a/src/def.d.ts b/src/def.d.ts
index 01daf00..3960ed0 100644
--- a/src/def.d.ts
+++ b/src/def.d.ts
@@ -127,6 +127,7 @@ interface VendettaObject {
}
settings: Settings;
logger: Logger;
+ version: string;
}
declare global {
diff --git a/src/index.ts b/src/index.ts
index 00da721..f3eb61d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -11,7 +11,7 @@ import * as toasts from "@ui/toasts";
import { patchAssets, all, find, getAssetByID, getAssetByName, getAssetIDByName } from "@ui/assets";
import initSettings from "@ui/settings";
import { fixTheme } from "@ui/fixTheme";
-import { connectToDebugger, patchLogHook } from "@lib/debug";
+import { connectToDebugger, patchLogHook, versionHash } from "@lib/debug";
import { plugins, fetchPlugin, evalPlugin, stopPlugin, removePlugin, getSettings } from "@lib/plugins";
import settings from "@lib/settings";
@@ -54,12 +54,13 @@ async function init() {
},
settings: settings,
logger: logger,
+ version: versionHash,
};
- initSettings();
- patchAssets();
patchLogHook();
+ patchAssets();
fixTheme();
+ initSettings();
} catch (e: Error | any) {
erroredOnLoad = true;
alert(`Vendetta failed to initialize... ${e.stack || e.toString()}`);
diff --git a/src/lib/debug.ts b/src/lib/debug.ts
index e513599..5dbdc98 100644
--- a/src/lib/debug.ts
+++ b/src/lib/debug.ts
@@ -1,3 +1,4 @@
+import { ReactNative as RN } from "@metro/common";
import { after } from "@lib/patcher";
import { getAssetIDByName } from "@ui/assets";
import { showToast } from "@ui/toasts";
@@ -41,3 +42,30 @@ export function patchLogHook() {
logger.log(args[0]);
});
}
+
+export const versionHash = "__vendettaVersion";
+
+export function getDebugInfo(string: boolean = false) {
+ const InfoDictionaryManager = RN.NativeModules.InfoDictionaryManager;
+ const hermesProps = window.HermesInternal.getRuntimeProperties();
+ const rnVer = RN.Platform.constants.reactNativeVersion;
+
+ return {
+ vendetta: {
+ version: versionHash,
+ },
+ discord: {
+ version: InfoDictionaryManager.Version,
+ build: InfoDictionaryManager.Build,
+ },
+ react: {
+ version: React.version,
+ nativeVersion: `${rnVer.major || 0}.${rnVer.minor || 0}.${rnVer.patch || 0}`,
+ },
+ hermes: {
+ version: hermesProps["OSS Release Version"],
+ buildType: hermesProps["Build"],
+ bytecodeVersion: hermesProps["Bytecode Version"],
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ui/components.ts b/src/ui/components.ts
index 6e88552..9564579 100644
--- a/src/ui/components.ts
+++ b/src/ui/components.ts
@@ -1,4 +1,5 @@
-import { findByProps } from "@metro/filters";
+import { findByDisplayName, findByProps } from "@metro/filters";
export const Forms = findByProps("Form", "FormSection");
-export const General = findByProps("Button", "Text", "View");
\ No newline at end of file
+export const General = findByProps("Button", "Text", "View");
+export const Search = findByDisplayName("StaticSearchBarContainer");
\ No newline at end of file
diff --git a/src/ui/settings/components/PluginCard.tsx b/src/ui/settings/components/PluginCard.tsx
index cd6cfef..740a977 100644
--- a/src/ui/settings/components/PluginCard.tsx
+++ b/src/ui/settings/components/PluginCard.tsx
@@ -53,7 +53,7 @@ export default function PluginCard({ plugin }: PluginCardProps) {
leading={}
trailing={
{
if (v) startPlugin(plugin.id); else stopPlugin(plugin.id);
setEnabled(v);
@@ -76,11 +76,11 @@ export default function PluginCard({ plugin }: PluginCardProps) {
{
plugin.update = !plugin.update;
- setUpdate(plugin.update);
showToast(`${plugin.update ? "Enabled" : "Disabled"} updates for ${plugin.manifest.name}.`, getAssetIDByName("toast_image_saved"));
+ setUpdate(plugin.update);
}}
>
-
+
{getSettings(plugin.id) && showSettings(plugin)}>
diff --git a/src/ui/settings/pages/Developer.tsx b/src/ui/settings/pages/Developer.tsx
index a05bd99..ccc97b0 100644
--- a/src/ui/settings/pages/Developer.tsx
+++ b/src/ui/settings/pages/Developer.tsx
@@ -1,19 +1,33 @@
-import { ReactNative as RN } from "@metro/common";
-import { Forms } from "@ui/components";
+import { ReactNative as RN, stylesheet } from "@metro/common";
+import { Forms, Search } from "@ui/components";
import { getAssetIDByName } from "@ui/assets";
+import { showToast } from "@/ui/toasts";
import { connectToDebugger } from "@lib/debug";
import { all } from "@ui/assets";
import settings from "@lib/settings";
+import logger from "@lib/logger";
import AssetDisplay from "@ui/settings/components/AssetDisplay";
const { FormSection, FormRow, FormInput, FormDivider } = Forms;
+const { connectToDevTools } = window.__vendetta_rdc;
+
+const styles = stylesheet.createThemedStyleSheet({
+ search: {
+ margin: 0,
+ padding: 0,
+ paddingRight: 15,
+ paddingLeft: 15,
+ borderBottomWidth: 0,
+ backgroundColor: "none"
+ }
+})
export default function Developer() {
const [debuggerUrl, setDebuggerUrl] = React.useState(settings.debuggerUrl || "");
const [searchName, setSearchName] = React.useState("");
return (
- <>
+
connectToDebugger(debuggerUrl)}
/>
+
+ {connectToDevTools && }
+ trailing={FormRow.Arrow}
+ onPress={() => {
+ try {
+ connectToDevTools({
+ host: debuggerUrl.split(":")[0],
+ resolveRNStyle: RN.StyleSheet.flatten,
+ });
+ } catch(e) {
+ logger.error("Failed to connect to React DevTools!", e);
+ showToast("Failed to connect to React DevTools!", getAssetIDByName("Small"));
+ }
+ }}
+ />}
- setSearchName(v)}
- title="SEARCH"
+ setSearchName(v)}
+ placeholder="Search..."
/>
a.name.includes(searchName))}
@@ -48,6 +79,6 @@ export default function Developer() {
keyExtractor={item => item.name}
/>
- >
+
)
}
\ No newline at end of file
diff --git a/src/ui/settings/pages/General.tsx b/src/ui/settings/pages/General.tsx
index 96fb455..da90aac 100644
--- a/src/ui/settings/pages/General.tsx
+++ b/src/ui/settings/pages/General.tsx
@@ -2,36 +2,40 @@ import { ReactNative as RN, url } from "@metro/common";
import { DISCORD_SERVER, GITHUB } from "@lib/constants";
import { getAssetIDByName } from "@ui/assets";
import { Forms } from "@ui/components";
+import { getDebugInfo } from "@lib/debug";
import Version from "@ui/settings/components/Version";
import settings from "@lib/settings";
-const { FormRow, FormSection, FormDivider, FormSwitch } = Forms;
-const InfoDictionaryManager = RN.NativeModules.InfoDictionaryManager;
-const hermesProps = window.HermesInternal.getRuntimeProperties();
-const rnVer = RN.Platform.constants.reactNativeVersion;
+const { FormRow, FormSwitchRow, FormSection, FormDivider } = Forms;
+const debugInfo = getDebugInfo()
export default function General() {
const [devSettings, setDevSettings] = React.useState(settings.developerSettings || false);
const versions = [
+ {
+ label: "Vendetta",
+ version: debugInfo.vendetta.version,
+ icon: "ic_progress_wrench_24px"
+ },
{
label: "Discord",
- version: `${InfoDictionaryManager.Version} (${InfoDictionaryManager.Build})`,
+ version: `${debugInfo.discord.version} (${debugInfo.discord.build})`,
icon: "Discord",
},
{
label: "React",
- version: React.version,
+ version: debugInfo.react.version,
icon: "ic_category_16px",
},
{
label: "React Native",
- version: `${rnVer.major || 0}.${rnVer.minor || 0}.${rnVer.patch || 0}`,
+ version: debugInfo.react.nativeVersion,
icon: "mobile",
},
{
label: "Hermes",
- version: `${hermesProps["OSS Release Version"]} ${hermesProps["Build"]} | Bytecode ${hermesProps["Bytecode Version"]}`,
+ version: `${debugInfo.hermes.version} ${debugInfo.hermes.buildType} | Bytecode ${debugInfo.hermes.bytecodeVersion}`,
icon: "ic_badge_staff",
},
];
@@ -69,16 +73,14 @@ export default function General() {
onPress={() => RN.NativeModules.BundleUpdaterManager.reload()}
/>
- }
- trailing={ {
- settings.developerSettings = v;
- setDevSettings(v);
- }}
- />}
+ value={devSettings}
+ onValueChange={(v: boolean) => {
+ settings.developerSettings = v;
+ setDevSettings(v);
+ }}
/>
diff --git a/src/ui/settings/pages/Plugins.tsx b/src/ui/settings/pages/Plugins.tsx
index 32a6e82..b6f81ab 100644
--- a/src/ui/settings/pages/Plugins.tsx
+++ b/src/ui/settings/pages/Plugins.tsx
@@ -12,7 +12,7 @@ export default function Plugins() {
const [pluginList, setPluginList] = React.useState(plugins);
return (
- <>
+
setPluginUrl(v)}
@@ -20,7 +20,7 @@ export default function Plugins() {
/>
}
+ leading={}
trailing={FormRow.Arrow}
onPress={() => {
fetchPlugin(pluginUrl).then(() => {
@@ -37,6 +37,6 @@ export default function Plugins() {
renderItem={({ item }) => }
keyExtractor={item => item.id}
/>
- >
+
)
}
\ No newline at end of file