From 67a9e63799aaec65d25d9eb22e839fd717b4b1de Mon Sep 17 00:00:00 2001 From: Ally Founder Date: Mon, 10 Aug 2026 21:23:58 -0400 Subject: [PATCH] FakeProfileThemesAndEffects: actually fix the Effects picker crash --- .../patches/patchUseProfileEffectSections.ts | 28 +++++++++++-------- .../actionSheets/EffectPickerActionSheet.tsx | 14 ++++++++-- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/plugins/fake-profile-themes-and-effects/src/patches/patchUseProfileEffectSections.ts b/plugins/fake-profile-themes-and-effects/src/patches/patchUseProfileEffectSections.ts index 68b654b..59ddf3f 100644 --- a/plugins/fake-profile-themes-and-effects/src/patches/patchUseProfileEffectSections.ts +++ b/plugins/fake-profile-themes-and-effects/src/patches/patchUseProfileEffectSections.ts @@ -13,17 +13,23 @@ let prevSections: Record[]; export const patchUseProfileEffectSections = () => useSectionModules.map( sectionModule => after("default", sectionModule, (_args: unknown[], origSections: typeof prevSections) => { - if (previewUserId) { - const currProfileEffects = ProfileEffectStore.profileEffects; - if (prevProfileEffects !== currProfileEffects) { - origSections.splice(1); - origSections[0]!.items.splice(1); - ProfileEffectStore.profileEffects.forEach(effect => { - origSections[0]!.items.push(new ProfileEffectRecord(effect)); - }); - prevSections = origSections; - } else - origSections = prevSections; + try { + if (previewUserId && origSections?.[0]?.items) { + const currProfileEffects = ProfileEffectStore.profileEffects; + if (prevProfileEffects !== currProfileEffects) { + origSections.splice(1); + origSections[0]!.items.splice(1); + ProfileEffectStore.profileEffects.forEach(effect => { + origSections[0]!.items.push(new ProfileEffectRecord(effect)); + }); + prevSections = origSections; + } else if (prevSections) { + origSections = prevSections; + } + } + } catch { + // A broken section rewrite shouldn't crash the whole effect-browsing screen - let + // Discord's own sections render unmodified instead. } return origSections; }) diff --git a/plugins/fake-profile-themes-and-effects/src/ui/actionSheets/EffectPickerActionSheet.tsx b/plugins/fake-profile-themes-and-effects/src/ui/actionSheets/EffectPickerActionSheet.tsx index 5959dbc..0225d29 100644 --- a/plugins/fake-profile-themes-and-effects/src/ui/actionSheets/EffectPickerActionSheet.tsx +++ b/plugins/fake-profile-themes-and-effects/src/ui/actionSheets/EffectPickerActionSheet.tsx @@ -24,15 +24,23 @@ let lastGoodTree: RN.Node; function PatchedEffectPickerActionSheet(props: EffectPickerActionSheetProps) { const { currentEffectId, effects, onSelect, user } = props; + // This has to be the very first thing checked, before EffectPicker is ever called below - + // that call runs Discord's own EditProfileEffectActionSheet as a plain function from inside + // this component's own render, which chains its internal hooks onto this fiber. Checking the + // setting only *after* that call (as this used to) still paid that cost on every render + // regardless of the setting - the crash it exists to avoid had already happened by the time + // the fallback kicked in. forceFallbackEffectPicker doesn't change while this component is + // mounted, so returning early here before any hooks run is safe across this component's own + // re-renders. + if (storage.forceFallbackEffectPicker) + return ; + const tree = EffectPicker!({ user }); const themeContext = useThemeContext(); const effectRecords = useMemo(() => effects.map(effect => ({ items: new ProfileEffectRecord(effect) })), [effects]); - if (storage.forceFallbackEffectPicker) - return ; - let isLegacyEffectPicker = false; const effectPickerInner: RN.Element | null = findElementInTree(tree, element => { if (getComponentNameFromType(element.type) === "EditProfileEffectInner")