[Global] Refactors all around

This commit is contained in:
Beef 2023-01-10 23:30:46 +00:00
parent 01a05a8b9d
commit 93c4eef678
11 changed files with 127 additions and 35 deletions

View file

@ -1,11 +1,16 @@
import { build } from "esbuild"; 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 alias from "esbuild-plugin-alias";
import esg from "esbuild-plugin-external-global"; import esg from "esbuild-plugin-external-global";
import fs from "fs/promises"; import fs from "fs/promises";
import path from "path"; import path from "path";
const exec = promisify(_exec);
const tsconfig = JSON.parse(await fs.readFile("./tsconfig.json")); 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 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 { try {
await build({ await build({
@ -19,6 +24,9 @@ try {
alias(aliases), alias(aliases),
esg.externalGlobalPlugin({ esg.externalGlobalPlugin({
"react": "window.React", "react": "window.React",
}),
replace({
"__vendettaVersion": commit,
}) })
], ],
legalComments: "external", legalComments: "external",

View file

@ -20,6 +20,7 @@
"esbuild": "^0.15.11", "esbuild": "^0.15.11",
"esbuild-plugin-alias": "^0.2.1", "esbuild-plugin-alias": "^0.2.1",
"esbuild-plugin-external-global": "^1.0.1", "esbuild-plugin-external-global": "^1.0.1",
"esbuild-plugin-replace": "^1.3.0",
"redux": "^4.2.0", "redux": "^4.2.0",
"typescript": "^4.8.4", "typescript": "^4.8.4",
"zustand": "^4.1.2" "zustand": "^4.1.2"

View file

@ -7,6 +7,7 @@ specifiers:
esbuild: ^0.15.11 esbuild: ^0.15.11
esbuild-plugin-alias: ^0.2.1 esbuild-plugin-alias: ^0.2.1
esbuild-plugin-external-global: ^1.0.1 esbuild-plugin-external-global: ^1.0.1
esbuild-plugin-replace: ^1.3.0
redux: ^4.2.0 redux: ^4.2.0
spitroast: ^1.4.2 spitroast: ^1.4.2
typescript: ^4.8.4 typescript: ^4.8.4
@ -22,6 +23,7 @@ devDependencies:
esbuild: 0.15.11 esbuild: 0.15.11
esbuild-plugin-alias: 0.2.1 esbuild-plugin-alias: 0.2.1
esbuild-plugin-external-global: 1.0.1 esbuild-plugin-external-global: 1.0.1
esbuild-plugin-replace: 1.3.0
redux: 4.2.0 redux: 4.2.0
typescript: 4.8.4 typescript: 4.8.4
zustand: 4.1.2 zustand: 4.1.2
@ -242,6 +244,12 @@ packages:
resolution: {integrity: sha512-NDzYHRoShpvLqNcrgV8ZQh61sMIFAry5KLTQV83BPG5iTXCCu7h72SCfJ97bW0GqtuqDD/1aqLbKinI/rNgUsg==} resolution: {integrity: sha512-NDzYHRoShpvLqNcrgV8ZQh61sMIFAry5KLTQV83BPG5iTXCCu7h72SCfJ97bW0GqtuqDD/1aqLbKinI/rNgUsg==}
dev: true 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: /esbuild-sunos-64/0.15.11:
resolution: {integrity: sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==} resolution: {integrity: sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -313,6 +321,12 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true 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: /merge-options/3.0.4:
resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==} resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -330,6 +344,11 @@ packages:
resolution: {integrity: sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==} resolution: {integrity: sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==}
dev: true 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: /spitroast/1.4.2:
resolution: {integrity: sha512-iEBsKg3EXTQj2nikYIMtOE5YSqbI5CtRxVYI+Gh+9HeQxf4u86UWF5yC5eTVAoReZSogbD2M37JYG8TYGBnFTg==} resolution: {integrity: sha512-iEBsKg3EXTQj2nikYIMtOE5YSqbI5CtRxVYI+Gh+9HeQxf4u86UWF5yC5eTVAoReZSogbD2M37JYG8TYGBnFTg==}
dev: false dev: false

1
src/def.d.ts vendored
View file

@ -127,6 +127,7 @@ interface VendettaObject {
} }
settings: Settings; settings: Settings;
logger: Logger; logger: Logger;
version: string;
} }
declare global { declare global {

View file

@ -11,7 +11,7 @@ import * as toasts from "@ui/toasts";
import { patchAssets, all, find, getAssetByID, getAssetByName, getAssetIDByName } from "@ui/assets"; import { patchAssets, all, find, getAssetByID, getAssetByName, getAssetIDByName } from "@ui/assets";
import initSettings from "@ui/settings"; import initSettings from "@ui/settings";
import { fixTheme } from "@ui/fixTheme"; 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 { plugins, fetchPlugin, evalPlugin, stopPlugin, removePlugin, getSettings } from "@lib/plugins";
import settings from "@lib/settings"; import settings from "@lib/settings";
@ -54,12 +54,13 @@ async function init() {
}, },
settings: settings, settings: settings,
logger: logger, logger: logger,
version: versionHash,
}; };
initSettings();
patchAssets();
patchLogHook(); patchLogHook();
patchAssets();
fixTheme(); fixTheme();
initSettings();
} catch (e: Error | any) { } catch (e: Error | any) {
erroredOnLoad = true; erroredOnLoad = true;
alert(`Vendetta failed to initialize... ${e.stack || e.toString()}`); alert(`Vendetta failed to initialize... ${e.stack || e.toString()}`);

View file

@ -1,3 +1,4 @@
import { ReactNative as RN } from "@metro/common";
import { after } from "@lib/patcher"; import { after } from "@lib/patcher";
import { getAssetIDByName } from "@ui/assets"; import { getAssetIDByName } from "@ui/assets";
import { showToast } from "@ui/toasts"; import { showToast } from "@ui/toasts";
@ -41,3 +42,30 @@ export function patchLogHook() {
logger.log(args[0]); 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"],
}
}
}

View file

@ -1,4 +1,5 @@
import { findByProps } from "@metro/filters"; import { findByDisplayName, findByProps } from "@metro/filters";
export const Forms = findByProps("Form", "FormSection"); export const Forms = findByProps("Form", "FormSection");
export const General = findByProps("Button", "Text", "View"); export const General = findByProps("Button", "Text", "View");
export const Search = findByDisplayName("StaticSearchBarContainer");

View file

@ -53,7 +53,7 @@ export default function PluginCard({ plugin }: PluginCardProps) {
leading={<FormRow.Icon source={getAssetIDByName(plugin.manifest.vendetta.icon || "ic_application_command_24px")} />} leading={<FormRow.Icon source={getAssetIDByName(plugin.manifest.vendetta.icon || "ic_application_command_24px")} />}
trailing={ trailing={
<FormSwitch <FormSwitch
value={plugin.enabled} value={enabled}
onValueChange={(v: boolean) => { onValueChange={(v: boolean) => {
if (v) startPlugin(plugin.id); else stopPlugin(plugin.id); if (v) startPlugin(plugin.id); else stopPlugin(plugin.id);
setEnabled(v); setEnabled(v);
@ -76,11 +76,11 @@ export default function PluginCard({ plugin }: PluginCardProps) {
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
plugin.update = !plugin.update; plugin.update = !plugin.update;
setUpdate(plugin.update);
showToast(`${plugin.update ? "Enabled" : "Disabled"} updates for ${plugin.manifest.name}.`, getAssetIDByName("toast_image_saved")); showToast(`${plugin.update ? "Enabled" : "Disabled"} updates for ${plugin.manifest.name}.`, getAssetIDByName("toast_image_saved"));
setUpdate(plugin.update);
}} }}
> >
<Image style={styles.icon} source={getAssetIDByName(plugin.update ? "Check" : "Small")} /> <Image style={styles.icon} source={getAssetIDByName(update ? "Check" : "Small")} />
</TouchableOpacity> </TouchableOpacity>
{getSettings(plugin.id) && <TouchableOpacity onPress={() => showSettings(plugin)}> {getSettings(plugin.id) && <TouchableOpacity onPress={() => showSettings(plugin)}>
<Image style={styles.icon} source={getAssetIDByName("settings")} /> <Image style={styles.icon} source={getAssetIDByName("settings")} />

View file

@ -1,19 +1,33 @@
import { ReactNative as RN } from "@metro/common"; import { ReactNative as RN, stylesheet } from "@metro/common";
import { Forms } from "@ui/components"; import { Forms, Search } from "@ui/components";
import { getAssetIDByName } from "@ui/assets"; import { getAssetIDByName } from "@ui/assets";
import { showToast } from "@/ui/toasts";
import { connectToDebugger } from "@lib/debug"; import { connectToDebugger } from "@lib/debug";
import { all } from "@ui/assets"; import { all } from "@ui/assets";
import settings from "@lib/settings"; import settings from "@lib/settings";
import logger from "@lib/logger";
import AssetDisplay from "@ui/settings/components/AssetDisplay"; import AssetDisplay from "@ui/settings/components/AssetDisplay";
const { FormSection, FormRow, FormInput, FormDivider } = Forms; 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() { export default function Developer() {
const [debuggerUrl, setDebuggerUrl] = React.useState(settings.debuggerUrl || ""); const [debuggerUrl, setDebuggerUrl] = React.useState(settings.debuggerUrl || "");
const [searchName, setSearchName] = React.useState(""); const [searchName, setSearchName] = React.useState("");
return ( return (
<> <RN.View>
<FormSection title="Debug"> <FormSection title="Debug">
<FormInput <FormInput
value={debuggerUrl} value={debuggerUrl}
@ -30,12 +44,29 @@ export default function Developer() {
trailing={FormRow.Arrow} trailing={FormRow.Arrow}
onPress={() => connectToDebugger(debuggerUrl)} onPress={() => connectToDebugger(debuggerUrl)}
/> />
<FormDivider />
{connectToDevTools && <FormRow
label="Connect to React DevTools"
leading={() => <FormRow.Icon source={getAssetIDByName("ic_badge_staff")} />}
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"));
}
}}
/>}
</FormSection> </FormSection>
<FormSection title="Assets"> <FormSection title="Assets">
<FormInput <Search
value={searchName} style={styles.search}
onChange={(v: string) => setSearchName(v)} onChangeText={(v: string) => setSearchName(v)}
title="SEARCH" placeholder="Search..."
/> />
<RN.FlatList <RN.FlatList
data={Object.values(all).filter(a => a.name.includes(searchName))} data={Object.values(all).filter(a => a.name.includes(searchName))}
@ -48,6 +79,6 @@ export default function Developer() {
keyExtractor={item => item.name} keyExtractor={item => item.name}
/> />
</FormSection> </FormSection>
</> </RN.View>
) )
} }

View file

@ -2,36 +2,40 @@ import { ReactNative as RN, url } from "@metro/common";
import { DISCORD_SERVER, GITHUB } from "@lib/constants"; import { DISCORD_SERVER, GITHUB } from "@lib/constants";
import { getAssetIDByName } from "@ui/assets"; import { getAssetIDByName } from "@ui/assets";
import { Forms } from "@ui/components"; import { Forms } from "@ui/components";
import { getDebugInfo } from "@lib/debug";
import Version from "@ui/settings/components/Version"; import Version from "@ui/settings/components/Version";
import settings from "@lib/settings"; import settings from "@lib/settings";
const { FormRow, FormSection, FormDivider, FormSwitch } = Forms; const { FormRow, FormSwitchRow, FormSection, FormDivider } = Forms;
const InfoDictionaryManager = RN.NativeModules.InfoDictionaryManager; const debugInfo = getDebugInfo()
const hermesProps = window.HermesInternal.getRuntimeProperties();
const rnVer = RN.Platform.constants.reactNativeVersion;
export default function General() { export default function General() {
const [devSettings, setDevSettings] = React.useState(settings.developerSettings || false); const [devSettings, setDevSettings] = React.useState(settings.developerSettings || false);
const versions = [ const versions = [
{
label: "Vendetta",
version: debugInfo.vendetta.version,
icon: "ic_progress_wrench_24px"
},
{ {
label: "Discord", label: "Discord",
version: `${InfoDictionaryManager.Version} (${InfoDictionaryManager.Build})`, version: `${debugInfo.discord.version} (${debugInfo.discord.build})`,
icon: "Discord", icon: "Discord",
}, },
{ {
label: "React", label: "React",
version: React.version, version: debugInfo.react.version,
icon: "ic_category_16px", icon: "ic_category_16px",
}, },
{ {
label: "React Native", label: "React Native",
version: `${rnVer.major || 0}.${rnVer.minor || 0}.${rnVer.patch || 0}`, version: debugInfo.react.nativeVersion,
icon: "mobile", icon: "mobile",
}, },
{ {
label: "Hermes", 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", icon: "ic_badge_staff",
}, },
]; ];
@ -69,16 +73,14 @@ export default function General() {
onPress={() => RN.NativeModules.BundleUpdaterManager.reload()} onPress={() => RN.NativeModules.BundleUpdaterManager.reload()}
/> />
<FormDivider /> <FormDivider />
<FormRow <FormSwitchRow
label="Developer Settings" label="Developer Settings"
leading={<FormRow.Icon source={getAssetIDByName("ic_progress_wrench_24px")} />} leading={<FormRow.Icon source={getAssetIDByName("ic_progress_wrench_24px")} />}
trailing={<FormSwitch
value={devSettings} value={devSettings}
onValueChange={(v: boolean) => { onValueChange={(v: boolean) => {
settings.developerSettings = v; settings.developerSettings = v;
setDevSettings(v); setDevSettings(v);
}} }}
/>}
/> />
</FormSection> </FormSection>
</RN.ScrollView> </RN.ScrollView>

View file

@ -12,7 +12,7 @@ export default function Plugins() {
const [pluginList, setPluginList] = React.useState(plugins); const [pluginList, setPluginList] = React.useState(plugins);
return ( return (
<> <RN.View>
<FormInput <FormInput
value={pluginUrl} value={pluginUrl}
onChange={(v: string) => setPluginUrl(v)} onChange={(v: string) => setPluginUrl(v)}
@ -20,7 +20,7 @@ export default function Plugins() {
/> />
<FormRow <FormRow
label="Install plugin" label="Install plugin"
leading={() => <FormRow.Icon source={getAssetIDByName("add_white")} />} leading={<FormRow.Icon source={getAssetIDByName("add_white")} />}
trailing={FormRow.Arrow} trailing={FormRow.Arrow}
onPress={() => { onPress={() => {
fetchPlugin(pluginUrl).then(() => { fetchPlugin(pluginUrl).then(() => {
@ -37,6 +37,6 @@ export default function Plugins() {
renderItem={({ item }) => <PluginCard plugin={item} />} renderItem={({ item }) => <PluginCard plugin={item} />}
keyExtractor={item => item.id} keyExtractor={item => item.id}
/> />
</> </RN.View>
) )
} }