Skip to content

Commit

Permalink
feat: adopt dev metro
Browse files Browse the repository at this point in the history
  • Loading branch information
pylixonly committed Nov 16, 2024
1 parent e56ec77 commit cc87948
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 129 deletions.
6 changes: 4 additions & 2 deletions src/core/ui/settings/pages/Developer/AssetBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import AssetDisplay from "@core/ui/settings/pages/Developer/AssetDisplay";
import { assetsMap } from "@lib/api/assets";
import { iterateAssets } from "@lib/api/assets";
import { LegacyFormDivider } from "@metro/common/components";
import { ErrorBoundary, Search } from "@ui/components";
import { useMemo } from "react";
import { FlatList, View } from "react-native";

export default function AssetBrowser() {
const [search, setSearch] = React.useState("");
const all = useMemo(() => Array.from(iterateAssets()), []);

return (
<ErrorBoundary>
Expand All @@ -15,7 +17,7 @@ export default function AssetBrowser() {
onChangeText={(v: string) => setSearch(v)}
/>
<FlatList
data={Object.values(assetsMap).filter(a => a.name.includes(search) || a.id.toString() === search)}
data={all.filter(a => a.name.includes(search) || a.id.toString() === search)}
renderItem={({ item }) => <AssetDisplay asset={item} />}
ItemSeparatorComponent={LegacyFormDivider}
keyExtractor={item => item.name}
Expand Down
21 changes: 20 additions & 1 deletion src/core/vendetta/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,26 @@ export const initVendettaObject = (): any => {
showInputAlert: (options: any) => alerts.showInputAlert(options)
},
assets: {
all: assets.assetsMap,
all: new Proxy<any>({}, {
get(cache, p) {
if (typeof p !== "string") return undefined;
if (cache[p]) return cache[p];

for (const asset of assets.iterateAssets()) {
if (asset.name) return cache[p] = asset;
}
},
ownKeys(cache) {
const keys = new Set<string>();

for (const asset of assets.iterateAssets()) {
cache[asset.name] = asset;
keys.add(asset.name);
}

return [...keys];
},
}),
find: (filter: (a: any) => boolean) => assets.findAsset(filter),
getAssetByName: (name: string) => assets.findAsset(name),
getAssetByID: (id: number) => assets.findAsset(id),
Expand Down
94 changes: 0 additions & 94 deletions src/lib/api/assets.ts

This file was deleted.

78 changes: 78 additions & 0 deletions src/lib/api/assets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { getMetroCache } from "@metro/internals/caches";
import { ModuleFlags } from "@metro/internals/enums";
import { requireModule } from "@metro/internals/modules";

import { assetsModule } from "./patches";

export interface Asset {
id: number;
name: string;
moduleId: number;
}

// Cache common usage
const _nameToAssetCache = {} as Record<string, Asset>;

export function* iterateAssets() {
const { flagsIndex } = getMetroCache();
const yielded = new Set<number>();

for (const id in flagsIndex) {
if (flagsIndex[id] & ModuleFlags.ASSET) {
const assetId = requireModule(Number(id));
if (typeof assetId !== "number" || yielded.has(assetId)) continue;
yield getAssetById(assetId);
yielded.add(assetId);
}
}
}

// Apply additional properties for convenience
function getAssetById(id: number): Asset {
const asset = assetsModule.getAssetByID(id);
if (!asset) return asset;
return Object.assign(asset, { id });
}

/**
* Returns the first asset registry by its registry id (number), name (string) or given filter (function)
*/
export function findAsset(id: number): Asset | undefined;
export function findAsset(name: string): Asset | undefined;
export function findAsset(filter: (a: Asset) => boolean): Asset | undefined;

export function findAsset(param: number | string | ((a: Asset) => boolean)) {
if (typeof param === "number") return getAssetById(param);

if (typeof param === "string" && _nameToAssetCache[param]) {
return _nameToAssetCache[param];
}

for (const asset of iterateAssets()) {
if (typeof param === "string" && asset.name === param) {
_nameToAssetCache[param] = asset;
return asset;
} else if (typeof param === "function" && param(asset)) {
return asset;
}
}
}

export function filterAssets(param: string | ((a: Asset) => boolean)) {
const filteredAssets = [] as Array<Asset>;

for (const asset of iterateAssets()) {
if (typeof param === "string" ? asset.name === param : param(asset)) {
filteredAssets.push(asset);
}
}

return filteredAssets;
}

/**
* Returns the first asset ID in the registry with the given name
*/
export function findAssetId(name: string) {
return findAsset(name)?.id;
}
25 changes: 25 additions & 0 deletions src/lib/api/assets/patches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { after } from "@lib/api/patcher";
import { indexAssetModuleFlag } from "@metro/internals/caches";
import { getImportingModuleId } from "@metro/internals/modules";

interface AssetModule {
registerAsset(assetDefinition: any): number;
getAssetByID(id: number): any;
}

export let assetsModule: AssetModule;

/**
* @internal
*/
export function patchAssets(module: AssetModule) {
if (assetsModule) return;
assetsModule = module;

const unpatch = after("registerAsset", assetsModule, () => {
const moduleId = getImportingModuleId();
if (moduleId !== -1) indexAssetModuleFlag(moduleId);
});

return unpatch;
}
1 change: 1 addition & 0 deletions src/lib/utils/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Nullish = null | undefined;
6 changes: 5 additions & 1 deletion src/metro/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { lazyDestructure } from "@lib/utils/lazy";
import { findByFilePathLazy, findByProps, findByPropsLazy } from "@metro/wrappers";

import type { Dispatcher } from "./types/flux";
Expand All @@ -18,13 +19,16 @@ export const toasts = findByFilePathLazy("modules/toast/native/ToastActionCreato
export const messageUtil = findByPropsLazy("sendBotMessage");
export const navigationStack = findByPropsLazy("createStackNavigator");
export const NavigationNative = findByPropsLazy("NavigationContainer");
export const tokens = findByPropsLazy("colors", "unsafe_rawColors");
export const semver = findByPropsLazy("parse", "clean");

export const tokens = findByPropsLazy("unsafe_rawColors", "colors");
export const { useToken } = lazyDestructure(() => findByProps("useToken"));

// Flux
export const Flux = findByPropsLazy("connectStores");
// TODO: Making this a proxy/lazy fuck things up for some reason
export const FluxDispatcher = findByProps("_interceptors") as Dispatcher;
export const FluxUtils = findByProps("useStateFromStores");

// React
export const React = window.React = findByPropsLazy("createElement") as typeof import("react");
Expand Down
3 changes: 3 additions & 0 deletions src/metro/common/stores.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { findByStoreNameLazy } from "@metro/wrappers";

export const UserStore = findByStoreNameLazy("UserStore");
6 changes: 4 additions & 2 deletions src/metro/common/types/components.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TextStyles, ThemeColors } from "@lib/ui/types";
import { Nullish } from "@lib/utils/types";
import { TextStyles, ThemeColors } from "@ui/types";
import { Falsey } from "lodash";
import { FC, MutableRefObject, PropsWithoutRef, ReactNode, RefObject } from "react";
import type * as RN from "react-native";
Expand Down Expand Up @@ -110,7 +111,7 @@ interface TextInputProps extends Omit<RN.TextInputProps, "onChange" | "onChangeT
trailingIcon?: React.FC<any>;
trailingPressableProps?: PressableProps;
trailingText?: string;
value?: string | Falsey;
value?: string | Nullish;
}

export type TextInput = React.FC<TextInputProps>;
Expand Down Expand Up @@ -141,6 +142,7 @@ interface FABProps {
style?: Style;
onPress: () => void;
positionBottom?: number;

}

export type FloatingActionButton = React.FC<FABProps>;
Expand Down
1 change: 1 addition & 0 deletions src/metro/finders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function findModuleId<A extends unknown[]>(filter: FilterFn<A>) {
export function findExports<A extends unknown[]>(filter: FilterFn<A>) {
const { id, defaultExport } = findModule(filter);
if (id == null) return;

return defaultExport ? requireModule(id).default : requireModule(id);
}

Expand Down
Loading

0 comments on commit cc87948

Please sign in to comment.