FakeProfileThemesAndEffects: actually fix the Effects picker crash

This commit is contained in:
Ally Founder 2026-08-10 21:23:58 -04:00
parent f4c4664feb
commit 67a9e63799
2 changed files with 28 additions and 14 deletions

View file

@ -13,17 +13,23 @@ let prevSections: Record<string, any>[];
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;
})

View file

@ -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 <FallbackEffectPickerActionSheet {...props} />;
const tree = EffectPicker!({ user });
const themeContext = useThemeContext();
const effectRecords = useMemo(() => effects.map(effect => ({ items: new ProfileEffectRecord(effect) })), [effects]);
if (storage.forceFallbackEffectPicker)
return <FallbackEffectPickerActionSheet {...props} />;
let isLegacyEffectPicker = false;
const effectPickerInner: RN.Element<any> | null = findElementInTree(tree, element => {
if (getComponentNameFromType(element.type) === "EditProfileEffectInner")