From 7d77a34a4f78bbb0d9f388fad4087c82cf1d088b Mon Sep 17 00:00:00 2001 From: amsyarasyiq <82711525+amsyarasyiq@users.noreply.github.com> Date: Tue, 2 Apr 2024 22:24:56 +0800 Subject: [PATCH] [metro] Polyfill the lost redesign module --- src/index.ts | 4 +- src/lib/metro/filters.ts | 14 ++- src/lib/metro/polyfills/redesign.ts | 138 ++++++++++++++++++++++++++++ src/lib/ui/index.ts | 1 + src/lib/ui/styles.ts | 3 +- 5 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 src/lib/metro/polyfills/redesign.ts diff --git a/src/index.ts b/src/index.ts index cc7585e..c89bc59 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import { patchAssets } from "@lib/api/assets"; import { patchCommands } from "@lib/api/commands"; import { injectFluxInterceptor } from "@lib/api/flux"; import { isThemeSupported } from "@lib/api/native/loader"; -import { patchLogHook } from "@lib/debug"; +import { connectToDebugger, patchLogHook } from "@lib/debug"; import { initPlugins } from "@lib/managers/plugins"; import { initThemes, patchChatBackground } from "@lib/managers/themes"; import { patchSettings } from "@lib/ui/settings"; @@ -48,6 +48,8 @@ export default async () => { // Assign window object window.bunny = lib; + connectToDebugger("127.0.0.1:9090/"); + // Once done, load plugins lib.unload.push(await initPlugins()); diff --git a/src/lib/metro/filters.ts b/src/lib/metro/filters.ts index f2b6f29..a2f569f 100644 --- a/src/lib/metro/filters.ts +++ b/src/lib/metro/filters.ts @@ -1,5 +1,6 @@ import { after, instead } from "@lib/api/patcher"; + export type MetroModules = { [id: string]: any; }; export type PropIntellisense

= Record & Record; export type PropsFinder = (...props: T[]) => PropIntellisense; @@ -29,7 +30,6 @@ for (const id in window.modules) { } } - // Blacklist any "bad-actor" modules, e.g. the dreaded null proxy, the window itself, or undefined modules for (const id in window.modules) { const module = requireModule(id); @@ -96,13 +96,19 @@ function requireModule(id: string) { return exports; } +function* getModules() { + yield require("./polyfills/redesign"); + + for (const id in modules) { + yield requireModule(id); + } +} + // Function to filter through modules const filterModules = (modules: MetroModules, single = false) => (filter: (m: any) => boolean) => { const found = []; - for (const id in modules) { - const exports = requireModule(id); - + for (const exports of getModules()) { if (exports.default && exports.__esModule && filter(exports.default)) { if (single) return exports.default; found.push(exports.default); diff --git a/src/lib/metro/polyfills/redesign.ts b/src/lib/metro/polyfills/redesign.ts new file mode 100644 index 0000000..0d54786 --- /dev/null +++ b/src/lib/metro/polyfills/redesign.ts @@ -0,0 +1,138 @@ +import "@metro/index"; + +import { LiteralUnion } from "type-fest"; + +const redesignProps = new Set([ + "AlertActionButton", + "AlertModal", + "AlertModalContainer", + "AvatarDuoPile", + "AvatarPile", + "BACKDROP_OPAQUE_MAX_OPACITY", + "Backdrop", + "Button", + "Card", + "ContextMenu", + "ContextMenuContainer", + "FauxHeader", + "FloatingActionButton", + "GhostInput", + "GuildIconPile", + "HeaderActionButton", + "HeaderButton", + "HeaderSubmittingIndicator", + "IconButton", + "Input", + "InputButton", + "InputContainer", + "LayerContext", + "LayerScope", + "Modal", + "ModalActionButton", + "ModalContent", + "ModalDisclaimer", + "ModalFloatingAction", + "ModalFloatingActionSpacer", + "ModalFooter", + "ModalScreen", + "ModalStepIndicator", + "NAV_BAR_HEIGHT", + "NAV_BAR_HEIGHT_MULTILINE", + "Navigator", + "NavigatorHeader", + "NavigatorScreen", + "Pile", + "PileOverflow", + "RedesignCompat", + "RedesignCompatContext", + "RowButton", + "STATUS_BAR_HEIGHT", + "SceneLoadingIndicator", + "SearchField", + "SegmentedControl", + "SegmentedControlPages", + "Slider", + "Stack", + "StepModal", + "StickyContext", + "StickyHeader", + "StickyWrapper", + "TABLE_ROW_CONTENT_HEIGHT", + "TABLE_ROW_HEIGHT", + "TableCheckboxRow", + "TableRadioGroup", + "TableRadioRow", + "TableRow", + "TableRowGroup", + "TableRowGroupTitle", + "TableRowIcon", + "TableSwitchRow", + "Tabs", + "TextArea", + "TextField", + "TextInput", + "Toast", + "dismissAlerts", + "getHeaderBackButton", + "getHeaderCloseButton", + "getHeaderConditionalBackButton", + "getHeaderNoTitle", + "getHeaderTextButton", + "hideContextMenu", + "navigatorShouldCrossfade", + "openAlert", + "useAccessibilityNativeStackOptions", + "useAndroidNavScrim", + "useCoachmark", + "useFloatingActionButtonScroll", + "useFloatingActionButtonState", + "useNativeStackNavigation", + "useNavigation", + "useNavigationTheme", + "useNavigatorBackPressHandler", + "useNavigatorScreens", + "useNavigatorShouldCrossfade", + "useSegmentedControlState", + "useStackNavigation", + "useTabNavigation", + "useTooltip" +] as const); + +type Keys = LiteralUnion ? U : string, string>; + +const redesignPropSource = {} as Record; +const redesignModule = {} as Record; + +for (const id in window.modules) { + const exports = window.__r(id); + polyfillRedesignModule(exports); +} + +function polyfillRedesignModule(exports: any) { + const propMap = new Map(); + + for (const prop of redesignProps) { + if (exports?.[prop]) { + propMap.set(prop, null); + } + else if (exports?.default?.[prop]) { + propMap.set(prop, "default"); + } + } + + for (const [prop, defaultKey] of propMap) { + const exportsForProp = defaultKey ? exports[defaultKey] : exports; + + if (redesignModule[prop]) { + if (Object.keys(exportsForProp).length < Object.keys(redesignPropSource[prop]).length) { + redesignModule[prop] = exportsForProp[prop]; + redesignPropSource[prop] = exportsForProp; + } + } else { + redesignModule[prop] = exportsForProp[prop]; + redesignPropSource[prop] = exportsForProp; + } + } +} + +export default redesignModule; diff --git a/src/lib/ui/index.ts b/src/lib/ui/index.ts index 824de76..a82cd14 100644 --- a/src/lib/ui/index.ts +++ b/src/lib/ui/index.ts @@ -1,3 +1,4 @@ + export * as alerts from "./alerts"; export * as color from "./color"; export * as components from "./components"; diff --git a/src/lib/ui/styles.ts b/src/lib/ui/styles.ts index 0939827..448c135 100644 --- a/src/lib/ui/styles.ts +++ b/src/lib/ui/styles.ts @@ -1,3 +1,4 @@ +import { findByProps } from "@lib/metro"; import { isSemanticColor, resolveSemanticColor } from "@ui/color"; import { CompatfulRedesign } from "@ui/components/discord/Redesign"; import { DiscordTextStyles } from "@ui/types"; @@ -5,7 +6,7 @@ import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from "react-native"; type NamedStyles = { [P in keyof T]: ViewStyle | TextStyle | ImageStyle }; -export const { TextStyleSheet } = CompatfulRedesign as unknown as { +export const { TextStyleSheet } = findByProps("TextStyleSheet") as unknown as { TextStyleSheet: { [key in DiscordTextStyles]: TextStyle; }; };