From 6d2eb7a6bfcc98639e8bef774466b1eb48fa2d69 Mon Sep 17 00:00:00 2001 From: amsyarasyiq <82711525+amsyarasyiq@users.noreply.github.com> Date: Mon, 20 May 2024 15:36:33 +0800 Subject: [PATCH] refactor(metro): overall rewrite --- .eslintrc.json | 4 +- build.mjs | 1 + src/core/commands/eval.ts | 2 +- src/core/i18n/index.ts | 4 +- src/core/plugins/quickInstall/forumPost.tsx | 6 +- src/core/plugins/quickInstall/url.tsx | 6 +- src/core/ui/components/AddonPage.tsx | 4 +- src/core/ui/components/AssetDisplay.tsx | 2 +- src/core/ui/components/Card.tsx | 8 +- src/core/ui/components/FontCard.tsx | 4 +- src/core/ui/components/Version.tsx | 4 +- src/core/ui/settings/index.ts | 2 +- src/core/ui/settings/pages/About.tsx | 2 +- src/core/ui/settings/pages/AssetBrowser.tsx | 2 +- src/core/ui/settings/pages/Developer.tsx | 6 +- src/core/ui/settings/pages/FontImporter.tsx | 6 +- src/core/ui/settings/pages/Fonts.tsx | 4 +- src/core/ui/settings/pages/General.tsx | 2 +- src/core/vendettaObject.ts | 8 +- src/entry.ts | 2 +- src/global.d.ts | 6 +- src/index.ts | 8 +- src/lib/api/assets.ts | 4 +- src/lib/api/flux/index.ts | 2 +- src/lib/index.ts | 2 +- src/lib/managers/themes.ts | 6 +- src/lib/metro/index.ts | 5 - src/lib/metro/utils.ts | 12 --- src/lib/ui/alerts.ts | 2 +- src/lib/ui/color.ts | 2 +- src/lib/ui/components/ContextMenu.tsx | 2 +- src/lib/ui/components/InputAlert.tsx | 2 +- src/lib/ui/components/discord/Forms.ts | 2 +- src/lib/ui/components/discord/Redesign.tsx | 13 ++- src/lib/ui/components/discord/index.ts | 2 +- src/lib/ui/safeMode.tsx | 2 +- src/lib/ui/settings/patches/panel.tsx | 8 +- src/lib/ui/settings/patches/shared.tsx | 8 +- src/lib/ui/settings/patches/tabs.tsx | 6 +- src/lib/ui/styles.ts | 2 +- src/lib/ui/toasts.ts | 2 +- src/lib/utils/logger.ts | 2 +- src/{lib => }/metro/caches.ts | 9 +- .../metro/common.ts => metro/common/index.ts} | 11 ++- src/metro/filters.ts | 90 ++++++++++++++++++ src/metro/finders.ts | 40 ++++++++ .../metro/filters.ts => metro/modules.ts} | 91 +++---------------- src/{lib => }/metro/polyfills/redesign.ts | 6 +- src/{lib => }/metro/types.ts | 0 src/metro/utils.ts | 8 ++ tsconfig.json | 4 +- 51 files changed, 252 insertions(+), 186 deletions(-) delete mode 100644 src/lib/metro/index.ts delete mode 100644 src/lib/metro/utils.ts rename src/{lib => }/metro/caches.ts (88%) rename src/{lib/metro/common.ts => metro/common/index.ts} (78%) create mode 100644 src/metro/filters.ts create mode 100644 src/metro/finders.ts rename src/{lib/metro/filters.ts => metro/modules.ts} (56%) rename src/{lib => }/metro/polyfills/redesign.ts (95%) rename src/{lib => }/metro/types.ts (100%) create mode 100644 src/metro/utils.ts diff --git a/.eslintrc.json b/.eslintrc.json index ac03347..3f57be9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -67,11 +67,11 @@ { "relativeDepth": 0, "aliases": [ - { "alias": "@lib", "matcher": "^src/lib" }, { "alias": "@metro", "matcher": "^src/lib/metro" }, { "alias": "@core", "matcher": "^src/core" }, { "alias": "@ui", "matcher": "^src/lib/ui" }, - { "alias": "@types", "matcher": "^src/lib/utils/types.ts" } + { "alias": "@types", "matcher": "^src/lib/utils/types.ts" }, + { "alias": "@lib", "matcher": "^src/lib" } ] } ] diff --git a/build.mjs b/build.mjs index e9e4df6..7924e46 100644 --- a/build.mjs +++ b/build.mjs @@ -108,6 +108,7 @@ try { "transform-classes" ], exclude: [ + "transform-parameters", "transform-async-to-generator", "transform-exponentiation-operator", "transform-named-capturing-groups-regex", diff --git a/src/core/commands/eval.ts b/src/core/commands/eval.ts index 5db6d6c..56c99ba 100644 --- a/src/core/commands/eval.ts +++ b/src/core/commands/eval.ts @@ -2,7 +2,7 @@ import { Strings } from "@core/i18n"; import { ApplicationCommand, ApplicationCommandOptionType } from "@lib/api/commands/types"; import { settings } from "@lib/settings"; import { messageUtil } from "@metro/common"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; const util = findByProps("inspect"); const AsyncFunction = (async () => void 0).constructor; diff --git a/src/core/i18n/index.ts b/src/core/i18n/index.ts index aa9f1e6..9e90276 100644 --- a/src/core/i18n/index.ts +++ b/src/core/i18n/index.ts @@ -1,5 +1,5 @@ -import { FluxDispatcher } from "@lib/metro/common"; -import { findByName } from "@lib/metro/filters"; +import { FluxDispatcher } from "@metro/common"; +import { findByName } from "@metro/utils"; import { PrimitiveType } from "intl-messageformat"; import langDefault from "./default.json"; diff --git a/src/core/plugins/quickInstall/forumPost.tsx b/src/core/plugins/quickInstall/forumPost.tsx index c7171ad..a5aee8b 100644 --- a/src/core/plugins/quickInstall/forumPost.tsx +++ b/src/core/plugins/quickInstall/forumPost.tsx @@ -5,10 +5,10 @@ import { after } from "@lib/api/patcher"; import { useProxy } from "@lib/api/storage"; import { installPlugin, plugins, removePlugin } from "@lib/managers/plugins"; import { installTheme, removeTheme, themes } from "@lib/managers/themes"; -import { ErrorBoundary } from "@lib/ui/components"; -import { Button } from "@lib/ui/components/discord/Redesign"; import { DISCORD_SERVER_ID, HTTP_REGEX_MULTI, PLUGINS_CHANNEL_ID, PROXY_PREFIX, THEMES_CHANNEL_ID } from "@lib/utils/constants"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; +import { ErrorBoundary } from "@ui/components"; +import { Button } from "@ui/components/discord/Redesign"; import { showToast } from "@ui/toasts"; type PostType = "Plugin" | "Theme"; diff --git a/src/core/plugins/quickInstall/url.tsx b/src/core/plugins/quickInstall/url.tsx index d1b0f3b..09089d3 100644 --- a/src/core/plugins/quickInstall/url.tsx +++ b/src/core/plugins/quickInstall/url.tsx @@ -6,11 +6,13 @@ import { installPlugin } from "@lib/managers/plugins"; import { installTheme } from "@lib/managers/themes"; import { PROXY_PREFIX, THEMES_CHANNEL_ID } from "@lib/utils/constants"; import { channels, url } from "@metro/common"; -import { find, findByProps } from "@metro/filters"; +import { byMutableProp } from "@metro/filters"; +import { find } from "@metro/finders"; +import { findByProps } from "@metro/utils"; import { showConfirmationAlert } from "@ui/alerts"; import { showToast } from "@ui/toasts"; -const showSimpleActionSheet = find(m => m?.showSimpleActionSheet && !Object.getOwnPropertyDescriptor(m, "showSimpleActionSheet")?.get); +const showSimpleActionSheet = find(byMutableProp("showSimpleActionSheet")); const handleClick = findByProps("handleClick"); const { openURL } = url; const { getChannelId } = channels; diff --git a/src/core/ui/components/AddonPage.tsx b/src/core/ui/components/AddonPage.tsx index 18f8375..8cd55e5 100644 --- a/src/core/ui/components/AddonPage.tsx +++ b/src/core/ui/components/AddonPage.tsx @@ -2,13 +2,13 @@ import { Strings } from "@core/i18n"; import { CardWrapper } from "@core/ui/components/Card"; import { getAssetIDByName } from "@lib/api/assets"; import { useProxy } from "@lib/api/storage"; -import { findByProps } from "@lib/metro/filters"; import { settings } from "@lib/settings"; -import { HelpMessage } from "@lib/ui/components/discord"; import { HTTP_REGEX_MULTI } from "@lib/utils/constants"; import { clipboard } from "@metro/common"; +import { findByProps } from "@metro/utils"; import { showInputAlert } from "@ui/alerts"; import { ErrorBoundary, Search } from "@ui/components"; +import { HelpMessage } from "@ui/components/discord"; import fuzzysort from "fuzzysort"; import { createContext } from "react"; import { FlatList, View } from "react-native"; diff --git a/src/core/ui/components/AssetDisplay.tsx b/src/core/ui/components/AssetDisplay.tsx index 7743afc..19779a2 100644 --- a/src/core/ui/components/AssetDisplay.tsx +++ b/src/core/ui/components/AssetDisplay.tsx @@ -1,6 +1,6 @@ import { Asset } from "@lib/api/assets"; -import { FormRow } from "@lib/ui/components/discord/Forms"; import { clipboard } from "@metro/common"; +import { FormRow } from "@ui/components/discord/Forms"; import { showToast } from "@ui/toasts"; import { Image } from "react-native"; diff --git a/src/core/ui/components/Card.tsx b/src/core/ui/components/Card.tsx index df0a2c1..0255a17 100644 --- a/src/core/ui/components/Card.tsx +++ b/src/core/ui/components/Card.tsx @@ -1,10 +1,10 @@ import { getAssetIDByName } from "@lib/api/assets"; -import { FormRow } from "@lib/ui/components/discord/Forms"; -import { FormCheckbox, FormSwitch, IconButton } from "@lib/ui/components/discord/Redesign"; -import { createStyles, TextStyleSheet } from "@lib/ui/styles"; import { ReactNative as RN } from "@metro/common"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; import { semanticColors } from "@ui/color"; +import { FormRow } from "@ui/components/discord/Forms"; +import { FormCheckbox, FormSwitch, IconButton } from "@ui/components/discord/Redesign"; +import { createStyles, TextStyleSheet } from "@ui/styles"; import { ImageBackground, View } from "react-native"; const { hideActionSheet } = findByProps("openLazy", "hideActionSheet"); diff --git a/src/core/ui/components/FontCard.tsx b/src/core/ui/components/FontCard.tsx index 2125601..b71e733 100644 --- a/src/core/ui/components/FontCard.tsx +++ b/src/core/ui/components/FontCard.tsx @@ -3,8 +3,8 @@ import { CardWrapper } from "@core/ui/components/Card"; import { getAssetIDByName } from "@lib/api/assets"; import { useProxy } from "@lib/api/storage"; import { FontDefinition, fonts, removeFont, selectFont } from "@lib/managers/fonts"; -import { FormCheckbox, IconButton, TableRow, TableRowGroup } from "@lib/ui/components/discord/Redesign"; -import { showToast } from "@lib/ui/toasts"; +import { FormCheckbox, IconButton, TableRow, TableRowGroup } from "@ui/components/discord/Redesign"; +import { showToast } from "@ui/toasts"; import { useContext } from "react"; import { Pressable, View } from "react-native"; diff --git a/src/core/ui/components/Version.tsx b/src/core/ui/components/Version.tsx index 2438632..3607e27 100644 --- a/src/core/ui/components/Version.tsx +++ b/src/core/ui/components/Version.tsx @@ -1,7 +1,7 @@ import { getAssetIDByName } from "@lib/api/assets"; -import { FormText } from "@lib/ui/components/discord/Forms"; -import { TableRow } from "@lib/ui/components/discord/Redesign"; import { clipboard } from "@metro/common"; +import { FormText } from "@ui/components/discord/Forms"; +import { TableRow } from "@ui/components/discord/Redesign"; import { showToast } from "@ui/toasts"; interface VersionProps { diff --git a/src/core/ui/settings/index.ts b/src/core/ui/settings/index.ts index a844e10..66344b7 100644 --- a/src/core/ui/settings/index.ts +++ b/src/core/ui/settings/index.ts @@ -3,7 +3,7 @@ import { getAssetIDByName } from "@lib/api/assets"; import { isFontSupported, isThemeSupported } from "@lib/api/native/loader"; import { useProxy } from "@lib/api/storage"; import { settings } from "@lib/settings"; -import { registerSection } from "@lib/ui/settings"; +import { registerSection } from "@ui/settings"; import { version } from "bunny-build"; // @ts-ignore diff --git a/src/core/ui/settings/pages/About.tsx b/src/core/ui/settings/pages/About.tsx index cf9b4b0..5759a24 100644 --- a/src/core/ui/settings/pages/About.tsx +++ b/src/core/ui/settings/pages/About.tsx @@ -3,7 +3,7 @@ import Version from "@core/ui/components/Version"; import { useProxy } from "@lib/api/storage"; import { getDebugInfo } from "@lib/debug"; import { settings } from "@lib/settings"; -import { Stack, TableRowGroup } from "@lib/ui/components/discord/Redesign"; +import { Stack, TableRowGroup } from "@ui/components/discord/Redesign"; import { Platform, ScrollView } from "react-native"; export default function About() { diff --git a/src/core/ui/settings/pages/AssetBrowser.tsx b/src/core/ui/settings/pages/AssetBrowser.tsx index 09ce8d6..7b45d97 100644 --- a/src/core/ui/settings/pages/AssetBrowser.tsx +++ b/src/core/ui/settings/pages/AssetBrowser.tsx @@ -1,7 +1,7 @@ import AssetDisplay from "@core/ui/components/AssetDisplay"; import { all } from "@lib/api/assets"; -import { FormDivider } from "@lib/ui/components/discord/Forms"; import { ErrorBoundary, Search } from "@ui/components"; +import { FormDivider } from "@ui/components/discord/Forms"; import { FlatList, View } from "react-native"; export default function AssetBrowser() { diff --git a/src/core/ui/settings/pages/Developer.tsx b/src/core/ui/settings/pages/Developer.tsx index 37e290a..8af5b84 100644 --- a/src/core/ui/settings/pages/Developer.tsx +++ b/src/core/ui/settings/pages/Developer.tsx @@ -6,12 +6,12 @@ import { getReactDevToolsProp, getReactDevToolsVersion, isLoaderConfigSupported, import { useProxy } from "@lib/api/storage"; import { connectToDebugger } from "@lib/debug"; import { loaderConfig, settings } from "@lib/settings"; -import { FormText } from "@lib/ui/components/discord/Forms"; -import { Button, Stack, TableRow, TableRowGroup, TableSwitchRow, TextInput } from "@lib/ui/components/discord/Redesign"; import { NavigationNative } from "@metro/common"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; import { semanticColors } from "@ui/color"; import { ErrorBoundary } from "@ui/components"; +import { FormText } from "@ui/components/discord/Forms"; +import { Button, Stack, TableRow, TableRowGroup, TableSwitchRow, TextInput } from "@ui/components/discord/Redesign"; import { createStyles, TextStyleSheet } from "@ui/styles"; import { ScrollView, StyleSheet } from "react-native"; diff --git a/src/core/ui/settings/pages/FontImporter.tsx b/src/core/ui/settings/pages/FontImporter.tsx index 561906b..8b97675 100644 --- a/src/core/ui/settings/pages/FontImporter.tsx +++ b/src/core/ui/settings/pages/FontImporter.tsx @@ -3,10 +3,10 @@ import { getAssetIDByName } from "@lib/api/assets"; import { createProxy, useProxy } from "@lib/api/storage"; import { FontDefinition, saveFont, validateFont } from "@lib/managers/fonts"; import { getCurrentTheme } from "@lib/managers/themes"; -import { findByProps } from "@lib/metro"; -import { ErrorBoundary } from "@lib/ui/components"; -import { ActionSheet, BottomSheetTitleHeader, Button, IconButton, Stack, TableRow, TableRowGroup, Text, TextInput, useNavigation } from "@lib/ui/components/discord/Redesign"; import { safeFetch } from "@lib/utils"; +import { findByProps } from "@metro/utils"; +import { ErrorBoundary } from "@ui/components"; +import { ActionSheet, BottomSheetTitleHeader, Button, IconButton, Stack, TableRow, TableRowGroup, Text, TextInput, useNavigation } from "@ui/components/discord/Redesign"; import { useMemo, useRef, useState } from "react"; import { ScrollView, View } from "react-native"; diff --git a/src/core/ui/settings/pages/Fonts.tsx b/src/core/ui/settings/pages/Fonts.tsx index d32fb2b..5f4ea41 100644 --- a/src/core/ui/settings/pages/Fonts.tsx +++ b/src/core/ui/settings/pages/Fonts.tsx @@ -4,8 +4,8 @@ import FontCard from "@core/ui/components/FontCard"; import { useProxy } from "@lib/api/storage"; import { FontDefinition, fonts, installFont } from "@lib/managers/fonts"; import { settings } from "@lib/settings"; -import { FormText } from "@lib/ui/components/discord/Forms"; -import { useNavigation } from "@lib/ui/components/discord/Redesign"; +import { FormText } from "@ui/components/discord/Forms"; +import { useNavigation } from "@ui/components/discord/Redesign"; import { useEffect, useState } from "react"; import { TouchableOpacity } from "react-native"; diff --git a/src/core/ui/settings/pages/General.tsx b/src/core/ui/settings/pages/General.tsx index 9df3cbc..b9fea43 100644 --- a/src/core/ui/settings/pages/General.tsx +++ b/src/core/ui/settings/pages/General.tsx @@ -4,9 +4,9 @@ import { getAssetIDByName } from "@lib/api/assets"; import { useProxy } from "@lib/api/storage"; import { getDebugInfo, toggleSafeMode } from "@lib/debug"; import { settings } from "@lib/settings"; -import { Stack, TableRow, TableRowGroup, TableSwitchRow, useNavigation } from "@lib/ui/components/discord/Redesign"; import { DISCORD_SERVER, GITHUB } from "@lib/utils/constants"; import { url } from "@metro/common"; +import { Stack, TableRow, TableRowGroup, TableSwitchRow, useNavigation } from "@ui/components/discord/Redesign"; import { NativeModules, ScrollView } from "react-native"; import About from "./About"; diff --git a/src/core/vendettaObject.ts b/src/core/vendettaObject.ts index ae1e38d..e1d9813 100644 --- a/src/core/vendettaObject.ts +++ b/src/core/vendettaObject.ts @@ -7,15 +7,15 @@ import * as debug from "@lib/debug"; import * as plugins from "@lib/managers/plugins"; import * as themes from "@lib/managers/themes"; import { loaderConfig, settings } from "@lib/settings"; -import { Forms } from "@lib/ui/components/discord/Forms"; -import { CompatfulRedesign } from "@lib/ui/components/discord/Redesign"; -import { createThemedStyleSheet } from "@lib/ui/styles"; import * as utils from "@lib/utils"; import * as common from "@metro/common"; -import * as metro from "@metro/filters"; +import * as metro from "@metro/utils"; import * as alerts from "@ui/alerts"; import * as color from "@ui/color"; import * as components from "@ui/components"; +import { Forms } from "@ui/components/discord/Forms"; +import { CompatfulRedesign } from "@ui/components/discord/Redesign"; +import { createThemedStyleSheet } from "@ui/styles"; import * as toasts from "@ui/toasts"; export const initVendettaObject = (): any => { diff --git a/src/entry.ts b/src/entry.ts index 8d515bf..e795ffc 100644 --- a/src/entry.ts +++ b/src/entry.ts @@ -11,7 +11,7 @@ async function initializeBunny() { await require("@metro/caches").initMetroCache(); - require(".").default(); + await require(".").default(); } catch (e) { const { ClientInfoManager } = require("@lib/api/native/modules"); const stack = e instanceof Error ? e.stack : undefined; diff --git a/src/global.d.ts b/src/global.d.ts index fcb5c42..79523f9 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,14 +1,10 @@ -import { MetroModules } from "@lib/metro/filters"; -import { BunnyObject } from "@lib/windowObject"; - declare global { var React: typeof import("react"); interface Window { [key: string]: any; - modules: MetroModules; vendetta: any; - bunny: BunnyObject; + bunny: typeof import("@lib"); React: typeof import("react"); } } diff --git a/src/index.ts b/src/index.ts index 0da123e..3044b96 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,6 @@ import initFixes from "@core/fixes"; import { initFetchI18nStrings } from "@core/i18n"; import { initCorePlugins } from "@core/plugins"; import initSettings from "@core/ui/settings"; -import { initVendettaObject } from "@core/vendettaObject"; import { patchCommands } from "@lib/api/commands"; import { injectFluxInterceptor } from "@lib/api/flux"; import { removeFile, writeFile } from "@lib/api/native/fs"; @@ -10,11 +9,10 @@ import { isPyonLoader, isThemeSupported } from "@lib/api/native/loader"; import { FileManager } from "@lib/api/native/modules"; import { patchLogHook } from "@lib/debug"; import { updateFonts } from "@lib/managers/fonts"; -import { initPlugins } from "@lib/managers/plugins"; import { initThemes, patchChatBackground } from "@lib/managers/themes"; -import { patchSettings } from "@lib/ui/settings"; import { logger } from "@lib/utils/logger"; import initSafeMode from "@ui/safeMode"; +import { patchSettings } from "@ui/settings"; import * as lib from "./lib"; @@ -42,7 +40,7 @@ export default async () => { patchLogHook(), patchCommands(), patchChatBackground(), - initVendettaObject(), + // initVendettaObject(), initFetchI18nStrings(), initSettings(), initFixes(), @@ -57,7 +55,7 @@ export default async () => { window.bunny = lib; // Once done, load plugins - lib.unload.push(await initPlugins()); + // lib.unload.push(await initPlugins()); // Update the fonts updateFonts(); diff --git a/src/lib/api/assets.ts b/src/lib/api/assets.ts index 6e06d75..993c50c 100644 --- a/src/lib/api/assets.ts +++ b/src/lib/api/assets.ts @@ -1,8 +1,8 @@ // TODO: Rewrite the whole thing to fit new metro :3 import { after } from "@lib/api/patcher"; -import { getImportingModuleId, requireModule } from "@lib/metro"; -import { getMetroCache, registerAssetCacheId } from "@lib/metro/caches"; +import { getMetroCache, registerAssetCacheId } from "@metro/caches"; +import { getImportingModuleId, requireModule } from "@metro/modules"; export const all: Record = {}; diff --git a/src/lib/api/flux/index.ts b/src/lib/api/flux/index.ts index 5814666..880902c 100644 --- a/src/lib/api/flux/index.ts +++ b/src/lib/api/flux/index.ts @@ -1,5 +1,5 @@ // shelter-mod inspired -import { FluxDispatcher } from "@lib/metro/common"; +import { FluxDispatcher } from "@metro/common"; const blockedSym = Symbol.for("bunny.flux.blocked"); const modifiedSym = Symbol.for("bunny.flux.modified"); diff --git a/src/lib/index.ts b/src/lib/index.ts index 82ca517..40c8644 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -4,7 +4,7 @@ import "../global.d.ts"; export * as api from "./api"; export * as debug from "./debug"; export * as managers from "./managers"; -export * as metro from "./metro"; +// export * as metro from "./metro"; export * as settings from "./settings"; export * as ui from "./ui"; export * as utils from "./utils"; diff --git a/src/lib/managers/themes.ts b/src/lib/managers/themes.ts index 554eb2d..56a6ef2 100644 --- a/src/lib/managers/themes.ts +++ b/src/lib/managers/themes.ts @@ -10,7 +10,9 @@ import { awaitSyncWrapper, createFileBackend, createMMKVBackend, createStorage, import { findInReactTree, safeFetch } from "@lib/utils"; import { Author } from "@lib/utils/types"; import { chroma } from "@metro/common"; -import { find, findByName, findByProps, findByStoreName } from "@metro/filters"; +import { byMutableProp } from "@metro/filters"; +import { find } from "@metro/finders"; +import { findByName, findByProps, findByStoreName } from "@metro/utils"; import { ImageBackground, Platform, processColor } from "react-native"; export interface ThemeData { @@ -249,7 +251,7 @@ function isDiscordTheme(name: string) { } function patchColor() { - const isThemeModule = find(m => m.isThemeDark && Object.getOwnPropertyDescriptor(m, "isThemeDark")?.value); + const isThemeModule = find(byMutableProp("isThemeDark")); const callback = ([theme]: any[]) => theme === vdKey ? [vdThemeFallback] : void 0; Object.keys(color.RawColor).forEach(k => { diff --git a/src/lib/metro/index.ts b/src/lib/metro/index.ts deleted file mode 100644 index d6a7ec6..0000000 --- a/src/lib/metro/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * as cache from "./caches"; -export * as common from "./common"; -export * from "./filters"; -export * as filters from "./filters"; -export * from "./utils"; diff --git a/src/lib/metro/utils.ts b/src/lib/metro/utils.ts deleted file mode 100644 index 3ffb54d..0000000 --- a/src/lib/metro/utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Metro } from "@metro/types"; - -// eslint-disable-next-line prefer-destructuring -export const modules: Metro.ModuleList = window.modules; - -export const metroRequire: Metro.Require = window.__r; - -export const define: Metro.DefineFn = window.__d; - -export const clear: Metro.ClearFn = window.__c; - -export const registerSegment: Metro.RegisterSegmentFn = window.__registerSegment; diff --git a/src/lib/ui/alerts.ts b/src/lib/ui/alerts.ts index 085eee2..c43e7fd 100644 --- a/src/lib/ui/alerts.ts +++ b/src/lib/ui/alerts.ts @@ -1,5 +1,5 @@ import { ButtonColors } from "@lib/utils/types"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; import InputAlert, { InputAlertProps } from "@ui/components/InputAlert"; const Alerts = findByProps("openLazy", "close"); diff --git a/src/lib/ui/color.ts b/src/lib/ui/color.ts index 81c9c34..e503af3 100644 --- a/src/lib/ui/color.ts +++ b/src/lib/ui/color.ts @@ -1,6 +1,6 @@ import { color } from "@lib/managers/themes"; -import { findByStoreName } from "@lib/metro/filters"; import { constants } from "@metro/common"; +import { findByStoreName } from "@metro/utils"; //! This module is only found on 165.0+, under the assumption that iOS 165.0 is the same as Android 165.0. //* In 167.1, most if not all traces of the old color modules were removed. diff --git a/src/lib/ui/components/ContextMenu.tsx b/src/lib/ui/components/ContextMenu.tsx index d291d34..bde7ece 100644 --- a/src/lib/ui/components/ContextMenu.tsx +++ b/src/lib/ui/components/ContextMenu.tsx @@ -1,6 +1,6 @@ import { instead } from "@lib/api/patcher"; -import { findByProps } from "@lib/metro/filters"; import { OptionalKeys } from "@lib/utils/types"; +import { findByProps } from "@metro/utils"; import { AccessibilityInfo, Platform, View } from "react-native"; const { ContextMenu: _ContextMenu } = findByProps("ContextMenu"); diff --git a/src/lib/ui/components/InputAlert.tsx b/src/lib/ui/components/InputAlert.tsx index b42bee6..8644d01 100644 --- a/src/lib/ui/components/InputAlert.tsx +++ b/src/lib/ui/components/InputAlert.tsx @@ -1,5 +1,5 @@ import { ButtonColors } from "@lib/utils/types"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; import { Alert } from "@ui/components/discord"; import { FormInput } from "@ui/components/discord/Forms"; diff --git a/src/lib/ui/components/discord/Forms.ts b/src/lib/ui/components/discord/Forms.ts index 5fc8aff..e21a598 100644 --- a/src/lib/ui/components/discord/Forms.ts +++ b/src/lib/ui/components/discord/Forms.ts @@ -1,4 +1,4 @@ -import { findByProps } from "@lib/metro"; +import { findByProps } from "@metro/utils"; export const Forms = findByProps("Form", "FormSection"); diff --git a/src/lib/ui/components/discord/Redesign.tsx b/src/lib/ui/components/discord/Redesign.tsx index e713690..e2b47ad 100644 --- a/src/lib/ui/components/discord/Redesign.tsx +++ b/src/lib/ui/components/discord/Redesign.tsx @@ -1,9 +1,16 @@ -import { find, findByProps } from "@lib/metro"; -import { RedesignModuleKeys } from "@lib/ui/types"; +import { createFilterDefinition } from "@metro/filters"; +import { find } from "@metro/finders"; +import { findByProps } from "@metro/utils"; +import { RedesignModuleKeys } from "@ui/types"; import { useEffect } from "react"; import { View } from "react-native"; -const findSingular = (prop: string) => find(m => m[prop] && Object.keys(m).length === 1)?.[prop]; +const bySingularProp = createFilterDefinition<[string]>( + ([prop], m) => m[prop] && Object.keys(m).length === 1, + prop => `pyoncord.makldlksdjks(${prop})` +); + +const findSingular = (prop: string) => find(bySingularProp(prop))?.[prop]; export const Redesign = findByProps("TableRow") as Record; diff --git a/src/lib/ui/components/discord/index.ts b/src/lib/ui/components/discord/index.ts index f71bda9..b7c3a52 100644 --- a/src/lib/ui/components/discord/index.ts +++ b/src/lib/ui/components/discord/index.ts @@ -1,4 +1,4 @@ -import { findByDisplayName, findByName, findByProps } from "@metro/filters"; +import { findByDisplayName, findByName, findByProps } from "@metro/utils"; export * as Forms from "./Forms"; export * as Redesign from "./Redesign"; diff --git a/src/lib/ui/safeMode.tsx b/src/lib/ui/safeMode.tsx index 65c29d3..279725d 100644 --- a/src/lib/ui/safeMode.tsx +++ b/src/lib/ui/safeMode.tsx @@ -4,7 +4,7 @@ import { after } from "@lib/api/patcher"; import { toggleSafeMode } from "@lib/debug"; import { settings } from "@lib/settings"; import { ButtonColors } from "@lib/utils/types"; -import { findByName, findByProps } from "@metro/filters"; +import { findByName, findByProps } from "@metro/utils"; import { semanticColors } from "@ui/color"; import { Codeblock, ErrorBoundary as _ErrorBoundary } from "@ui/components"; import { Button, SafeAreaView } from "@ui/components/discord"; diff --git a/src/lib/ui/settings/patches/panel.tsx b/src/lib/ui/settings/patches/panel.tsx index 5af66f9..35bdaa6 100644 --- a/src/lib/ui/settings/patches/panel.tsx +++ b/src/lib/ui/settings/patches/panel.tsx @@ -1,8 +1,8 @@ -import { findByName } from "@lib/metro"; -import { i18n, NavigationNative } from "@lib/metro/common"; -import { FormIcon, FormRow, FormSection } from "@lib/ui/components/discord/Forms"; -import { registeredSections } from "@lib/ui/settings"; import { findInReactTree } from "@lib/utils"; +import { i18n, NavigationNative } from "@metro/common"; +import { findByName } from "@metro/utils"; +import { FormIcon, FormRow, FormSection } from "@ui/components/discord/Forms"; +import { registeredSections } from "@ui/settings"; import { after } from "spitroast"; import { CustomPageRenderer, wrapOnPress } from "./shared"; diff --git a/src/lib/ui/settings/patches/shared.tsx b/src/lib/ui/settings/patches/shared.tsx index c0d59f8..b3de128 100644 --- a/src/lib/ui/settings/patches/shared.tsx +++ b/src/lib/ui/settings/patches/shared.tsx @@ -1,7 +1,7 @@ -import { NavigationNative } from "@lib/metro/common"; -import { findByProps } from "@lib/metro/filters"; -import { ErrorBoundary } from "@lib/ui/components"; -import { RowConfig } from "@lib/ui/settings"; +import { NavigationNative } from "@metro/common"; +import { findByProps } from "@metro/utils"; +import { ErrorBoundary } from "@ui/components"; +import { RowConfig } from "@ui/settings"; const tabsNavigationRef = findByProps("getRootNavigationRef"); diff --git a/src/lib/ui/settings/patches/tabs.tsx b/src/lib/ui/settings/patches/tabs.tsx index 0fc167c..b967e52 100644 --- a/src/lib/ui/settings/patches/tabs.tsx +++ b/src/lib/ui/settings/patches/tabs.tsx @@ -1,7 +1,7 @@ -import { findByName, findByProps } from "@lib/metro"; -import { i18n } from "@lib/metro/common"; -import { registeredSections } from "@lib/ui/settings"; import { findInReactTree } from "@lib/utils"; +import { i18n } from "@metro/common"; +import { findByName, findByProps } from "@metro/utils"; +import { registeredSections } from "@ui/settings"; import { after } from "spitroast"; import { CustomPageRenderer, wrapOnPress } from "./shared"; diff --git a/src/lib/ui/styles.ts b/src/lib/ui/styles.ts index 448c135..4af4cfc 100644 --- a/src/lib/ui/styles.ts +++ b/src/lib/ui/styles.ts @@ -1,4 +1,4 @@ -import { findByProps } from "@lib/metro"; +import { findByProps } from "@metro/utils"; import { isSemanticColor, resolveSemanticColor } from "@ui/color"; import { CompatfulRedesign } from "@ui/components/discord/Redesign"; import { DiscordTextStyles } from "@ui/types"; diff --git a/src/lib/ui/toasts.ts b/src/lib/ui/toasts.ts index 5d2bc6c..0bfc51d 100644 --- a/src/lib/ui/toasts.ts +++ b/src/lib/ui/toasts.ts @@ -1,7 +1,7 @@ import { Strings } from "@core/i18n"; import { getAssetIDByName } from "@lib/api/assets"; import { toasts } from "@metro/common"; -import { findByProps } from "@metro/filters"; +import { findByProps } from "@metro/utils"; import { Platform } from "react-native"; const { uuid4 } = findByProps("uuid4"); diff --git a/src/lib/utils/logger.ts b/src/lib/utils/logger.ts index 27fc005..06c61a4 100644 --- a/src/lib/utils/logger.ts +++ b/src/lib/utils/logger.ts @@ -1,4 +1,4 @@ -import { findByName } from "@metro/filters"; +import { findByName } from "@metro/utils"; export type LoggerFunction = (...messages: any[]) => void; export interface Logger { diff --git a/src/lib/metro/caches.ts b/src/metro/caches.ts similarity index 88% rename from src/lib/metro/caches.ts rename to src/metro/caches.ts index f107fef..c61a767 100644 --- a/src/lib/metro/caches.ts +++ b/src/metro/caches.ts @@ -18,7 +18,6 @@ let metroCache = null as unknown as MetroCacheStore; export function getMetroCache() { return metroCache; } -window.getMetroCache = getMetroCache; export function getFuncUniqCall() { const { stack } = new Error(); @@ -34,18 +33,18 @@ function buildInitCache() { assetsCache: {} } as const; - // Make sure all assets are cached (delay by a second - // because force loading all of it crashes for some reason (it shouldn't)) + // Make sure all assets are cached. Delay by a second + // because force loading all of results in an unexpected crash. setTimeout(() => { for (const id in window.modules) { - require("@metro/filters").requireModule(id); + require("@metro/modules").requireModule(id); } }, 1000); } export async function initMetroCache() { const rawCache = await MMKVManager.getItem(PYON_METRO_CACHE_KEY); - if (rawCache == null) return void buildInitCache(); + if (String(1) !== "1" || rawCache == null) return void buildInitCache(); try { metroCache = JSON.parse(rawCache); diff --git a/src/lib/metro/common.ts b/src/metro/common/index.ts similarity index 78% rename from src/lib/metro/common.ts rename to src/metro/common/index.ts index cf03a5f..772bbf8 100644 --- a/src/lib/metro/common.ts +++ b/src/metro/common/index.ts @@ -1,24 +1,29 @@ -import { find, findByProps } from "@metro/filters"; +import { createSimpleFilter } from "@metro/filters"; +import { find } from "@metro/finders"; import { Dispatcher } from "@metro/types"; +import { findByProps } from "@metro/utils"; // Discord export const constants = findByProps("Fonts", "Permissions"); export const channels = findByProps("getVoiceChannelId"); export const i18n = findByProps("Messages"); export const url = findByProps("openURL", "openDeeplink"); -export const toasts = find(m => m.open && m.close && !m.startDrag && !m.init && !m.openReplay && !m.setAlwaysOnTop && !m.setAccountFlag); export const clipboard = findByProps("setString", "getString", "hasString") as typeof import("@react-native-clipboard/clipboard").default; export const assets = findByProps("registerAsset"); export const invites = findByProps("acceptInviteAndTransitionToInviteChannel"); export const commands = findByProps("getBuiltInCommands"); export const navigation = findByProps("pushLazy"); +export const toasts = find(createSimpleFilter( + m => m.open && m.close && !m.startDrag && !m.init && !m.openReplay && !m.setAlwaysOnTop && !m.setAccountFlag, + "pyoncord.metro.common.toasts" +)); export const messageUtil = findByProps("sendBotMessage"); export const navigationStack = findByProps("createStackNavigator"); export const NavigationNative = findByProps("NavigationContainer"); // Flux export const Flux = findByProps("connectStores"); -export const FluxDispatcher = findByProps("_currentDispatchActionType") as Dispatcher; +export const FluxDispatcher = findByProps("_interceptors") as Dispatcher; // React export const React = window.React = findByProps("createElement") as typeof import("react"); diff --git a/src/metro/filters.ts b/src/metro/filters.ts new file mode 100644 index 0000000..94712ed --- /dev/null +++ b/src/metro/filters.ts @@ -0,0 +1,90 @@ + +type Indexable = Record; +type ModuleExports = any; + +type FilterCheckDef = (args: A, m: M) => boolean; + +export interface FilterFn { + (m: any): boolean; + filter: FilterCheckDef; + args: A; + isDefault: boolean; + serialized: string; +} + +export interface FilterDef { + (...args: A): FilterFn; + byDefault(...args: A): FilterFn; + serializer(args: A): string; +} + +export function createFilterDefinition( + fn: FilterCheckDef, + serializer: (args: A) => string +): FilterDef { + function createHolder(func: T, args: A, isDefault: boolean) { + return Object.assign(func, { + filter: fn, + args, + isDefault, + serialized: [ + isDefault && "default::", + serializer(args) + ].filter(Boolean).join("") + }); + } + + const curried = (...args: A) => createHolder((m: ModuleExports) => fn(args, m), args, false); + const curriedDefault = (...args: A) => { + function filter(m: ModuleExports) { + return m.__esModule && m.default ? fn(args, m.default) : false; + } + return createHolder(filter, args, true); + }; + + return Object.assign(curried, { + byDefault: curriedDefault, + serializer + }); +} + +export function createSimpleFilter( + filter: (m: ModuleExports) => boolean, + id: string +) { + return createFilterDefinition( + (_, m) => filter(m), + () => `dynamic::${id}` + )(); +} + + +export const byProps = createFilterDefinition( + (props, m) => props.length === 0 ? m[props[0]] : props.every(p => m[p]), + props => `pyoncord.metro.byProps(${props.join(",")})` +); + +export const byName = createFilterDefinition<[string]>( + ([name], m) => m.name === name, + name => `pyoncord.metro.byName(${name})` +); + +export const byDisplayName = createFilterDefinition<[string]>( + ([displayName], m) => m.displayName === displayName, + name => `pyoncord.metro.byDisplayName(${name})` +); + +export const byTypeName = createFilterDefinition<[string]>( + ([typeName], m) => m.type?.name === typeName, + name => `pyoncord.metro.byTypeName(${name})` +); + +export const byStoreName = createFilterDefinition<[string]>( + ([name], m) => m.getName?.length === 0 && m.getName() === name, + name => `pyoncord.metro.byStoreName(${name})` +); + +export const byMutableProp = createFilterDefinition<[string]>( + ([prop], m) => m?.[prop] && !Object.getOwnPropertyDescriptor(m, prop)?.get, + prop => `pyoncord.metro.byMutableProp(${prop})` +); diff --git a/src/metro/finders.ts b/src/metro/finders.ts new file mode 100644 index 0000000..41b1cf9 --- /dev/null +++ b/src/metro/finders.ts @@ -0,0 +1,40 @@ +import { getFuncUniqCall } from "./caches"; +import { FilterFn } from "./filters"; +import { getModules } from "./modules"; + +function testExports(moduleExports: any, filter: FilterFn) { + if (moduleExports.default && moduleExports.__esModule && filter(moduleExports.default)) + return moduleExports.default; + if (filter(moduleExports)) + return moduleExports; +} + +/** + * Returns the exports of the first module where filter returns truthy, and undefined otherwise. + * @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value. + */ +export function find(filter: FilterFn) { + const uniq = getFuncUniqCall(); + + for (const [id, moduleExports] of getModules(uniq, false)) { + const testedExports = testExports(moduleExports, filter); + if (testedExports !== undefined) + return testedExports; + } +} + +/** + * Returns the exports of all modules where filter returns truthy. + * @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value. + */ +export function findAll(filter: FilterFn) { + const foundExports: any[] = []; + const uniq = getFuncUniqCall(); + + for (const [id, moduleExports] of getModules(uniq, true)) { + const testedExports = testExports(moduleExports, filter); + if (testedExports !== undefined) + foundExports.push(testedExports); + } + return foundExports; +} diff --git a/src/lib/metro/filters.ts b/src/metro/modules.ts similarity index 56% rename from src/lib/metro/filters.ts rename to src/metro/modules.ts index d64fc40..f794ac1 100644 --- a/src/lib/metro/filters.ts +++ b/src/metro/modules.ts @@ -1,12 +1,10 @@ -import { instead } from "@lib/api/patcher"; -import type { Metro } from "@metro/types"; -import { metroRequire, modules } from "@metro/utils"; +import { getMetroCache } from "@metro/caches"; +import { Metro } from "@metro/types"; +import { instead } from "spitroast"; -import { getFuncUniqCall, getMetroCache, registerModuleFindCacheId } from "./caches"; - -export type PropIntellisense

= Record & Record; -export type PropsFinder = (...props: T[]) => PropIntellisense; -export type PropsFinderAll = (...props: T[]) => PropIntellisense[]; +// eslint-disable-next-line prefer-destructuring +const modules: Metro.ModuleList = window.modules; +const metroRequire: Metro.Require = window.__r; metroRequire(0); @@ -153,11 +151,15 @@ export function requireModule(id: Metro.ModuleID) { return moduleExports; } -function* getModules(uniqueId: string, all: boolean) { +export function* getModules(uniqueId: string | null, all = false) { yield [-1, require("@metro/polyfills/redesign")]; - let cache = getMetroCache().findCache[uniqueId]; - if (all && !cache?._) cache = undefined; + let cache = null; + + if (uniqueId) { + cache = getMetroCache().findCache[uniqueId]; + if (all && !cache?._) cache = undefined; + } for (const id in cache ?? modules) { const exports = requireModule(id); @@ -165,70 +167,3 @@ function* getModules(uniqueId: string, all: boolean) { yield [id, exports]; } } - -type ExportsFilter = (moduleExports: any) => unknown; - -function testExports(moduleExports: any, filter: ExportsFilter) { - if (moduleExports.default && moduleExports.__esModule && filter(moduleExports.default)) - return moduleExports.default; - if (filter(moduleExports)) - return moduleExports; -} - -/** - * Returns the exports of the first module where filter returns truthy, and undefined otherwise. - * @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value. - */ -export function find(filter: ExportsFilter) { - const uniqueId = getFuncUniqCall(); - - for (const [id, moduleExports] of getModules(uniqueId, false)) { - const testedExports = testExports(moduleExports, filter); - if (testedExports !== undefined) { - if (id !== -1) registerModuleFindCacheId(uniqueId, Number(id), false); - return testedExports; - } - } -} - -/** - * Returns the exports of all modules where filter returns truthy. - * @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value. - */ -export function findAll(filter: ExportsFilter) { - const foundExports: any[] = []; - const uniqueId = getFuncUniqCall(); - - for (const [id, moduleExports] of getModules(uniqueId, true)) { - const testedExports = testExports(moduleExports, filter); - if (testedExports !== undefined) { - if (id !== -1) registerModuleFindCacheId(uniqueId, Number(id), true); - foundExports.push(testedExports); - } - } - return foundExports; -} - -const propsFilter = (props: PropertyKey[]) => - (exps: any) => props.every(p => exps[p] !== undefined); -const nameFilter = (name: string, defaultExp: boolean) => defaultExp - ? (exps: any) => exps?.name === name - : (exps: any) => exps?.default?.name === name; -const dNameFilter = (displayName: string, defaultExp: boolean) => defaultExp - ? (exps: any) => exps?.displayName === displayName - : (exps: any) => exps?.default?.displayName === displayName; -const tNameFilter = (typeName: string, defaultExp: boolean) => defaultExp - ? (exps: any) => exps?.type?.name === typeName - : (exps: any) => exps?.default?.type?.name === typeName; -const storeFilter = (name: string) => - (exps: any) => exps.getName && exps.getName.length === 0 && exps.getName() === name; - -export const findByProps: PropsFinder = (...props) => find(propsFilter(props)); -export const findByPropsAll: PropsFinderAll = (...props) => findAll(propsFilter(props)); -export const findByName = (name: string, defaultExp = true) => find(nameFilter(name, defaultExp)); -export const findByNameAll = (name: string, defaultExp = true) => findAll(nameFilter(name, defaultExp)); -export const findByDisplayName = (displayName: string, defaultExp = true) => find(dNameFilter(displayName, defaultExp)); -export const findByDisplayNameAll = (displayName: string, defaultExp = true) => findAll(dNameFilter(displayName, defaultExp)); -export const findByTypeName = (typeName: string, defaultExp = true) => find(tNameFilter(typeName, defaultExp)); -export const findByTypeNameAll = (typeName: string, defaultExp = true) => findAll(tNameFilter(typeName, defaultExp)); -export const findByStoreName = (name: string) => find(storeFilter(name)); diff --git a/src/lib/metro/polyfills/redesign.ts b/src/metro/polyfills/redesign.ts similarity index 95% rename from src/lib/metro/polyfills/redesign.ts rename to src/metro/polyfills/redesign.ts index 0f030bb..913d51c 100644 --- a/src/lib/metro/polyfills/redesign.ts +++ b/src/metro/polyfills/redesign.ts @@ -1,5 +1,5 @@ -import { getMetroCache, registerPolyfillCacheId } from "@lib/metro/caches"; -import { modules, requireModule } from "@metro"; +import { getMetroCache, registerPolyfillCacheId } from "@metro/caches"; +import { getModules, requireModule } from "@metro/modules"; import { LiteralUnion } from "type-fest"; const redesignProps = new Set([ @@ -104,7 +104,7 @@ const redesignPropSource = {} as Record; const redesignModule = {} as Record; const cache = getMetroCache().polyfillCache.redesign_module; -for (const id in cache ?? modules) { +for (const id in cache ?? getModules(null)) { const moduleExports = requireModule(id); polyfillRedesignModule(moduleExports, Number(id)); } diff --git a/src/lib/metro/types.ts b/src/metro/types.ts similarity index 100% rename from src/lib/metro/types.ts rename to src/metro/types.ts diff --git a/src/metro/utils.ts b/src/metro/utils.ts new file mode 100644 index 0000000..dd74dc8 --- /dev/null +++ b/src/metro/utils.ts @@ -0,0 +1,8 @@ +import { byDisplayName, byName, byProps, byStoreName, byTypeName } from "./filters"; +import { find } from "./finders"; + +export const findByProps = (...props: string[]) => find(byProps(...props)); +export const findByName = (name: string, expDefault = true) => find(expDefault ? byName(name) : byName.byDefault(name)); +export const findByDisplayName = (name: string, expDefault = true) => find(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); +export const findByTypeName = (name: string, expDefault = true) => find(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); +export const findByStoreName = (name: string) => find(byStoreName(name)); diff --git a/tsconfig.json b/tsconfig.json index bd56899..a399671 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,8 @@ "@core/*": ["./src/core/*"], "@lib": ["./src/lib"], "@lib/*": ["./src/lib/*"], - "@metro": ["./src/lib/metro"], - "@metro/*": ["./src/lib/metro/*"], + "@metro": ["./src/metro"], + "@metro/*": ["./src/metro/*"], "@ui": ["./src/lib/ui"], "@ui/*": ["./src/lib/ui/*"], "@types": ["./src/lib/utils/types.ts"],