feat(metro): lazify destructures

This commit is contained in:
amsyarasyiq 2024-05-22 19:41:00 +08:00
parent 8bbf1dbf5e
commit dcb0408e31
13 changed files with 55 additions and 29 deletions

View file

@ -6,7 +6,8 @@ import { useProxy } from "@lib/api/storage";
import { installPlugin, plugins, removePlugin } from "@lib/managers/plugins";
import { installTheme, removeTheme, themes } from "@lib/managers/themes";
import { DISCORD_SERVER_ID, HTTP_REGEX_MULTI, PLUGINS_CHANNEL_ID, PROXY_PREFIX, THEMES_CHANNEL_ID } from "@lib/utils/constants";
import { findByPropsProxy } from "@metro/utils";
import { lazyDestructure } from "@lib/utils/lazy";
import { findByProps, findByPropsProxy } from "@metro/utils";
import { ErrorBoundary } from "@ui/components";
import { Button } from "@ui/components/discord/Redesign";
import { showToast } from "@ui/toasts";
@ -15,7 +16,7 @@ type PostType = "Plugin" | "Theme";
// const ForumPostLongPressActionSheet = findByNameProxy("ForumPostLongPressActionSheet", false);
// const { ActionSheetRow } = findByPropsProxy("ActionSheetRow");
const { useFirstForumPostMessage } = findByPropsProxy("useFirstForumPostMessage");
const { useFirstForumPostMessage } = lazyDestructure(() => findByProps("useFirstForumPostMessage"));
const forumReactions = findByPropsProxy("MostCommonForumPostReaction");
const postMap = {

View file

@ -5,18 +5,19 @@ import { after, instead } from "@lib/api/patcher";
import { installPlugin } from "@lib/managers/plugins";
import { installTheme } from "@lib/managers/themes";
import { PROXY_PREFIX, THEMES_CHANNEL_ID } from "@lib/utils/constants";
import { lazyDestructure } from "@lib/utils/lazy";
import { channels, url } from "@metro/common";
import { byMutableProp } from "@metro/filters";
import { findExports } from "@metro/finders";
import { findByPropsProxy } from "@metro/utils";
import { findByProps, findByPropsProxy } from "@metro/utils";
import { showConfirmationAlert } from "@ui/alerts";
import { showToast } from "@ui/toasts";
const showSimpleActionSheet = findExports(byMutableProp("showSimpleActionSheet"));
const handleClick = findByPropsProxy("handleClick");
const { openURL } = url;
const { getChannelId } = channels;
const { getChannel } = findByPropsProxy("getChannel");
const { openURL } = lazyDestructure(() => url);
const { getChannelId } = lazyDestructure(() => channels);
const { getChannel } = lazyDestructure(() => findByProps("getChannel"));
function typeFromUrl(url: string) {
if (url.startsWith(PROXY_PREFIX)) {

View file

@ -4,8 +4,9 @@ import { getAssetIDByName } from "@lib/api/assets";
import { useProxy } from "@lib/api/storage";
import { settings } from "@lib/settings";
import { HTTP_REGEX_MULTI } from "@lib/utils/constants";
import { lazyDestructure } from "@lib/utils/lazy";
import { clipboard } from "@metro/common";
import { findByPropsProxy } from "@metro/utils";
import { findByProps, findByPropsProxy } from "@metro/utils";
import { showInputAlert } from "@ui/alerts";
import { ErrorBoundary, Search } from "@ui/components";
import { HelpMessage } from "@ui/components/discord";
@ -44,7 +45,7 @@ function getItemsByQuery<T extends AddonPageProps<unknown>["items"][string]>(ite
}
const reanimated = findByPropsProxy("useSharedValue");
const { FloatingActionButton } = findByPropsProxy("FloatingActionButton");
const { FloatingActionButton } = lazyDestructure(() => findByProps("FloatingActionButton"));
export default function AddonPage<T>({ floatingButtonText, fetchFunction, items, safeModeMessage, safeModeExtras, card: CardComponent, isRemoveMode, headerComponent, onFABPress }: AddonPageProps<T>) {
useProxy(items);

View file

@ -1,14 +1,15 @@
import { getAssetIDByName } from "@lib/api/assets";
import { lazyDestructure } from "@lib/utils/lazy";
import { ReactNative as RN } from "@metro/common";
import { findByPropsProxy } from "@metro/utils";
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 } = findByPropsProxy("openLazy", "hideActionSheet");
const { showSimpleActionSheet } = findByPropsProxy("showSimpleActionSheet");
const { hideActionSheet } = lazyDestructure(() => findByProps("openLazy", "hideActionSheet"));
const { showSimpleActionSheet } = lazyDestructure(() => findByProps("showSimpleActionSheet"));
// TODO: These styles work weirdly. iOS has cramped text, Android with low DPI probably does too. Fix?
const useStyles = createStyles({

View file

@ -6,8 +6,9 @@ import { getReactDevToolsProp, getReactDevToolsVersion, isLoaderConfigSupported,
import { useProxy } from "@lib/api/storage";
import { connectToDebugger } from "@lib/debug";
import { loaderConfig, settings } from "@lib/settings";
import { lazyDestructure } from "@lib/utils/lazy";
import { NavigationNative } from "@metro/common";
import { findByPropsProxy } from "@metro/utils";
import { findByProps } from "@metro/utils";
import { semanticColors } from "@ui/color";
import { ErrorBoundary } from "@ui/components";
import { FormText } from "@ui/components/discord/Forms";
@ -15,8 +16,8 @@ import { Button, Stack, TableRow, TableRowGroup, TableSwitchRow, TextInput } fro
import { createStyles, TextStyleSheet } from "@ui/styles";
import { ScrollView, StyleSheet } from "react-native";
const { hideActionSheet } = findByPropsProxy("openLazy", "hideActionSheet");
const { showSimpleActionSheet } = findByPropsProxy("showSimpleActionSheet");
const { hideActionSheet } = lazyDestructure(() => findByProps("openLazy", "hideActionSheet"));
const { showSimpleActionSheet } = lazyDestructure(() => findByProps("showSimpleActionSheet"));
const RDT_EMBED_LINK = "https://raw.githubusercontent.com/amsyarasyiq/rdt-embedder/main/dist.js";

View file

@ -8,11 +8,12 @@ import { ThemeManager } from "@lib/api/native/modules";
import { after, before, instead } from "@lib/api/patcher";
import { awaitSyncWrapper, createFileBackend, createMMKVBackend, createStorage, wrapSync } from "@lib/api/storage";
import { findInReactTree, safeFetch } from "@lib/utils";
import { lazyDestructure } from "@lib/utils/lazy";
import { Author } from "@lib/utils/types";
import { chroma } from "@metro/common";
import { byMutableProp } from "@metro/filters";
import { findExports } from "@metro/finders";
import { findByNameProxy, findByPropsProxy, findByStoreNameProxy } from "@metro/utils";
import { findByNameProxy, findByProps, findByPropsProxy, findByStoreNameProxy } from "@metro/utils";
import { ImageBackground, Platform, processColor } from "react-native";
export interface ThemeData {
@ -76,9 +77,7 @@ async function writeTheme(theme: Theme | {}) {
*/
export function patchChatBackground() {
const MessagesWrapperConnected = findByNameProxy("MessagesWrapperConnected", false);
if (!MessagesWrapperConnected) return;
const { MessagesWrapper } = findByPropsProxy("MessagesWrapper");
if (!MessagesWrapper) return;
const { MessagesWrapper } = lazyDestructure(() => findByProps("MessagesWrapper"));
const patches = [
after("default", MessagesWrapperConnected, (_, ret) => enabled ? React.createElement(ImageBackground, {

View file

@ -1,9 +1,10 @@
import { instead } from "@lib/api/patcher";
import { lazyDestructure } from "@lib/utils/lazy";
import { OptionalKeys } from "@lib/utils/types";
import { findByPropsProxy } from "@metro/utils";
import { findByProps } from "@metro/utils";
import { AccessibilityInfo, Platform, View } from "react-native";
const { ContextMenu: _ContextMenu } = findByPropsProxy("ContextMenu");
const { ContextMenu: _ContextMenu } = lazyDestructure(() => findByProps("ContextMenu"));
type ContextMenuItem = {
label: string,

View file

@ -3,8 +3,9 @@ import { DeviceManager } from "@lib/api/native/modules";
import { after } from "@lib/api/patcher";
import { toggleSafeMode } from "@lib/debug";
import { settings } from "@lib/settings";
import { lazyDestructure } from "@lib/utils/lazy";
import { ButtonColors } from "@lib/utils/types";
import { findByNameProxy, findByPropsProxy } from "@metro/utils";
import { findByNameProxy, findByProps } from "@metro/utils";
import { semanticColors } from "@ui/color";
import { Codeblock, ErrorBoundary as _ErrorBoundary } from "@ui/components";
import { Button, SafeAreaView } from "@ui/components/discord";
@ -14,7 +15,7 @@ import { Text, View } from "react-native";
const ErrorBoundary = findByNameProxy("ErrorBoundary");
// Let's just pray they have this.
const { BadgableTabBar } = findByPropsProxy("BadgableTabBar");
const { BadgableTabBar } = lazyDestructure(() => findByProps("BadgableTabBar"));
const styles = createThemedStyleSheet({
container: {

View file

@ -1,4 +1,5 @@
import { findByPropsProxy } from "@metro/utils";
import { lazyDestructure } from "@lib/utils/lazy";
import { findByProps } from "@metro/utils";
import { isSemanticColor, resolveSemanticColor } from "@ui/color";
import { CompatfulRedesign } from "@ui/components/discord/Redesign";
import { DiscordTextStyles } from "@ui/types";
@ -6,7 +7,7 @@ import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from "react-native";
type NamedStyles<T> = { [P in keyof T]: ViewStyle | TextStyle | ImageStyle };
export const { TextStyleSheet } = findByPropsProxy("TextStyleSheet") as unknown as {
export const { TextStyleSheet } = lazyDestructure(() => findByProps("TextStyleSheet")) as unknown as {
TextStyleSheet: { [key in DiscordTextStyles]: TextStyle; };
};

View file

@ -1,10 +1,11 @@
import { Strings } from "@core/i18n";
import { getAssetIDByName } from "@lib/api/assets";
import { lazyDestructure } from "@lib/utils/lazy";
import { toasts } from "@metro/common";
import { findByPropsProxy } from "@metro/utils";
import { findByProps } from "@metro/utils";
import { Platform } from "react-native";
const { uuid4 } = findByPropsProxy("uuid4");
const { uuid4 } = lazyDestructure(() => findByProps("uuid4"));
export const showToast = (content: string, asset?: number) => toasts.open({
// ? In build 182205/44707, Discord changed their toasts, source is no longer used, rather icon, and a key is needed.

View file

@ -43,3 +43,22 @@ export function proxyLazy<T>(factory: () => T, asFunction = true): T {
return new Proxy(dummy, lazyHandler) as any;
}
export function lazyDestructure<T extends Record<PropertyKey, unknown>>(factory: () => T, asFunction = false): T {
const proxiedObject = proxyLazy(factory, asFunction);
return new Proxy({}, {
get(_, property) {
if (property === Symbol.iterator) {
return function* () {
yield proxiedObject;
yield new Proxy({}, {
get: (_, p) => proxyLazy(() => proxiedObject[p])
});
throw new Error("This is not a real iterator, this is likely used incorrectly");
};
}
return proxyLazy(() => proxiedObject[property]);
}
}) as T;
}

View file

@ -174,7 +174,9 @@ export function requireModule(id: Metro.ModuleID) {
let moduleExports;
try {
const forced = !metroModules[id]?.isInitialized;
moduleExports = metroRequire(id);
forced && console.log("Force inited", id, moduleExports);
} catch {
blacklistModule(String(id));
moduleExports = undefined;

View file

@ -5,9 +5,6 @@ import { filterExports, findExports } from "./finders";
import { requireModule, subscribeModule } from "./modules";
import type { FilterFn } from "./types";
// TODO: "Find info" sounds too meh
const findInfoSym = Symbol.for("bunny.metro.findInfo");
const proxyInfoMap = new WeakMap<{}, FindProxyInfo<any[]>>();
interface FindProxyInfo<A extends unknown[]> {