From 9bac8d69539d47b88993c992c2654e4fc6c94de8 Mon Sep 17 00:00:00 2001 From: Ally Founder Date: Mon, 10 Aug 2026 20:48:15 -0400 Subject: [PATCH] FakeProfileThemesAndEffects: fix crash opening the profile edit screen --- .../src/lib/reactNativeRenderTree.ts | 6 +++ .../src/patches/patchNitroUpsellCard.tsx | 11 +++-- .../src/patches/patchUserProfileEditForm.tsx | 45 +++++++++++-------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/plugins/fake-profile-themes-and-effects/src/lib/reactNativeRenderTree.ts b/plugins/fake-profile-themes-and-effects/src/lib/reactNativeRenderTree.ts index 3ae9d76..bec838e 100644 --- a/plugins/fake-profile-themes-and-effects/src/lib/reactNativeRenderTree.ts +++ b/plugins/fake-profile-themes-and-effects/src/lib/reactNativeRenderTree.ts @@ -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) diff --git a/plugins/fake-profile-themes-and-effects/src/patches/patchNitroUpsellCard.tsx b/plugins/fake-profile-themes-and-effects/src/patches/patchNitroUpsellCard.tsx index 512f5dc..c926ea8 100644 --- a/plugins/fake-profile-themes-and-effects/src/patches/patchNitroUpsellCard.tsx +++ b/plugins/fake-profile-themes-and-effects/src/patches/patchNitroUpsellCard.tsx @@ -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; + } }); }; \ No newline at end of file diff --git a/plugins/fake-profile-themes-and-effects/src/patches/patchUserProfileEditForm.tsx b/plugins/fake-profile-themes-and-effects/src/patches/patchUserProfileEditForm.tsx index b10d84f..eaabe8a 100644 --- a/plugins/fake-profile-themes-and-effects/src/patches/patchUserProfileEditForm.tsx +++ b/plugins/fake-profile-themes-and-effects/src/patches/patchUserProfileEditForm.tsx @@ -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((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, ); + if (parent) { + const index = parent.props.children.reduce((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, ); + } } + } catch { + // One broken edit-form render shouldn't crash the whole profile edit screen. } return tree; - }); \ No newline at end of file + }); +}; \ No newline at end of file