FakeProfileThemesAndEffects: fix crash opening the profile edit screen

This commit is contained in:
Ally Founder 2026-08-10 20:48:15 -04:00
parent da3cf105f8
commit 9bac8d6953
3 changed files with 40 additions and 22 deletions

View file

@ -89,6 +89,12 @@ export function getComponentNameFromType(type: RN.ElementType) {
return Symbol.keyFor(type) || null;
if (typeof type === "function")
return type.displayName || type.name || null;
// Host components (View, Text, ...) are plain strings, not objects - isProviderType and the
// checks after it all use the `in` operator, which throws on a string primitive rather than
// returning false. This is the exact same bug class as isElementWithChildren's props: null
// crash, just a second, separate instance in this same file.
if (typeof type !== "object" || type === null)
return null;
if (isProviderType(type))
return type._context.displayName || null;
if (type.displayName)

View file

@ -29,9 +29,14 @@ function removeNitroCards(node: RN.Node): RN.Node | null {
}
export const patchNitroUpsellCard = () => {
if (!funcParent) return;
if (!funcParent) return () => {};
after("default", funcParent, (_args: unknown[], tree: RN.Node) => {
return removeNitroCards(tree) || tree;
return after("default", funcParent, (_args: unknown[], tree: RN.Node) => {
try {
return removeNitroCards(tree) || tree;
} catch {
// One broken upsell-card removal shouldn't crash the whole profile edit screen.
return tree;
}
});
};

View file

@ -8,31 +8,38 @@ import { Builder } from "@fpte/ui/components";
const funcParent = findByName("UserProfileEditForm", false);
export const patchUserProfileEditForm = () =>
after("default", funcParent, (_args: unknown[], tree: RN.Node) => {
if (storage.hideBuilder) return tree;
export const patchUserProfileEditForm = () => {
if (!funcParent) return () => {};
const parent = findParentInTree(tree, (children): children is RN.Node[] =>
Array.isArray(children) &&
children.some(child =>
isElement(child) &&
getComponentNameFromType(child.type) === "UserProfileEditFormTextField"
)
);
return after("default", funcParent, (_args: unknown[], tree: RN.Node) => {
try {
if (storage.hideBuilder) return tree;
if (parent) {
const index = parent.props.children.reduce<number[]>((acc, child, i) => {
if (
const parent = findParentInTree(tree, (children): children is RN.Node[] =>
Array.isArray(children) &&
children.some(child =>
isElement(child) &&
getComponentNameFromType(child.type) === "UserProfileEditFormTextField"
) acc.push(i);
return acc;
}, []);
)
);
if (index.length >= 3) {
parent.props.children.splice(index[2] + 1, 0, <Builder />);
if (parent) {
const index = parent.props.children.reduce<number[]>((acc, child, i) => {
if (
isElement(child) &&
getComponentNameFromType(child.type) === "UserProfileEditFormTextField"
) acc.push(i);
return acc;
}, []);
if (index.length >= 3) {
parent.props.children.splice(index[2] + 1, 0, <Builder />);
}
}
} catch {
// One broken edit-form render shouldn't crash the whole profile edit screen.
}
return tree;
});
};