fix: make badges work again

This commit is contained in:
cocobo1 2026-03-18 22:12:52 +02:00
parent cb6a242fe8
commit 1cf2787f3a

View file

@ -1,15 +1,43 @@
import { after } from "@lib/api/patcher";
import { onJsxCreate } from "@lib/api/react/jsx";
import { findByName } from "@metro";
import { findByName, findByNameLazy } from "@metro";
import { useEffect, useState } from "react";
import { defineCorePlugin } from "..";
import { FluxDispatcher } from "@metro/common";
interface BunnyBadge {
interface Badge {
label: string;
url: string;
}
const useBadgesModule = findByName("useBadges", false);
interface CustomBadge {
label: string;
url: string;
}
interface UserBadgeData {
roles?: string[];
custom?: CustomBadge[];
}
interface BadgeData {
[userId: string]: UserBadgeData;
}
interface RoleData {
label: string;
url: string;
}
interface RolesData {
[roleName: string]: RoleData;
}
const useBadgesModule = findByNameLazy("useBadges", false);
const badgesCache = new Map<string, Badge[]>();
const badgeProps = new Map<string, Record<string, any>>();
const pendingRequests = new Set<string>();
export default defineCorePlugin({
manifest: {
@ -26,12 +54,9 @@ export default defineCorePlugin({
},
start() {
let allBadges: { [x: string]: any; } | null = null;
const badgeProps = {} as Record<string, any>;
onJsxCreate("ProfileBadge", (component, ret) => {
if (ret.props.id?.startsWith("bunny-")) {
const cachedProps = badgeProps[ret.props.id];
if (ret.props.id?.startsWith("rain-")) {
const cachedProps = badgeProps.get(ret.props.id);
if (cachedProps) {
ret.props.source = cachedProps.source;
ret.props.label = cachedProps.label;
@ -39,54 +64,91 @@ export default defineCorePlugin({
}
}
});
onJsxCreate("RenderedBadge", (component, ret) => {
if (ret.props.id?.startsWith("bunny-")) {
const cachedProps = badgeProps[ret.props.id];
if (ret.props.id?.startsWith("rain-")) {
const cachedProps = badgeProps.get(ret.props.id);
if (cachedProps) {
Object.assign(ret.props, cachedProps);
}
}
});
after("default", useBadgesModule, ([user], result) => {
const [badges, setBadges] = useState<BunnyBadge[]>([]);
useEffect(() => {
if (!user) return;
if (!allBadges) {
fetch("https://codeberg.org/raincord/badges/raw/branch/main/badges.json")
.then(r => r.json())
.then(data => {
allBadges = data;
//@ts-expect-error
setBadges(allBadges[user.userId] || []);
})
} else {
//user has no badges, but maybe they should get some by contributing
setBadges(allBadges[user.userId] || []);
const fetchAndProcessBadges = async (userId: string) => {
if (pendingRequests.has(userId)) return;
pendingRequests.add(userId);
try {
const [badgesRes, rolesRes] = await Promise.all([
fetch("https://codeberg.org/raincord/badges/raw/branch/main/badges.json"),
fetch("https://codeberg.org/raincord/badges/raw/branch/main/assets/roles/roles.json"),
]);
const badgesData: BadgeData = await badgesRes.json();
const rolesData: RolesData = await rolesRes.json();
const userBadgeData = badgesData[userId] || { roles: [], custom: [] };
const allBadges: Badge[] = [];
// process role badges
if (userBadgeData.roles) {
userBadgeData.roles.forEach(roleName => {
const roleData = rolesData[roleName];
if (roleData) {
allBadges.push({
label: roleData.label,
url: roleData.url,
});
}
});
}
}, [user?.userId]);
if (user && badges.length > 0) {
badges.forEach((badge, i) => {
const badgeId = `bunny-${user.userId}-${i}`;
badgeProps[badgeId] = {
// process custom badges
if (userBadgeData.custom) {
allBadges.push(...userBadgeData.custom);
}
badgesCache.set(userId, allBadges);
allBadges.forEach((badge, i) => {
const badgeId = `rain-${userId}-${i}`;
badgeProps.set(badgeId, {
id: badgeId,
source: { uri: badge.url },
label: badge.label,
userId: user.userId,
};
result.push({
id: badgeId,
description: badge.label,
icon: " _",
userId,
});
});
FluxDispatcher.dispatch({ type: "USER_UPDATE", user: { id: userId } });
} finally {
pendingRequests.delete(userId);
}
};
after("default", useBadgesModule, ([user], result) => {
if (!user) return;
const userId = user.userId;
const cached = badgesCache.get(userId);
if (!cached) {
if (!pendingRequests.has(userId)) {
fetchAndProcessBadges(userId);
}
return;
}
cached.forEach((badge, i) => {
const badgeId = `rain-${userId}-${i}`;
result.unshift({
id: badgeId,
description: badge.label,
icon: " _",
});
});
});
}
});