/* * Vencord, a Discord client mod * Copyright (c) 2025 Vendicated and contributors * SPDX-License-Identifier: GPL-3.0-or-later */ import ErrorBoundary from "@components/ErrorBoundary"; import { Logger } from "@utils/Logger"; import { useEffect, useState } from "@webpack/common"; import type { JSX } from "react"; const logger = new Logger("ProfileCollectionAPI"); export type ProfileCollectionFactory = Function; export interface ProfileCollectionData { /** Function that renders the collection component, receives the full profile props */ render: ProfileCollectionFactory; /** Higher priority collections appear first in the list. Default: 0 */ priority?: number; } interface CollectionEntry { render: ProfileCollectionFactory; priority: number; } const profileCollections = new Map(); const profileCollectionListeners = new Set<() => void>(); /** * Adds a collection to the user profile panel. * * @param id - Unique identifier for the collection (e.g., "my-plugin-profile-collection") * @param render - Function that returns the collection JSX. Receives the full profile props object. * @param priority - Higher values appear first. Default: 0 * * @example * addProfileCollection("my-collection", (props) => ( *
Custom content for {props.user.id}
* )); */ export function addProfileCollection(id: string, render: ProfileCollectionFactory, priority = 0) { profileCollections.set(id, { render, priority }); profileCollectionListeners.forEach(listener => listener()); } /** * Removes a collection from the user profile panel. * * @param id - The identifier used when adding the collection */ export function removeProfileCollection(id: string) { profileCollections.delete(id); profileCollectionListeners.forEach(listener => listener()); } function ProfileCollections({ props }: { props: any; }) { const [, forceUpdate] = useState(0); useEffect(() => { const listener = () => forceUpdate(n => n + 1); profileCollectionListeners.add(listener); return () => { profileCollectionListeners.delete(listener); }; }, []); return Array.from(profileCollections) .sort(([, a], [, b]) => b.priority - a.priority) .map(([id, { render: Collection }]) => ( logger.error(`Failed to render profile collection: ${id}`, e.error)}> {Collection({ ...props, user: props.user ?? props.currentUser })} )); } /** @internal Injected by ProfileCollectionAPI patch (do NOT call directly) */ export function renderProfileCollections(props: any) { return ; }