diff --git a/bun.lock b/bun.lock index 46124a7..992ff87 100644 --- a/bun.lock +++ b/bun.lock @@ -7,8 +7,6 @@ "dependencies": { "@revenge-mod/assets": "workspace:*", "@revenge-mod/components": "workspace:*", - "@revenge-mod/devtools-client": "^1.4.0", - "@revenge-mod/devtools-shared": "^1.3.0", "@revenge-mod/discord": "workspace:*", "@revenge-mod/externals": "workspace:*", "@revenge-mod/json-storage": "workspace:*", @@ -210,10 +208,6 @@ "@revenge-mod/components": ["@revenge-mod/components@workspace:lib/components"], - "@revenge-mod/devtools-client": ["@revenge-mod/devtools-client@1.4.0", "", { "dependencies": { "@revenge-mod/devtools-shared": "^1.3.0", "bippy": "^0.3.8" } }, "sha512-hGmdM0RcK3/IrzpW7lDOXl+it3wYcoF+ePI43Ey3AvIPaBGIDIGqqitKtrB8wIGo5jREsr703fcjseE+bt+aCg=="], - - "@revenge-mod/devtools-shared": ["@revenge-mod/devtools-shared@1.3.0", "", { "dependencies": { "chalk": "^5.6.2", "devalue": "^5.3.2" } }, "sha512-MLox/xQsYtMG78R4R8sy32P5X7ILUNUPAX8IiWjUsPIclkTweDvwEAUadkvbBo8j+/ZJaJdif+Fg/C9YQNlOqg=="], - "@revenge-mod/discord": ["@revenge-mod/discord@workspace:lib/discord"], "@revenge-mod/externals": ["@revenge-mod/externals@workspace:lib/externals"], @@ -304,8 +298,6 @@ "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], - "@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="], - "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], "@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="], @@ -406,8 +398,6 @@ "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - "bippy": ["bippy@0.3.34", "", { "dependencies": { "@types/react-reconciler": "^0.28.9" }, "peerDependencies": { "react": ">=17.0.1" } }, "sha512-vmptmU/20UdIWHHhq7qCSHhHzK7Ro3YJ1utU0fBG7ujUc58LEfTtilKxcF0IOgSjT5XLcm7CBzDjbv4lcKApGQ=="], - "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], @@ -434,8 +424,6 @@ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "devalue": ["devalue@5.8.2", "", {}, "sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA=="], - "dts-resolver": ["dts-resolver@3.0.0", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-1T1f+z+4tl9XD+m+0HBgWoL/nm0bOIffyWaUuUSBlFg/86IWvfx+wjNaO/ybU0AJzG9/Mi5hBUgGV6zCmWEN7Q=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -592,8 +580,6 @@ "yuku-parser": ["yuku-parser@0.8.1", "", { "dependencies": { "@yuku-toolchain/types": "^0.8.1", "yuku-ast": "^0.8.1" }, "optionalDependencies": { "@yuku-parser/binding-darwin-arm64": "0.8.1", "@yuku-parser/binding-darwin-x64": "0.8.1", "@yuku-parser/binding-freebsd-x64": "0.8.1", "@yuku-parser/binding-linux-arm-gnu": "0.8.1", "@yuku-parser/binding-linux-arm-musl": "0.8.1", "@yuku-parser/binding-linux-arm64-gnu": "0.8.1", "@yuku-parser/binding-linux-arm64-musl": "0.8.1", "@yuku-parser/binding-linux-x64-gnu": "0.8.1", "@yuku-parser/binding-linux-x64-musl": "0.8.1", "@yuku-parser/binding-win32-arm64": "0.8.1", "@yuku-parser/binding-win32-x64": "0.8.1" } }, "sha512-YvUz2jdFMIq0QjN8LmI32ox+RBCn3l8VToAXVQ5QFfLTxSxmGZS6JP80ptePEju+CpeTdINLmUm7Ewodzh1QnQ=="], - "@revenge-mod/devtools-shared/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - "metro-runtime/@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], "pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], diff --git a/package.json b/package.json index 90038a4..2c8a381 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,6 @@ "dependencies": { "@revenge-mod/assets": "workspace:*", "@revenge-mod/components": "workspace:*", - "@revenge-mod/devtools-client": "^1.4.0", - "@revenge-mod/devtools-shared": "^1.3.0", "@revenge-mod/discord": "workspace:*", "@revenge-mod/externals": "workspace:*", "@revenge-mod/json-storage": "workspace:*", diff --git a/src/plugins/start/developer-kit/constants.ts b/src/plugins/start/developer-kit/constants.ts deleted file mode 100644 index 3c9cac9..0000000 --- a/src/plugins/start/developer-kit/constants.ts +++ /dev/null @@ -1,26 +0,0 @@ -export const Setting = { - // MAIN SETTINGS - - RevengeDeveloper: 'RevengeDeveloper', - - // SUBSETTINGS - - DTAutoConnect: 'DTAutoConnect', - DTConnect: 'DTConnect', - DTDisconnect: 'DTDisconnect', - - RDTAutoConnect: 'RDTAutoConnect', - RDTConnect: 'RDTConnect', - RDTDisconnect: 'RDTDisconnect', - - EvalJS: 'EvalJS', - AssetBrowser: 'AssetBrowser', - TestErrorBoundary: 'TestErrorBoundary', -} as const - -export const RouteNames = { - [Setting.RevengeDeveloper]: 'Revenge Developer', - [Setting.AssetBrowser]: 'Asset Browser', - [Setting.EvalJS]: 'Evaluate JavaScript', - [Setting.TestErrorBoundary]: 'Test ErrorBoundary', -} as const diff --git a/src/plugins/start/developer-kit/definitions/AssetBrowserSetting.tsx b/src/plugins/start/developer-kit/definitions/AssetBrowserSetting.tsx deleted file mode 100644 index 75d8b73..0000000 --- a/src/plugins/start/developer-kit/definitions/AssetBrowserSetting.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { RouteNames, Setting } from '../constants' -import defer * as AssetBrowserSettingScreen from '../screens/AssetBrowserSettingScreen' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const AssetBrowserSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - type: 'route', - IconComponent: () => , - useTitle: () => 'Asset Browser', - screen: { - route: RouteNames[Setting.AssetBrowser], - getComponent: () => AssetBrowserSettingScreen.default, - }, -} - -export default AssetBrowserSetting diff --git a/src/plugins/start/developer-kit/definitions/DTAutoConnectSetting.tsx b/src/plugins/start/developer-kit/definitions/DTAutoConnectSetting.tsx deleted file mode 100644 index c1b65f2..0000000 --- a/src/plugins/start/developer-kit/definitions/DTAutoConnectSetting.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { api } from '..' -import { Setting } from '../constants' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const DTAutoConnectSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - IconComponent: () => , - useTitle: () => 'Auto-connect to DevTools', - useDescription: () => 'Automatically connect to DevTools during startup.', - useValue: () => - api.jsonStorage.use(s => s.devTools?.autoConnect !== undefined)! - .devTools.autoConnect, - onValueChange: v => { - api.jsonStorage.set({ devTools: { autoConnect: v } }) - }, - type: 'toggle', -} - -export default DTAutoConnectSetting diff --git a/src/plugins/start/developer-kit/definitions/DTConnectSetting.tsx b/src/plugins/start/developer-kit/definitions/DTConnectSetting.tsx deleted file mode 100644 index f3b9f38..0000000 --- a/src/plugins/start/developer-kit/definitions/DTConnectSetting.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { DevToolsClient } from '@revenge-mod/devtools-client' -import { Setting } from '../constants' -import { connect, useIsConnected } from '../devtools' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const DTConnectSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - IconComponent: () => , - useTitle: () => 'Connect to DevTools', - useDescription: () => `Version: ${DevToolsClient.version}`, - usePredicate: () => !useIsConnected(), - onPress: connect, - type: 'pressable', -} - -export default DTConnectSetting diff --git a/src/plugins/start/developer-kit/definitions/DTDisconnectSetting.tsx b/src/plugins/start/developer-kit/definitions/DTDisconnectSetting.tsx deleted file mode 100644 index 278000d..0000000 --- a/src/plugins/start/developer-kit/definitions/DTDisconnectSetting.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { Setting } from '../constants' -import { disconnect, useIsConnected } from '../devtools' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const DTDisconnectSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - IconComponent: () => , - variant: 'danger', - useTitle: () => 'Disconnect from DevTools', - usePredicate: useIsConnected, - onPress: disconnect, - type: 'pressable', -} - -export default DTDisconnectSetting diff --git a/src/plugins/start/developer-kit/definitions/EvalJSSetting.tsx b/src/plugins/start/developer-kit/definitions/EvalJSSetting.tsx deleted file mode 100644 index 3a1d030..0000000 --- a/src/plugins/start/developer-kit/definitions/EvalJSSetting.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { TableRowAssetIcon } from '@revenge-mod/components' -import { RouteNames, Setting } from '../constants' -import EvalJSSettingScreen from '../screens/EvalJSSettingScreen' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const EvalJSSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - type: 'route', - IconComponent: () => , - useTitle: () => 'Evaluate JavaScript', - useDescription: () => 'Runs a JavaScript code snippet.', - screen: { - route: RouteNames[Setting.EvalJS], - getComponent: () => EvalJSSettingScreen, - }, -} - -export default EvalJSSetting diff --git a/src/plugins/start/developer-kit/definitions/RDTAutoConnectSetting.tsx b/src/plugins/start/developer-kit/definitions/RDTAutoConnectSetting.tsx deleted file mode 100644 index 3c49412..0000000 --- a/src/plugins/start/developer-kit/definitions/RDTAutoConnectSetting.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { api } from '..' -import { Setting } from '../constants' -import { RDTContext } from '../react-devtools' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const RDTAutoConnectSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - IconComponent: () => , - useTitle: () => 'Auto-connect to React DevTools', - useDescription: () => - 'Automatically connect to React DevTools during startup.', - usePredicate: () => RDTContext.active, - useValue: () => - api.jsonStorage.use(s => s.reactDevTools?.autoConnect !== undefined)! - .reactDevTools.autoConnect, - onValueChange: v => { - api.jsonStorage.set({ reactDevTools: { autoConnect: v } }) - }, - type: 'toggle', -} - -export default RDTAutoConnectSetting diff --git a/src/plugins/start/developer-kit/definitions/RDTConnectSetting.tsx b/src/plugins/start/developer-kit/definitions/RDTConnectSetting.tsx deleted file mode 100644 index 0054970..0000000 --- a/src/plugins/start/developer-kit/definitions/RDTConnectSetting.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { Setting } from '../constants' -import { connect, RDTContext, useIsConnected } from '../react-devtools' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const RDTConnectSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - IconComponent: () => , - useTitle: () => 'Connect to React DevTools', - useDescription: () => `Version: ${globalThis.__REACT_DEVTOOLS__?.version}`, - usePredicate: () => !useIsConnected() && RDTContext.active, - onPress: connect, - type: 'pressable', -} - -export default RDTConnectSetting diff --git a/src/plugins/start/developer-kit/definitions/RDTDisconnectSetting.tsx b/src/plugins/start/developer-kit/definitions/RDTDisconnectSetting.tsx deleted file mode 100644 index 740cbea..0000000 --- a/src/plugins/start/developer-kit/definitions/RDTDisconnectSetting.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { Setting } from '../constants' -import { disconnect, useIsConnected } from '../react-devtools' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const RDTDisconnectSetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - IconComponent: () => , - variant: 'danger', - useTitle: () => 'Disconnect from React DevTools', - usePredicate: useIsConnected, - onPress: disconnect, - type: 'pressable', -} - -export default RDTDisconnectSetting diff --git a/src/plugins/start/developer-kit/definitions/RevengeDeveloperSetting.tsx b/src/plugins/start/developer-kit/definitions/RevengeDeveloperSetting.tsx deleted file mode 100644 index d89f5cb..0000000 --- a/src/plugins/start/developer-kit/definitions/RevengeDeveloperSetting.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { RouteNames, Setting } from '../constants' -import defer * as RevengeDeveloperSettingScreen from '../screens/RevengeDeveloperSettingScreen' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const RevengeDeveloperSetting: SettingsItem = { - parent: null, - type: 'route', - IconComponent: () => , - useTitle: () => 'Developer', - screen: { - route: RouteNames[Setting.RevengeDeveloper], - getComponent: () => RevengeDeveloperSettingScreen.default, - }, -} - -export default RevengeDeveloperSetting diff --git a/src/plugins/start/developer-kit/definitions/TestErrorBoundarySetting.tsx b/src/plugins/start/developer-kit/definitions/TestErrorBoundarySetting.tsx deleted file mode 100644 index 85e3bb9..0000000 --- a/src/plugins/start/developer-kit/definitions/TestErrorBoundarySetting.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { RouteNames, Setting } from '../constants' -import defer * as TestErrorBoundarySettingScreen from '../screens/TestErrorBoundarySettingScreen' -import type { SettingsItem } from '@revenge-mod/discord/modules/settings' - -const TestErrorBoundarySetting: SettingsItem = { - parent: Setting.RevengeDeveloper, - type: 'route', - variant: 'danger', - IconComponent: () => ( - - ), - useTitle: () => 'Test ErrorBoundary', - screen: { - route: RouteNames[Setting.TestErrorBoundary], - getComponent: () => TestErrorBoundarySettingScreen.default, - }, -} - -export default TestErrorBoundarySetting diff --git a/src/plugins/start/developer-kit/devtools.ts b/src/plugins/start/developer-kit/devtools.ts deleted file mode 100644 index 9a9284e..0000000 --- a/src/plugins/start/developer-kit/devtools.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { DevToolsClient } from '@revenge-mod/devtools-client' -import { LogLevel } from '@revenge-mod/devtools-shared/constants' -import { ToastActionCreators } from '@revenge-mod/discord/actions' -import { TypedEventEmitter } from '@revenge-mod/discord/common/utils' -import { ClientInfoModule } from '@revenge-mod/discord/native' -import { getBridgeInfo } from '@revenge-mod/modules/native' -import { instead } from '@revenge-mod/patcher' -import { noop } from '@revenge-mod/utils/callback' -import { lookupGeneratedIconComponent } from '@revenge-mod/utils/discord' -import { useReRender } from '@revenge-mod/utils/react' -import { useEffect } from 'react' -import { api } from '.' -import type { UnpatchFunction } from '@revenge-mod/patcher/types' - -export const DTContext: { - client: DevToolsClient | null - addr: string - alias: string - con: boolean -} = { - client: null, - addr: 'localhost:7684', - alias: '', - con: false, -} - -const events = new TypedEventEmitter<{ - connect: [] - disconnect: [] - errored: [unknown] -}>() - -const CircleErrorIcon = lookupGeneratedIconComponent( - 'CircleErrorIcon', - 'CircleErrorIcon-secondary', - 'CircleErrorIcon-primary', -) - -let intercepted = false - -function interceptLogging() { - if (intercepted) return noop - - intercepted = true - const unpatches: UnpatchFunction[] = [] - - for (const [key, level] of [ - ['log', LogLevel.Default], - ['warn', LogLevel.Warn], - ['error', LogLevel.Error], - ['info', LogLevel.Default], - ['debug', LogLevel.Debug], - ] as const) { - unpatches.push( - instead(console, key, (args, orig) => { - if (DTContext.con && DTContext.client) - DTContext.client.log(level, args) - return Reflect.apply(orig, console, args) - }), - ) - } - - return () => { - intercepted = false - for (const unpatch of unpatches) unpatch() - } -} - -export function connect() { - const Bridge = getBridgeInfo() - const Client = ClientInfoModule.getConstants() - - const client = (DTContext.client = new DevToolsClient()) - client.expose('api', api) - client.expose('cleanup', api.cleanup) - client.expose('logger', api.logger) - client.expose('revenge', api.unscoped) - - client.connect( - `ws://${DTContext.addr}`, - `${Client.Version}${Bridge ? ` (${Bridge.name} ${Bridge.version})` : ''}`, - DTContext.alias || undefined, - ) - - const ws = client.ws! - - ws.addEventListener('open', () => { - if (client.settings.log.interceptConsole) { - const unintercept = interceptLogging() - - ws.addEventListener('close', function self() { - unintercept() - ws.removeEventListener('close', self) - }) - } - - DTContext.con = true - events.emit('connect') - }) - - ws.addEventListener('close', e_ => { - cleanup() - events.emit('disconnect') - - const e = e_ as CloseEvent - if (!e.wasClean) { - api.logger.error('DevTools error:', e.reason) - - ToastActionCreators.open({ - key: 'DEVTOOLS_ERROR', - IconComponent: CircleErrorIcon, - content: e.reason, - }) - } - }) -} - -function cleanup() { - DTContext.client = null - DTContext.con = false -} - -export function disconnect() { - DTContext.client?.disconnect() -} - -export function useIsConnected() { - const rerender = useReRender() - - useEffect(() => { - events.on('connect', rerender) - events.on('disconnect', rerender) - - return () => { - events.off('connect', rerender) - events.off('disconnect', rerender) - } - }, [rerender]) - - return DTContext.con -} diff --git a/src/plugins/start/developer-kit/index.ts b/src/plugins/start/developer-kit/index.ts deleted file mode 100644 index 882a351..0000000 --- a/src/plugins/start/developer-kit/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { - onSettingsModulesLoaded, - refreshSettings, -} from '@revenge-mod/discord/modules/settings' -import { - InternalPluginFlags, - isPluginStartedLate, - PluginFlags, - registerInternalPlugin, -} from '@revenge-mod/plugins/_' -import pluginSettings from '../settings' -import * as dt from './devtools' -import defer * as rdt from './react-devtools' -import defer * as utils from './utils' -import type { PluginApi } from '@revenge-mod/plugins/types' - -interface Storage { - devTools: DevToolsSettings & { alias?: string } - reactDevTools: DevToolsSettings -} - -interface DevToolsSettings { - address: string - autoConnect: boolean -} - -const defaultStorage: Storage = { - devTools: { - address: 'localhost:7864', - autoConnect: false, - }, - reactDevTools: { - address: 'localhost:8097', - autoConnect: false, - }, -} - -// TODO(PalmDevs): only register in development builds once updates can be made automatic -registerInternalPlugin<{ jsonStorage: Storage }>( - { - id: 'revenge.developer-kit', - name: 'Developer Kit', - description: 'Tools assisting Revenge developers.', - author: 'Revenge', - icon: 'WrenchIcon', - dependencies: { [pluginSettings]: {} }, - }, - { - jsonStorage: { - load: true, - default: defaultStorage, - }, - async start(api_) { - api = api_ - - onSettingsModulesLoaded(utils.register) - - if (isPluginStartedLate(api_.plugin)) { - refreshSettings() - } - - const settings = await api.jsonStorage.get() - - dt.DTContext.addr = settings.devTools.address - dt.DTContext.alias = settings.devTools.alias ?? '' - rdt.RDTContext.addr = settings.reactDevTools.address - - if (settings.devTools.autoConnect) dt.connect() - if (settings.reactDevTools.autoConnect) rdt.connect() - }, - stop({ cleanup }) { - cleanup(refreshSettings) - }, - }, - PluginFlags.Enabled, - InternalPluginFlags.Internal, -) - -// Expose to EvalJSSetting -export let api: PluginApi<{ jsonStorage: Storage }> diff --git a/src/plugins/start/developer-kit/react-devtools.ts b/src/plugins/start/developer-kit/react-devtools.ts deleted file mode 100644 index dc0ae97..0000000 --- a/src/plugins/start/developer-kit/react-devtools.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ToastActionCreators } from '@revenge-mod/discord/actions' -import { TypedEventEmitter } from '@revenge-mod/discord/common/utils' -import { lookupGeneratedIconComponent } from '@revenge-mod/utils/discord' -import { useReRender } from '@revenge-mod/utils/react' -import { useEffect } from 'react' -import { api } from '.' - -export const RDTContext: { - ws: WebSocket | undefined - addr: string - con: boolean - active: boolean -} = { - active: Boolean(globalThis.__REACT_DEVTOOLS__), - ws: undefined, - addr: 'localhost:8097', - con: false, -} - -const events = new TypedEventEmitter<{ - connect: [] - disconnect: [] - errored: [unknown] -}>() - -const CircleErrorIcon = lookupGeneratedIconComponent( - 'CircleErrorIcon', - 'CircleErrorIcon-secondary', - 'CircleErrorIcon-primary', -) - -export function connect() { - if (!RDTContext.active || RDTContext.ws) return - - const ws = (RDTContext.ws = new WebSocket(`ws://${RDTContext.addr}`)) - - ws.addEventListener('open', () => { - RDTContext.con = true - events.emit('connect') - }) - - ws.addEventListener('close', e_ => { - cleanup() - events.emit('disconnect') - - const e = e_ as CloseEvent - if (!e.wasClean) { - api.logger.error('React DevTools error:', e.reason) - - ToastActionCreators.open({ - key: 'REACT_DEVTOOLS_ERROR', - IconComponent: CircleErrorIcon, - content: e.reason, - }) - } - }) - - __REACT_DEVTOOLS__!.exports.connectToDevTools({ - websocket: ws, - }) -} - -function cleanup() { - RDTContext.con = false - RDTContext.ws = undefined -} - -export function disconnect() { - if (RDTContext.ws) RDTContext.ws.close() -} - -export function useIsConnected() { - const rerender = useReRender() - - useEffect(() => { - events.on('connect', rerender) - events.on('disconnect', rerender) - - return () => { - events.off('connect', rerender) - events.off('disconnect', rerender) - } - }, [rerender]) - - return RDTContext.con -} diff --git a/src/plugins/start/developer-kit/screens/AssetBrowserSettingScreen.tsx b/src/plugins/start/developer-kit/screens/AssetBrowserSettingScreen.tsx deleted file mode 100644 index dd52f95..0000000 --- a/src/plugins/start/developer-kit/screens/AssetBrowserSettingScreen.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import { getAssets } from '@revenge-mod/assets' -import Page from '@revenge-mod/components/Page' -import SearchInput from '@revenge-mod/components/SearchInput' -import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' -import { - AlertActionCreators, - ToastActionCreators, -} from '@revenge-mod/discord/actions' -import { Design } from '@revenge-mod/discord/design' -import { Clipboard } from '@revenge-mod/externals/react-native-clipboard' -import { debounce } from '@revenge-mod/utils/callback' -import { lookupGeneratedIconComponent } from '@revenge-mod/utils/discord' -import { FlashList } from '@shopify/flash-list' -import { useCallback, useMemo, useState } from 'react' -import { Image, StyleSheet, View } from 'react-native' -import type { Asset, AssetId } from '@revenge-mod/assets/types' -import type { Metro } from '@revenge-mod/modules/types' - -const { AlertModal, AlertActionButton, TableRow, TableRowGroup, Text } = Design - -const Displayable = new Set(['png', 'jpg', 'svg', 'webp']) -const UndisplayableFallback = { - jsona: 'PaperIcon', - lottie: 'ImageFileIcon', - webm: 'CirclePlayIcon-primary', - ttf: 'LanguageIcon', - default: 'UnknownGameIcon', -} - -export default function AssetBrowserSettingScreen() { - const [search, setSearch] = useState('') - const debouncedSetSearch = useCallback(debounce(setSearch, 100), []) - const assets = useMemo(() => [...getAssets()], []) - - const filteredAssets = useMemo( - () => - !search.length - ? assets - : assets.filter(asset => - asset.name.toLowerCase().includes(search.toLowerCase()), - ), - [assets, search], - ) - - return ( - - { - debouncedSetSearch(v) - }} - size="md" - /> - - asset.id - ? asset.id.toString() - : `${asset.name}.${asset.type}` - } - renderItem={({ item: asset, index }) => ( - - )} - /> - - ) -} - -function AssetDisplay({ - id, - moduleId, - asset, - start, - end, -}: { - id: AssetId - moduleId?: Metro.ModuleID - asset: Asset - start?: boolean - end?: boolean -}) { - const isDisplayable = Displayable.has(asset.type) - const metadata = [ - ['ID', id.toString()], - ['Type', asset.type], - ] as [string, string, unpressable?: boolean, hiddenInText?: boolean][] - - metadata.push( - moduleId - ? ['Module ID', moduleId.toString()] - : [ - 'Custom asset', - 'This is a custom asset registered by a plugin.', - true, - true, - ], - ) - - return ( - - ) : ( - - ) - } - label={asset.name} - onPress={() => { - openAssetDisplayAlert(asset, id, metadata) - }} - start={start} - subLabel={metadata - .filter(([, , , hiddenInText]) => !hiddenInText) - .map(([name, value]) => `${name}: ${value ?? 'N/A'}`) - .join(' • ')} - variant={isDisplayable ? 'default' : 'danger'} - /> - ) -} - -const CopyIcon = lookupGeneratedIconComponent('CopyIcon') - -function openAssetDisplayAlert( - asset: Asset, - id: AssetId, - metadata: [string, string, unpressable?: boolean, ...unknown[]][], -) { - const isDisplayable = Displayable.has(asset.type) - - AlertActionCreators.openAlert( - 'asset-display', - } - title={ - - {isDisplayable ? ( - - ) : ( - - )} - - } - extraContent={ - <> - - {[['Name', asset.name], ...metadata].map( - ([name, value, unpressable]) => ( - { - Clipboard.setString(value) - - ToastActionCreators.open({ - key: 'ASSET_BROWSER_COPIED', - IconComponent: CopyIcon, - content: `Copied ${name} to clipboard`, - }) - } - } - subLabel={value} - /> - ), - )} - - - Note: Asset IDs and module IDs are not consistent - between app launches and app versions respectively and - should only be used when absolutely needed. - - - } - />, - ) -} - -function PreviewUnavailable({ type }: { type: string }) { - return ( - - Asset type {type.toUpperCase()} is not supported for preview. - - ) -} - -const styles = StyleSheet.create({ - listContainer: { - paddingBottom: 16, - }, - smallPreview: { - height: 32, - width: 32, - }, - preview: { - flex: 1, - width: 'auto', - height: 192, - resizeMode: 'contain', - }, - centeredText: { - width: '100%', - textAlign: 'center', - }, -}) diff --git a/src/plugins/start/developer-kit/screens/EvalJSSettingScreen.tsx b/src/plugins/start/developer-kit/screens/EvalJSSettingScreen.tsx deleted file mode 100644 index 25fbe93..0000000 --- a/src/plugins/start/developer-kit/screens/EvalJSSettingScreen.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import { Page } from '@revenge-mod/components' -import { Design } from '@revenge-mod/discord/design' -import { nodeUtil } from '@revenge-mod/externals/browserify' -import { getErrorStack } from '@revenge-mod/utils/error' -import { sleep } from '@revenge-mod/utils/promise' -import { useRef, useState } from 'react' -import { ScrollView } from 'react-native' -import { api } from '..' - -const { - Button, - Card, - Slider, - Stack, - TableRow, - TableRowGroup, - TableSwitchRow, - Text, - TextArea, -} = Design - -export default function EvalJSSettingScreen() { - const code = useRef('') - const [result, setResult] = useState('') - const [awaitResult, setAwaitResult] = useState(true) - const [showHidden, setShowHidden] = useState(true) - const [inspectDepth, setInspectDepth] = useState(3) - const [wordWrap, setWordWrap] = useState(true) - - return ( - - -