GoonCord/src/core/debug/patches/patchSafeCard.ts
2026-08-09 23:41:24 +02:00

141 lines
3.5 KiB
TypeScript

import React from "react";
import { View } from "react-native";
import { byProps } from "@metro/filters";
import { findExports } from "@metro/finders";
import { findByStoreNameLazy } from "@metro/wrappers";
import { instead } from "@lib/api/patcher";
import { logger } from "@lib/utils/logger";
import { isSemanticColor, resolveSemanticColor, semanticColors } from "@ui/color";
const ThemeStore = findByStoreNameLazy("ThemeStore");
function log(...messages: any[]) {
try {
logger.warn("[ShiggyCord] patchSafeCard:", ...messages);
} catch {}
}
let cardHealthy = false;
const FALLBACK_STYLE = {
borderRadius: 8,
padding: 16,
};
function resolveCardBackground(): string | undefined {
try {
const color = semanticColors?.CARD_BACKGROUND_DEFAULT;
if (isSemanticColor(color)) return resolveSemanticColor(color);
if (typeof color === "string") return color;
} catch {}
return undefined;
}
export default function patchSafeCard() {
const unpatchers: Array<() => boolean> = [];
try {
const cardModule = findExports(byProps("Card"));
const origCard = cardModule?.Card;
if (typeof origCard !== "function") {
log("no Card function on the resolved module, skipping");
return () => unpatchers.forEach((unpatch) => unpatch());
}
log("resolved design Card from first-match module");
let cardBackground = resolveCardBackground();
const unsubscribeTheme = ThemeStore?.addChangeListener?.(() => {
const resolved = resolveCardBackground();
if (resolved) cardBackground = resolved;
});
if (typeof unsubscribeTheme === "function") {
unpatchers.push(() => {
unsubscribeTheme();
return true;
});
}
class CardProbeBoundary extends React.Component<
{
fallback: React.ReactNode;
children?: React.ReactNode;
},
{ hasError: boolean }
> {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: unknown) {
try {
log("Card render threw, using View fallback", error);
} catch {}
}
render() {
if (this.state.hasError) return this.props.fallback;
return this.props.children;
}
}
class HealthyProbe extends React.Component<{
onHealthy: () => void;
children?: React.ReactNode;
}> {
componentDidMount() {
this.props.onHealthy();
}
render() {
return this.props.children;
}
}
const SafeCard = function SafeCard(props: any) {
if (cardHealthy) return React.createElement(origCard, props);
return React.createElement(
CardProbeBoundary,
{
fallback: React.createElement(
View,
{
style: [
FALLBACK_STYLE,
...(cardBackground
? [{ backgroundColor: cardBackground }]
: []),
props?.style,
],
},
props?.children,
),
},
React.createElement(
HealthyProbe,
{
onHealthy: () => {
cardHealthy = true;
},
},
React.createElement(origCard, props),
),
);
};
unpatchers.push(
instead("Card", cardModule, (args: any[]) => SafeCard(args[0] ?? {})),
);
log("patched design Card (adaptive probe on first mount)");
} catch (e) {
log("patch failed", e);
}
return () => unpatchers.forEach((unpatch) => unpatch());
}