Skip to content

Commit

Permalink
[metro] Polyfill the lost redesign module
Browse files Browse the repository at this point in the history
  • Loading branch information
pylixonly committed Apr 2, 2024
1 parent 01c1694 commit 7d77a34
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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());

Expand Down
14 changes: 10 additions & 4 deletions src/lib/metro/filters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { after, instead } from "@lib/api/patcher";


export type MetroModules = { [id: string]: any; };
export type PropIntellisense<P extends string | symbol> = Record<P, any> & Record<PropertyKey, any>;
export type PropsFinder = <T extends string | symbol>(...props: T[]) => PropIntellisense<T>;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
138 changes: 138 additions & 0 deletions src/lib/metro/polyfills/redesign.ts
Original file line number Diff line number Diff line change
@@ -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<typeof redesignProps extends Set<infer U> ? U : string, string>;

const redesignPropSource = {} as Record<Keys, any>;
const redesignModule = {} as Record<Keys, any>;

for (const id in window.modules) {
const exports = window.__r(id);
polyfillRedesignModule(exports);
}

function polyfillRedesignModule(exports: any) {
const propMap = new Map<string, string | null>();

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;
1 change: 1 addition & 0 deletions src/lib/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

export * as alerts from "./alerts";
export * as color from "./color";
export * as components from "./components";
Expand Down
3 changes: 2 additions & 1 deletion src/lib/ui/styles.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { findByProps } from "@lib/metro";
import { isSemanticColor, resolveSemanticColor } from "@ui/color";
import { CompatfulRedesign } from "@ui/components/discord/Redesign";
import { DiscordTextStyles } from "@ui/types";
import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from "react-native";

type NamedStyles<T> = { [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; };
};

Expand Down

0 comments on commit 7d77a34

Please sign in to comment.