fix(plugins): remove developer-kit
This plugin has been moved to an external repository. The goal of bundling internal plugins are including what's needed by _the user_ by default. Developer Kit is not needed by most users, nor is it a "safe" plugin (it exposes a few attack surfaces, even if unlikely to be used).
This commit is contained in:
parent
0f75551c36
commit
b258ac70d6
21 changed files with 0 additions and 1137 deletions
14
bun.lock
14
bun.lock
|
|
@ -7,8 +7,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@revenge-mod/assets": "workspace:*",
|
"@revenge-mod/assets": "workspace:*",
|
||||||
"@revenge-mod/components": "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/discord": "workspace:*",
|
||||||
"@revenge-mod/externals": "workspace:*",
|
"@revenge-mod/externals": "workspace:*",
|
||||||
"@revenge-mod/json-storage": "workspace:*",
|
"@revenge-mod/json-storage": "workspace:*",
|
||||||
|
|
@ -210,10 +208,6 @@
|
||||||
|
|
||||||
"@revenge-mod/components": ["@revenge-mod/components@workspace:lib/components"],
|
"@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/discord": ["@revenge-mod/discord@workspace:lib/discord"],
|
||||||
|
|
||||||
"@revenge-mod/externals": ["@revenge-mod/externals@workspace:lib/externals"],
|
"@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": ["@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-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=="],
|
"@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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@revenge-mod/assets": "workspace:*",
|
"@revenge-mod/assets": "workspace:*",
|
||||||
"@revenge-mod/components": "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/discord": "workspace:*",
|
||||||
"@revenge-mod/externals": "workspace:*",
|
"@revenge-mod/externals": "workspace:*",
|
||||||
"@revenge-mod/json-storage": "workspace:*",
|
"@revenge-mod/json-storage": "workspace:*",
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="ImageIcon" />,
|
|
||||||
useTitle: () => 'Asset Browser',
|
|
||||||
screen: {
|
|
||||||
route: RouteNames[Setting.AssetBrowser],
|
|
||||||
getComponent: () => AssetBrowserSettingScreen.default,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AssetBrowserSetting
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="LinkIcon" />,
|
|
||||||
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
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="LinkIcon" />,
|
|
||||||
useTitle: () => 'Connect to DevTools',
|
|
||||||
useDescription: () => `Version: ${DevToolsClient.version}`,
|
|
||||||
usePredicate: () => !useIsConnected(),
|
|
||||||
onPress: connect,
|
|
||||||
type: 'pressable',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DTConnectSetting
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="DenyIcon" variant="danger" />,
|
|
||||||
variant: 'danger',
|
|
||||||
useTitle: () => 'Disconnect from DevTools',
|
|
||||||
usePredicate: useIsConnected,
|
|
||||||
onPress: disconnect,
|
|
||||||
type: 'pressable',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DTDisconnectSetting
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="FileIcon" />,
|
|
||||||
useTitle: () => 'Evaluate JavaScript',
|
|
||||||
useDescription: () => 'Runs a JavaScript code snippet.',
|
|
||||||
screen: {
|
|
||||||
route: RouteNames[Setting.EvalJS],
|
|
||||||
getComponent: () => EvalJSSettingScreen,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default EvalJSSetting
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="LinkIcon" />,
|
|
||||||
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
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="LinkIcon" />,
|
|
||||||
useTitle: () => 'Connect to React DevTools',
|
|
||||||
useDescription: () => `Version: ${globalThis.__REACT_DEVTOOLS__?.version}`,
|
|
||||||
usePredicate: () => !useIsConnected() && RDTContext.active,
|
|
||||||
onPress: connect,
|
|
||||||
type: 'pressable',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RDTConnectSetting
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="DenyIcon" variant="danger" />,
|
|
||||||
variant: 'danger',
|
|
||||||
useTitle: () => 'Disconnect from React DevTools',
|
|
||||||
usePredicate: useIsConnected,
|
|
||||||
onPress: disconnect,
|
|
||||||
type: 'pressable',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RDTDisconnectSetting
|
|
||||||
|
|
@ -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: () => <TableRowAssetIcon name="WrenchIcon" />,
|
|
||||||
useTitle: () => 'Developer',
|
|
||||||
screen: {
|
|
||||||
route: RouteNames[Setting.RevengeDeveloper],
|
|
||||||
getComponent: () => RevengeDeveloperSettingScreen.default,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RevengeDeveloperSetting
|
|
||||||
|
|
@ -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: () => (
|
|
||||||
<TableRowAssetIcon name="ScreenXIcon" variant="danger" />
|
|
||||||
),
|
|
||||||
useTitle: () => 'Test ErrorBoundary',
|
|
||||||
screen: {
|
|
||||||
route: RouteNames[Setting.TestErrorBoundary],
|
|
||||||
getComponent: () => TestErrorBoundarySettingScreen.default,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TestErrorBoundarySetting
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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 }>
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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 (
|
|
||||||
<Page spacing={16}>
|
|
||||||
<SearchInput
|
|
||||||
onChange={(v: string) => {
|
|
||||||
debouncedSetSearch(v)
|
|
||||||
}}
|
|
||||||
size="md"
|
|
||||||
/>
|
|
||||||
<FlashList
|
|
||||||
data={filteredAssets}
|
|
||||||
contentContainerStyle={styles.listContainer}
|
|
||||||
fadingEdgeLength={32}
|
|
||||||
keyExtractor={asset =>
|
|
||||||
asset.id
|
|
||||||
? asset.id.toString()
|
|
||||||
: `${asset.name}.${asset.type}`
|
|
||||||
}
|
|
||||||
renderItem={({ item: asset, index }) => (
|
|
||||||
<AssetDisplay
|
|
||||||
asset={asset}
|
|
||||||
end={index === filteredAssets.length - 1}
|
|
||||||
id={asset.id}
|
|
||||||
moduleId={asset.moduleId}
|
|
||||||
start={!index}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Page>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<TableRow
|
|
||||||
end={end}
|
|
||||||
icon={
|
|
||||||
isDisplayable ? (
|
|
||||||
<Image source={id} style={styles.smallPreview} />
|
|
||||||
) : (
|
|
||||||
<TableRowAssetIcon
|
|
||||||
name={
|
|
||||||
asset.type in UndisplayableFallback
|
|
||||||
? UndisplayableFallback[
|
|
||||||
asset.type as keyof typeof UndisplayableFallback
|
|
||||||
]
|
|
||||||
: UndisplayableFallback.default
|
|
||||||
}
|
|
||||||
variant="danger"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
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',
|
|
||||||
<AlertModal
|
|
||||||
actions={<AlertActionButton text="Close" variant="secondary" />}
|
|
||||||
title={
|
|
||||||
<View style={{ flex: 1, width: '100%' }}>
|
|
||||||
{isDisplayable ? (
|
|
||||||
<Image source={id} style={styles.preview} />
|
|
||||||
) : (
|
|
||||||
<PreviewUnavailable type={asset.type} />
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
extraContent={
|
|
||||||
<>
|
|
||||||
<TableRowGroup>
|
|
||||||
{[['Name', asset.name], ...metadata].map(
|
|
||||||
([name, value, unpressable]) => (
|
|
||||||
<TableRow
|
|
||||||
key={id}
|
|
||||||
label={name}
|
|
||||||
onPress={
|
|
||||||
unpressable
|
|
||||||
? undefined
|
|
||||||
: () => {
|
|
||||||
Clipboard.setString(value)
|
|
||||||
|
|
||||||
ToastActionCreators.open({
|
|
||||||
key: 'ASSET_BROWSER_COPIED',
|
|
||||||
IconComponent: CopyIcon,
|
|
||||||
content: `Copied ${name} to clipboard`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
subLabel={value}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</TableRowGroup>
|
|
||||||
<Text
|
|
||||||
color="text-feedback-critical"
|
|
||||||
variant="text-xs/semibold"
|
|
||||||
>
|
|
||||||
Note: Asset IDs and module IDs are not consistent
|
|
||||||
between app launches and app versions respectively and
|
|
||||||
should only be used when absolutely needed.
|
|
||||||
</Text>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function PreviewUnavailable({ type }: { type: string }) {
|
|
||||||
return (
|
|
||||||
<Text
|
|
||||||
color="text-feedback-critical"
|
|
||||||
style={styles.centeredText}
|
|
||||||
variant="text-sm/medium"
|
|
||||||
>
|
|
||||||
Asset type {type.toUpperCase()} is not supported for preview.
|
|
||||||
</Text>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
@ -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 (
|
|
||||||
<ScrollView contentContainerStyle={{ paddingBottom: 32 }}>
|
|
||||||
<Page spacing={16}>
|
|
||||||
<TextArea
|
|
||||||
autoFocus
|
|
||||||
label="Code"
|
|
||||||
onChange={v => {
|
|
||||||
code.current = v
|
|
||||||
}}
|
|
||||||
placeholder="revenge.discord.native.BundleUpdaterManager.reload()"
|
|
||||||
size="md"
|
|
||||||
/>
|
|
||||||
<TableRowGroup title="Inspection Options">
|
|
||||||
<TableSwitchRow
|
|
||||||
label="Await result"
|
|
||||||
onValueChange={setAwaitResult}
|
|
||||||
subLabel="Wait for the result of the code before displaying it."
|
|
||||||
value={awaitResult}
|
|
||||||
/>
|
|
||||||
<TableSwitchRow
|
|
||||||
label="Show hidden"
|
|
||||||
onValueChange={setShowHidden}
|
|
||||||
subLabel="Show hidden properties of the object."
|
|
||||||
value={showHidden}
|
|
||||||
/>
|
|
||||||
<TableRow
|
|
||||||
label="Inspect depth"
|
|
||||||
subLabel="The depth of the object to inspect."
|
|
||||||
trailing={
|
|
||||||
<Text variant="text-sm/normal">{inspectDepth}</Text>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</TableRowGroup>
|
|
||||||
<Slider
|
|
||||||
endIcon={<Text variant="text-sm/normal">10</Text>}
|
|
||||||
maximumValue={10}
|
|
||||||
minimumValue={0}
|
|
||||||
onValueChange={setInspectDepth}
|
|
||||||
startIcon={<Text variant="text-sm/normal">0</Text>}
|
|
||||||
step={1}
|
|
||||||
value={inspectDepth}
|
|
||||||
/>
|
|
||||||
<TableRowGroup title="Display Options">
|
|
||||||
<TableSwitchRow
|
|
||||||
label="Word wrap"
|
|
||||||
subLabel="Long results will wrap to the next line."
|
|
||||||
onValueChange={setWordWrap}
|
|
||||||
value={wordWrap}
|
|
||||||
/>
|
|
||||||
</TableRowGroup>
|
|
||||||
<Stack>
|
|
||||||
<Text variant="heading-sm/semibold" color="text-strong">
|
|
||||||
Result
|
|
||||||
</Text>
|
|
||||||
<Card>
|
|
||||||
{/* TODO: Maybe try to make it fill space with minHeight: 128? */}
|
|
||||||
<ScrollView
|
|
||||||
nestedScrollEnabled
|
|
||||||
style={{ maxHeight: 300 }}
|
|
||||||
>
|
|
||||||
<ScrollView
|
|
||||||
nestedScrollEnabled
|
|
||||||
horizontal={!wordWrap}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
selectable
|
|
||||||
style={{ fontFamily: 'monospace' }}
|
|
||||||
>
|
|
||||||
{result || '<empty>'}
|
|
||||||
</Text>
|
|
||||||
</ScrollView>
|
|
||||||
</ScrollView>
|
|
||||||
</Card>
|
|
||||||
</Stack>
|
|
||||||
<Button
|
|
||||||
onPress={async function onPress() {
|
|
||||||
const key = `_${Math.random()
|
|
||||||
.toString(36)
|
|
||||||
.substring(2, 15)}`
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!api) {
|
|
||||||
setResult(
|
|
||||||
'<Revenge API not available, snippet will be run without it...>',
|
|
||||||
)
|
|
||||||
|
|
||||||
await sleep(1000)
|
|
||||||
}
|
|
||||||
// @ts-expect-error
|
|
||||||
else globalThis[key] = api
|
|
||||||
|
|
||||||
// biome-ignore lint/security/noGlobalEval: Intentional
|
|
||||||
const res = (0, eval)(
|
|
||||||
`var api=${key},{unscoped:revenge}=api;undefined;${code.current}//# sourceURL=Revenge:EvalJS`,
|
|
||||||
)
|
|
||||||
|
|
||||||
setResult(
|
|
||||||
nodeUtil.inspect(
|
|
||||||
awaitResult ? await res : res,
|
|
||||||
{
|
|
||||||
depth: inspectDepth,
|
|
||||||
showHidden,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
delete globalThis[key]
|
|
||||||
} catch (e) {
|
|
||||||
setResult(getErrorStack(e))
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
text="Evaluate"
|
|
||||||
variant="primary"
|
|
||||||
/>
|
|
||||||
</Page>
|
|
||||||
</ScrollView>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
import { styles } from '@revenge-mod/components/_'
|
|
||||||
import { ToastActionCreators } from '@revenge-mod/discord/actions'
|
|
||||||
import { Design } from '@revenge-mod/discord/design'
|
|
||||||
import { SettingListRenderer } from '@revenge-mod/discord/modules/settings/renderer'
|
|
||||||
import { lookupGeneratedIconComponent } from '@revenge-mod/utils/discord'
|
|
||||||
import { StyleSheet, View } from 'react-native'
|
|
||||||
import { api } from '..'
|
|
||||||
import { Setting } from '../constants'
|
|
||||||
import { DTContext, useIsConnected as useIsDTConnected } from '../devtools'
|
|
||||||
import {
|
|
||||||
RDTContext,
|
|
||||||
useIsConnected as useIsRDTConnected,
|
|
||||||
} from '../react-devtools'
|
|
||||||
|
|
||||||
const CircleCheckIcon = lookupGeneratedIconComponent(
|
|
||||||
'CircleCheckIcon',
|
|
||||||
'CircleCheckIcon-secondary',
|
|
||||||
'CircleCheckIcon-primary',
|
|
||||||
)
|
|
||||||
|
|
||||||
import { ScrollView } from 'react-native'
|
|
||||||
|
|
||||||
const listStyles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flexGrow: 0,
|
|
||||||
flexShrink: 0,
|
|
||||||
height: 'auto',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function RevengeDeveloperSettingScreen() {
|
|
||||||
return (
|
|
||||||
<ScrollView style={styles.flex}>
|
|
||||||
<Design.Stack spacing={8}>
|
|
||||||
<View>
|
|
||||||
<SettingListRenderer.SettingsList
|
|
||||||
containerStyle={listStyles.container}
|
|
||||||
node={{
|
|
||||||
type: 'list',
|
|
||||||
ListHeaderComponent: DTConnectionSetting,
|
|
||||||
sections: [
|
|
||||||
{
|
|
||||||
settings: [
|
|
||||||
Setting.DTAutoConnect,
|
|
||||||
Setting.DTConnect,
|
|
||||||
Setting.DTDisconnect,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View>
|
|
||||||
<SettingListRenderer.SettingsList
|
|
||||||
containerStyle={listStyles.container}
|
|
||||||
node={{
|
|
||||||
type: 'list',
|
|
||||||
ListHeaderComponent: RDTContext.active
|
|
||||||
? RDTAddrSetting
|
|
||||||
: undefined,
|
|
||||||
sections: [
|
|
||||||
{
|
|
||||||
settings: [
|
|
||||||
Setting.RDTAutoConnect,
|
|
||||||
Setting.RDTConnect,
|
|
||||||
Setting.RDTDisconnect,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Tools',
|
|
||||||
settings: [
|
|
||||||
Setting.EvalJS,
|
|
||||||
Setting.AssetBrowser,
|
|
||||||
Setting.TestErrorBoundary,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</Design.Stack>
|
|
||||||
</ScrollView>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function DTConnectionSetting() {
|
|
||||||
const open = useIsDTConnected()
|
|
||||||
const settings = api.jsonStorage.use(
|
|
||||||
s =>
|
|
||||||
s.devTools?.address !== undefined ||
|
|
||||||
s.devTools?.alias !== undefined,
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Design.TextInput
|
|
||||||
defaultValue={settings?.devTools.address ?? DTContext.addr}
|
|
||||||
editable={!open}
|
|
||||||
isDisabled={open}
|
|
||||||
label="DevTools"
|
|
||||||
leadingText="ws://"
|
|
||||||
onBlur={() =>
|
|
||||||
api.jsonStorage
|
|
||||||
.set({
|
|
||||||
devTools: {
|
|
||||||
address: DTContext.addr,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() =>
|
|
||||||
ToastActionCreators.open({
|
|
||||||
IconComponent: CircleCheckIcon,
|
|
||||||
key: 'DEVTOOLS_ADDRESS_SAVED',
|
|
||||||
content: 'Address saved',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onChange={text => {
|
|
||||||
DTContext.addr = text
|
|
||||||
}}
|
|
||||||
returnKeyType="done"
|
|
||||||
/>
|
|
||||||
<Design.TextInput
|
|
||||||
defaultValue={settings?.devTools.alias ?? DTContext.alias}
|
|
||||||
editable={!open}
|
|
||||||
isDisabled={open}
|
|
||||||
label="DevTools Alias"
|
|
||||||
onBlur={() =>
|
|
||||||
api.jsonStorage
|
|
||||||
.set({
|
|
||||||
devTools: {
|
|
||||||
alias: DTContext.alias,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() =>
|
|
||||||
ToastActionCreators.open({
|
|
||||||
IconComponent: CircleCheckIcon,
|
|
||||||
key: 'DEVTOOLS_ALIAS_SAVED',
|
|
||||||
content: 'Alias saved',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onChange={text => {
|
|
||||||
DTContext.alias = text
|
|
||||||
}}
|
|
||||||
returnKeyType="done"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function RDTAddrSetting() {
|
|
||||||
const open = useIsRDTConnected()
|
|
||||||
const settings = api.jsonStorage.use(s => s.reactDevTools?.address)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Design.TextInput
|
|
||||||
defaultValue={settings?.reactDevTools.address ?? RDTContext.addr}
|
|
||||||
editable={!open}
|
|
||||||
isDisabled={open}
|
|
||||||
label="React DevTools"
|
|
||||||
leadingText="ws://"
|
|
||||||
onBlur={() =>
|
|
||||||
api.jsonStorage
|
|
||||||
.set({
|
|
||||||
reactDevTools: {
|
|
||||||
address: RDTContext.addr,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() =>
|
|
||||||
ToastActionCreators.open({
|
|
||||||
IconComponent: CircleCheckIcon,
|
|
||||||
key: 'REACT_DEVTOOLS_ADDRESS_SAVED',
|
|
||||||
content: 'Address saved',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onChange={text => {
|
|
||||||
RDTContext.addr = text
|
|
||||||
}}
|
|
||||||
returnKeyType="done"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
import { useEffect } from 'react'
|
|
||||||
|
|
||||||
export default function TestErrorBoundarySettingScreen() {
|
|
||||||
let x = 0
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
x++
|
|
||||||
})
|
|
||||||
|
|
||||||
// @ts-expect-error: Intentional
|
|
||||||
return x < 2 ? <undefined /> : null
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import {
|
|
||||||
addSettingsItemToSection,
|
|
||||||
registerSettingsItems,
|
|
||||||
} from '@revenge-mod/discord/modules/settings'
|
|
||||||
import { api } from '.'
|
|
||||||
import { Setting } from './constants'
|
|
||||||
import AssetBrowserSetting from './definitions/AssetBrowserSetting'
|
|
||||||
import DTAutoConnectSetting from './definitions/DTAutoConnectSetting'
|
|
||||||
import DTConnectSetting from './definitions/DTConnectSetting'
|
|
||||||
import DTDisconnectSetting from './definitions/DTDisconnectSetting'
|
|
||||||
import EvalJSSetting from './definitions/EvalJSSetting'
|
|
||||||
import RDTAutoConnectSetting from './definitions/RDTAutoConnectSetting'
|
|
||||||
import RDTConnectSetting from './definitions/RDTConnectSetting'
|
|
||||||
import RDTDisconnectSetting from './definitions/RDTDisconnectSetting'
|
|
||||||
import RevengeDeveloperSetting from './definitions/RevengeDeveloperSetting'
|
|
||||||
import TestErrorBoundarySetting from './definitions/TestErrorBoundarySetting'
|
|
||||||
|
|
||||||
export function register() {
|
|
||||||
api.cleanup(
|
|
||||||
registerSettingsItems({
|
|
||||||
[Setting.RevengeDeveloper]: RevengeDeveloperSetting,
|
|
||||||
[Setting.DTAutoConnect]: DTAutoConnectSetting,
|
|
||||||
[Setting.DTConnect]: DTConnectSetting,
|
|
||||||
[Setting.DTDisconnect]: DTDisconnectSetting,
|
|
||||||
[Setting.RDTAutoConnect]: RDTAutoConnectSetting,
|
|
||||||
[Setting.RDTConnect]: RDTConnectSetting,
|
|
||||||
[Setting.RDTDisconnect]: RDTDisconnectSetting,
|
|
||||||
[Setting.EvalJS]: EvalJSSetting,
|
|
||||||
[Setting.AssetBrowser]: AssetBrowserSetting,
|
|
||||||
[Setting.TestErrorBoundary]: TestErrorBoundarySetting,
|
|
||||||
}),
|
|
||||||
addSettingsItemToSection('REVENGE', Setting.RevengeDeveloper, -1),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue