diff --git a/bun.lock b/bun.lock index 72d8526..14ccc22 100644 --- a/bun.lock +++ b/bun.lock @@ -29,6 +29,9 @@ "lib/assets": { "name": "@revenge-mod/assets", }, + "lib/components": { + "name": "@revenge-mod/components", + }, "lib/discord": { "name": "@revenge-mod/discord", }, @@ -437,6 +440,8 @@ "@revenge-mod/assets": ["@revenge-mod/assets@workspace:lib/assets"], + "@revenge-mod/components": ["@revenge-mod/components@workspace:lib/components"], + "@revenge-mod/discord": ["@revenge-mod/discord@workspace:lib/discord"], "@revenge-mod/externals": ["@revenge-mod/externals@workspace:lib/externals"], diff --git a/lib/assets/src/index.ts b/lib/assets/src/index.ts index 846d2a4..6ee41ad 100644 --- a/lib/assets/src/index.ts +++ b/lib/assets/src/index.ts @@ -1,4 +1,4 @@ -import { ReactNative } from '@revenge-mod/react' +import { Platform } from 'react-native' import { _customs, _overrides } from './_internal' import { cache } from './caches' import { AssetsRegistry } from './preinit' @@ -16,8 +16,7 @@ export { } from './preinit' // iOS cannot display SVGs -let _preferredType: Asset['type'] = - ReactNative.Platform.OS === 'ios' ? 'png' : 'svg' +let _preferredType: Asset['type'] = Platform.OS === 'ios' ? 'png' : 'svg' /** * Set the preferred asset type. This is used to determine which asset to use when multiple types are available. diff --git a/lib/components/package.json b/lib/components/package.json new file mode 100644 index 0000000..e71d27a --- /dev/null +++ b/lib/components/package.json @@ -0,0 +1,25 @@ +{ + "name": "@revenge-mod/components", + "private": true, + "type": "module", + "exports": { + "./FormSwitch": { + "default": "./src/FormSwitch.tsx" + }, + "./Page": { + "default": "./src/Page.tsx" + }, + "./SearchInput": { + "default": "./src/SearchInput.tsx" + }, + "./TableRowAssetIcon": { + "default": "./src/TableRowAssetIcon.tsx" + }, + "./init": { + "default": "./src/init.ts" + }, + "./types": { + "types": "./src/types.ts" + } + } +} diff --git a/src/components/FormSwitch.tsx b/lib/components/src/FormSwitch.tsx similarity index 67% rename from src/components/FormSwitch.tsx rename to lib/components/src/FormSwitch.tsx index 2faa857..85e1f8c 100644 --- a/src/components/FormSwitch.tsx +++ b/lib/components/src/FormSwitch.tsx @@ -1,5 +1,5 @@ import { FormSwitch as Switch } from '@revenge-mod/discord/design' -import { ReactNative } from '@revenge-mod/react' +import { StyleSheet, View } from 'react-native' import type { DiscordModules } from '@revenge-mod/discord/types' /** @@ -9,13 +9,13 @@ export default function FormSwitch( props: DiscordModules.Components.FormSwitchProps, ) { return ( - + - + ) } -const styles = ReactNative.StyleSheet.create({ +const styles = StyleSheet.create({ disabled: { opacity: 0.5, }, diff --git a/src/components/Page.tsx b/lib/components/src/Page.tsx similarity index 81% rename from src/components/Page.tsx rename to lib/components/src/Page.tsx index d417289..1678900 100644 --- a/src/components/Page.tsx +++ b/lib/components/src/Page.tsx @@ -1,5 +1,5 @@ import { Design } from '@revenge-mod/discord/design' -import { ReactNative } from '@revenge-mod/react' +import { StyleSheet } from 'react-native' import type { DiscordModules } from '@revenge-mod/discord/types' export default function Page(props: DiscordModules.Components.StackProps) { @@ -10,7 +10,7 @@ export default function Page(props: DiscordModules.Components.StackProps) { ) } -const styles = ReactNative.StyleSheet.create({ +const styles = StyleSheet.create({ page: { flex: 1, paddingHorizontal: 16, diff --git a/src/components/SearchInput.tsx b/lib/components/src/SearchInput.tsx similarity index 100% rename from src/components/SearchInput.tsx rename to lib/components/src/SearchInput.tsx diff --git a/src/components/TableRowAssetIcon.tsx b/lib/components/src/TableRowAssetIcon.tsx similarity index 100% rename from src/components/TableRowAssetIcon.tsx rename to lib/components/src/TableRowAssetIcon.tsx diff --git a/lib/components/src/index.ts b/lib/components/src/index.ts new file mode 100644 index 0000000..cd31643 --- /dev/null +++ b/lib/components/src/index.ts @@ -0,0 +1,4 @@ +export { default as FormSwitch } from './FormSwitch' +export { default as Page } from './Page' +export { default as SearchInput } from './SearchInput' +export { default as TableRowAssetIcon } from './TableRowAssetIcon' diff --git a/lib/components/src/init.ts b/lib/components/src/init.ts new file mode 100644 index 0000000..bee7837 --- /dev/null +++ b/lib/components/src/init.ts @@ -0,0 +1,11 @@ +/** biome-ignore-all lint/complexity/useArrowFunction: Rolldown issue: Bug requires us to use normal functions instead of arrow functions */ + +import { _uapi } from '@revenge-mod/plugins/_' +import { defineLazyProperty } from '@revenge-mod/utils/objects' +import type { UnscopedInitPluginApi } from '@revenge-mod/plugins/types' + +const uapi = _uapi as UnscopedInitPluginApi + +defineLazyProperty(uapi, 'components', function () { + return require('./index') +}) diff --git a/lib/components/src/types.ts b/lib/components/src/types.ts new file mode 100644 index 0000000..dbde261 --- /dev/null +++ b/lib/components/src/types.ts @@ -0,0 +1,12 @@ +export interface PluginApiComponents { + FormSwitch: typeof import('@revenge-mod/components/FormSwitch').default + Page: typeof import('@revenge-mod/components/Page').default + SearchInput: typeof import('@revenge-mod/components/SearchInput').default + TableRowAssetIcon: typeof import('@revenge-mod/components/TableRowAssetIcon').default +} + +declare module '@revenge-mod/plugins/types' { + export interface UnscopedInitPluginApi { + components: PluginApiComponents + } +} diff --git a/lib/storage/src/index.ts b/lib/storage/src/index.ts index bc5e59a..6c9b307 100644 --- a/lib/storage/src/index.ts +++ b/lib/storage/src/index.ts @@ -1,6 +1,7 @@ // TODO(storage): Implement using NativeModules interop instead import { FileModule } from '@revenge-mod/discord/native' +// This file is usually imported way too early, so we can't import our shim import { React } from '@revenge-mod/react' import { mergeDeep } from '@revenge-mod/utils/objects' import { useReRender } from '@revenge-mod/utils/react' diff --git a/lib/utils/src/react.ts b/lib/utils/src/react.ts index 5951fc8..4cc1b59 100644 --- a/lib/utils/src/react.ts +++ b/lib/utils/src/react.ts @@ -1,3 +1,4 @@ +// @revenge-mod/storage depends on this file, and it is imported way too early, so we can't import our shim import { React } from '@revenge-mod/react' import { findInTree } from './trees' import type { ReactNode } from 'react' diff --git a/scripts/build.ts b/scripts/build.ts index f732ebf..44c4c26 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -61,10 +61,21 @@ export default async function build(dev = false, log = true) { find: 'react/jsx-runtime', replacement: `${ShimsDir}/react~jsx-runtime.ts`, }, + // Do not move React to the top! + // If you do that, react/jsx-runtime would resolve to ${ShimsDir}/react.ts/jsx-runtime instead. + { + find: 'react', + replacement: `${ShimsDir}/react.ts`, + }, + { + find: 'react-native', + replacement: `${ShimsDir}/react-native.ts`, + }, ], }), importGlobPlugin(), swcPlugin(), + sourceURLPlugin(), hermesCPlugin({ flags: [ dev ? '-Og' : '-O', @@ -102,7 +113,6 @@ export default async function build(dev = false, log = true) { minify: {}, file: 'dist/revenge.js', format: 'iife', - footer: '//# sourceURL=Revenge', }) if (log) @@ -113,6 +123,18 @@ export default async function build(dev = false, log = true) { ) } +function sourceURLPlugin() { + return { + name: 'footer', + renderChunk(code) { + return { + code: `${code}\n//# sourceURL=Revenge`, + map: null, + } + }, + } satisfies RolldownPlugin +} + function swcPlugin() { return { name: 'swc', diff --git a/shims/react-native.ts b/shims/react-native.ts new file mode 100644 index 0000000..e0d31df --- /dev/null +++ b/shims/react-native.ts @@ -0,0 +1,3 @@ +import { ReactNative } from '@revenge-mod/react' + +module.exports = ReactNative diff --git a/shims/react.ts b/shims/react.ts new file mode 100644 index 0000000..5f263ed --- /dev/null +++ b/shims/react.ts @@ -0,0 +1,3 @@ +import { React } from '@revenge-mod/react' + +module.exports = React diff --git a/shims/react~jsx-runtime.ts b/shims/react~jsx-runtime.ts index 555ed21..b807092 100644 --- a/shims/react~jsx-runtime.ts +++ b/shims/react~jsx-runtime.ts @@ -19,4 +19,4 @@ const jsxs = ((type, ...args) => ...args, )) as typeof _jsxs -export { jsx, jsxs, Fragment } +module.exports = { jsx, jsxs, Fragment } diff --git a/src/index.ts b/src/index.ts index 0d3ce82..20e45d7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -37,6 +37,7 @@ onModuleFirstRequired(IndexModuleId, function onIndexRequired() { // Initialize init libraries require('@revenge-mod/externals/init') require('@revenge-mod/discord/init') + require('@revenge-mod/components/init') // Run all init plugins require('~/plugins/init') diff --git a/src/plugins/init/developer-settings/definitions/AssetBrowserSetting.tsx b/src/plugins/init/developer-settings/definitions/AssetBrowserSetting.tsx index 7b3d130..760893d 100644 --- a/src/plugins/init/developer-settings/definitions/AssetBrowserSetting.tsx +++ b/src/plugins/init/developer-settings/definitions/AssetBrowserSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { MobileSetting, UserSettingsSections } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/developer-settings/definitions/EvaluateJavaScriptSetting.tsx b/src/plugins/init/developer-settings/definitions/EvaluateJavaScriptSetting.tsx index 95b6546..e0b5c05 100644 --- a/src/plugins/init/developer-settings/definitions/EvaluateJavaScriptSetting.tsx +++ b/src/plugins/init/developer-settings/definitions/EvaluateJavaScriptSetting.tsx @@ -1,9 +1,9 @@ +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { AlertActionCreators } from '@revenge-mod/discord/actions' import { Design } from '@revenge-mod/discord/design' import { nodeUtil } from '@revenge-mod/externals/browserify' -import { React } from '@revenge-mod/react' import { getErrorStack } from '@revenge-mod/utils/errors' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import { useRef, useState } from 'react' import { api } from '..' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' @@ -34,11 +34,11 @@ const { } = Design function EvaluateJavaScriptAlert() { - const code = React.useRef('') - const [awaitResult, setAwaitResult] = React.useState(true) - const [showHidden, setShowHidden] = React.useState(true) - const [inspectDepth, setInspectDepth] = React.useState(3) - const [loading, setLoading] = React.useState(false) + const code = useRef('') + const [awaitResult, setAwaitResult] = useState(true) + const [showHidden, setShowHidden] = useState(true) + const [inspectDepth, setInspectDepth] = useState(3) + const [loading, setLoading] = useState(false) return ( { + useEffect(() => { const sub: Subscription = e => (e === 1 || e === 2) && rerender() subscriptions.add(sub) return () => { subscriptions.delete(sub) } - }, []) + }, [rerender]) return DevToolsContext.open } diff --git a/src/plugins/init/developer-settings/screens/AssetBrowserSettingScreen.tsx b/src/plugins/init/developer-settings/screens/AssetBrowserSettingScreen.tsx index 24113eb..e0eddf0 100644 --- a/src/plugins/init/developer-settings/screens/AssetBrowserSettingScreen.tsx +++ b/src/plugins/init/developer-settings/screens/AssetBrowserSettingScreen.tsx @@ -1,4 +1,7 @@ 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, @@ -6,15 +9,13 @@ import { import { Design } from '@revenge-mod/discord/design' import { Clipboard } from '@revenge-mod/externals/react-native-clipboard' import { FlashList } from '@revenge-mod/externals/shopify' -import { React, ReactNative } from '@revenge-mod/react' +import { debounce } from '@revenge-mod/utils/callbacks' import { lookupGeneratedIconComponent } from '@revenge-mod/utils/discord' -import Page from '~/components/Page' -import SearchInput from '~/components/SearchInput' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import { useCallback, useMemo, useState } from 'react' +import { Image, StyleSheet } from 'react-native' import type { Asset, AssetId } from '@revenge-mod/assets/types' import type { Metro } from '@revenge-mod/modules/types' -const { Image, StyleSheet } = ReactNative const { AlertModal, AlertActionButton, TableRow, TableRowGroup, Text } = Design const Displayable = new Set(['png', 'jpg', 'svg', 'webp']) @@ -27,10 +28,11 @@ const UndisplayableFallback = { } export default function AssetBrowserSettingScreen() { - const [search, setSearch] = React.useState('') - const assets = React.useMemo(() => [...getAssets()], [getAssets]) + const [search, setSearch] = useState('') + const debouncedSetSearch = useCallback(debounce(setSearch, 100), []) + const assets = useMemo(() => [...getAssets()], []) - const filteredAssets = React.useMemo( + const filteredAssets = useMemo( () => !search.length ? assets @@ -42,7 +44,10 @@ export default function AssetBrowserSettingScreen() { return ( - setSearch(v)} size="md" /> + debouncedSetSearch(v)} + size="md" + /> s.devtools?.address) return ( - + (DevToolsContext.address = text)} returnKeyType="done" /> - + ) } diff --git a/src/plugins/init/settings/definitions/HermesVersionSetting.tsx b/src/plugins/init/settings/definitions/HermesVersionSetting.tsx index 66de0a5..00b1c89 100644 --- a/src/plugins/init/settings/definitions/HermesVersionSetting.tsx +++ b/src/plugins/init/settings/definitions/HermesVersionSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/definitions/ReactNativeVersionSetting.tsx b/src/plugins/init/settings/definitions/ReactNativeVersionSetting.tsx index 7c609dc..2d41f47 100644 --- a/src/plugins/init/settings/definitions/ReactNativeVersionSetting.tsx +++ b/src/plugins/init/settings/definitions/ReactNativeVersionSetting.tsx @@ -1,10 +1,10 @@ -import { ReactNative } from '@revenge-mod/react' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' +import { Platform } from 'react-native' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' const { major, minor, patch, prerelease } = - ReactNative.Platform.constants.reactNativeVersion + Platform.constants.reactNativeVersion const version = `${major}.${minor}.${patch}${prerelease ? `-${prerelease}` : ''}` const ReactNativeVersionSetting: SettingsItem = { diff --git a/src/plugins/init/settings/definitions/ReactVersionSetting.tsx b/src/plugins/init/settings/definitions/ReactVersionSetting.tsx index 9a6acee..33e1300 100644 --- a/src/plugins/init/settings/definitions/ReactVersionSetting.tsx +++ b/src/plugins/init/settings/definitions/ReactVersionSetting.tsx @@ -1,5 +1,5 @@ -import { React } from '@revenge-mod/react' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' +import { version } from 'react' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' @@ -7,7 +7,7 @@ const ReactVersionSetting: SettingsItem = { parent: MobileSetting.REVENGE, IconComponent: () => , title: () => 'React', - useDescription: () => React.version, + useDescription: () => version, type: 'static', } diff --git a/src/plugins/init/settings/definitions/ReloadAppSetting.tsx b/src/plugins/init/settings/definitions/ReloadAppSetting.tsx index 7bcbd03..7a1847f 100644 --- a/src/plugins/init/settings/definitions/ReloadAppSetting.tsx +++ b/src/plugins/init/settings/definitions/ReloadAppSetting.tsx @@ -1,5 +1,5 @@ +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { BundleUpdaterManager } from '@revenge-mod/discord/native' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/definitions/RevengeDiscordServerSetting.tsx b/src/plugins/init/settings/definitions/RevengeDiscordServerSetting.tsx index b47127f..aba2730 100644 --- a/src/plugins/init/settings/definitions/RevengeDiscordServerSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeDiscordServerSetting.tsx @@ -1,5 +1,5 @@ -import { ReactNative } from '@revenge-mod/react' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' +import { Linking } from 'react-native' import { DiscordServerURL } from '~/constants' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' @@ -8,7 +8,7 @@ const RevengeDiscordServerSetting: SettingsItem = { parent: MobileSetting.REVENGE, IconComponent: () => , title: () => 'Discord Server', - onPress: () => ReactNative.Linking.openURL(DiscordServerURL), + onPress: () => Linking.openURL(DiscordServerURL), type: 'pressable', } diff --git a/src/plugins/init/settings/definitions/RevengeFontsSetting.tsx b/src/plugins/init/settings/definitions/RevengeFontsSetting.tsx index 66081b3..69b3df3 100644 --- a/src/plugins/init/settings/definitions/RevengeFontsSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeFontsSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { MobileSetting, UserSettingsSections } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/definitions/RevengeGitHubOrganizationSetting.tsx b/src/plugins/init/settings/definitions/RevengeGitHubOrganizationSetting.tsx index 12cf1ee..3957369 100644 --- a/src/plugins/init/settings/definitions/RevengeGitHubOrganizationSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeGitHubOrganizationSetting.tsx @@ -1,5 +1,5 @@ -import { ReactNative } from '@revenge-mod/react' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' +import { Linking } from 'react-native' import { GitHubOrganizationURL } from '~/constants' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' @@ -10,7 +10,7 @@ const RevengeGitHubOrganizationSetting: SettingsItem = { ), title: () => 'GitHub', - onPress: () => ReactNative.Linking.openURL(GitHubOrganizationURL), + onPress: () => Linking.openURL(GitHubOrganizationURL), type: 'pressable', } diff --git a/src/plugins/init/settings/definitions/RevengeNotImplementedSetting.tsx b/src/plugins/init/settings/definitions/RevengeNotImplementedSetting.tsx index 8ccd5ed..5985a02 100644 --- a/src/plugins/init/settings/definitions/RevengeNotImplementedSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeNotImplementedSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' const RevengeNotImplementedSetting: SettingsItem = { diff --git a/src/plugins/init/settings/definitions/RevengePluginsSetting.tsx b/src/plugins/init/settings/definitions/RevengePluginsSetting.tsx index 9c17481..445f249 100644 --- a/src/plugins/init/settings/definitions/RevengePluginsSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengePluginsSetting.tsx @@ -1,6 +1,6 @@ +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { _plugins } from '@revenge-mod/plugins/_' import { PluginFlags } from '@revenge-mod/plugins/constants' -import TableRowAssetIcon from '~/components/TableRowAssetIcon' import { MobileSetting, UserSettingsSections } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/definitions/RevengeSetting.tsx b/src/plugins/init/settings/definitions/RevengeSetting.tsx index cdf1b03..d14c852 100644 --- a/src/plugins/init/settings/definitions/RevengeSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import RevengeIcon from '~assets/RevengeIcon' import { MobileSetting, UserSettingsSections } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/definitions/RevengeThemesSetting.tsx b/src/plugins/init/settings/definitions/RevengeThemesSetting.tsx index a4e6526..d4dea0a 100644 --- a/src/plugins/init/settings/definitions/RevengeThemesSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeThemesSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import { MobileSetting, UserSettingsSections } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/definitions/RevengeVersionSetting.tsx b/src/plugins/init/settings/definitions/RevengeVersionSetting.tsx index fdf58a7..a628def 100644 --- a/src/plugins/init/settings/definitions/RevengeVersionSetting.tsx +++ b/src/plugins/init/settings/definitions/RevengeVersionSetting.tsx @@ -1,4 +1,4 @@ -import TableRowAssetIcon from '~/components/TableRowAssetIcon' +import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' import RevengeIcon from '~assets/RevengeIcon' import { MobileSetting } from '../constants' import type { SettingsItem } from '@revenge-mod/discord/modules/settings' diff --git a/src/plugins/init/settings/screens/RevengeCustomPageScreen.tsx b/src/plugins/init/settings/screens/RevengeCustomPageScreen.tsx index 73a3e4c..fd3c5e3 100644 --- a/src/plugins/init/settings/screens/RevengeCustomPageScreen.tsx +++ b/src/plugins/init/settings/screens/RevengeCustomPageScreen.tsx @@ -1,4 +1,4 @@ -import { React } from '@revenge-mod/react' +import { useEffect } from 'react' import type { StackScreenProps } from '@react-navigation/stack' import type { ReactNavigationParamList } from '@revenge-mod/externals/react-navigation' import type { MobileSetting, UserSettingsSections } from '../constants' @@ -12,7 +12,8 @@ export default function RevengeCustomPageScreen({ >) { const { render: PageComponent, options } = route.params - React.useEffect(() => { + // biome-ignore lint/correctness/useExhaustiveDependencies: We only want to set options once + useEffect(() => { if (options) navigation.setOptions(options) }, []) diff --git a/src/plugins/init/settings/screens/RevengePluginsSettingScreen.tsx b/src/plugins/init/settings/screens/RevengePluginsSettingScreen.tsx index ebbae57..cbe786e 100644 --- a/src/plugins/init/settings/screens/RevengePluginsSettingScreen.tsx +++ b/src/plugins/init/settings/screens/RevengePluginsSettingScreen.tsx @@ -1,4 +1,7 @@ import { getAssetIdByName } from '@revenge-mod/assets' +import FormSwitch from '@revenge-mod/components/FormSwitch' +import Page from '@revenge-mod/components/Page' +import SearchInput from '@revenge-mod/components/SearchInput' import { Tokens } from '@revenge-mod/discord/common' import { Design } from '@revenge-mod/discord/design' import { FlashList } from '@revenge-mod/externals/shopify' @@ -12,31 +15,30 @@ import { startPlugin, } from '@revenge-mod/plugins/_' import { PluginFlags } from '@revenge-mod/plugins/constants' -import { React, ReactNative } from '@revenge-mod/react' +import { debounce } from '@revenge-mod/utils/callbacks' import { useReRender } from '@revenge-mod/utils/react' -import FormSwitch from '~/components/FormSwitch' -import Page from '~/components/Page' -import SearchInput from '~/components/SearchInput' +import { useCallback, useMemo, useState } from 'react' +import { Image, useWindowDimensions } from 'react-native' import type { InternalPlugin } from '@revenge-mod/plugins/_' -const { Image, useWindowDimensions } = ReactNative const { Card, Text, Stack } = Design export default function RevengePluginsSettingScreen() { - const [search, setSearch] = React.useState('') + const [search, setSearch] = useState('') + const debouncedSetSearch = useCallback(debounce(setSearch, 100), []) const { width } = useWindowDimensions() const numColumns = Math.floor((width - 16) / 448) - const plugins = React.useMemo( + const plugins = useMemo( () => [..._plugins.values()].map( plugin => [plugin, _metas.get(plugin.manifest.id)![2]] as const, ), - [_plugins], + [], ) - const filteredPlugins = React.useMemo( + const filteredPlugins = useMemo( () => plugins.filter(([plugin]) => { const { name, description, author } = plugin.manifest @@ -52,7 +54,10 @@ export default function RevengePluginsSettingScreen() { return ( - setSearch(v)} size="md" /> + debouncedSetSearch(v)} + size="md" + /> ( pattern: ImportMetaGlobPattern,