BadgeAPI: fix bugs in new profiles

This commit is contained in:
Vendicated 2024-06-26 18:09:21 +02:00
parent e0d99e2f6c
commit bc0d4a80ff
No known key found for this signature in database
GPG key ID: D66986BAF75ECF18
4 changed files with 75 additions and 20 deletions

View file

@ -44,6 +44,11 @@ export interface ProfileBadge {
position?: BadgePosition; position?: BadgePosition;
/** The badge name to display, Discord uses this. Required for component badges */ /** The badge name to display, Discord uses this. Required for component badges */
key?: string; key?: string;
/**
* Allows dynamically returning multiple badges
*/
getBadges?(userInfo: BadgeUserArgs): ProfileBadge[];
} }
const Badges = new Set<ProfileBadge>(); const Badges = new Set<ProfileBadge>();
@ -73,9 +78,16 @@ export function _getBadges(args: BadgeUserArgs) {
const badges = [] as ProfileBadge[]; const badges = [] as ProfileBadge[];
for (const badge of Badges) { for (const badge of Badges) {
if (!badge.shouldShow || badge.shouldShow(args)) { if (!badge.shouldShow || badge.shouldShow(args)) {
const b = badge.getBadges
? badge.getBadges(args).map(b => {
b.component &&= ErrorBoundary.wrap(b.component, { noop: true });
return b;
})
: [{ ...badge, ...args }];
badge.position === BadgePosition.START badge.position === BadgePosition.START
? badges.unshift({ ...badge, ...args }) ? badges.unshift(...b)
: badges.push({ ...badge, ...args }); : badges.push(...b);
} }
} }
const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId); const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId);

View file

@ -136,6 +136,8 @@ export default definePlugin({
}, },
getBadges(props: { userId: string; user?: User; guildId: string; }) { getBadges(props: { userId: string; user?: User; guildId: string; }) {
if (!props) return [];
try { try {
props.userId ??= props.user?.id!; props.userId ??= props.user?.id!;

View file

@ -16,7 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { addBadge, BadgePosition, ProfileBadge, removeBadge } from "@api/Badges"; import "./style.css";
import { addBadge, BadgePosition, BadgeUserArgs, ProfileBadge, removeBadge } from "@api/Badges";
import { addDecorator, removeDecorator } from "@api/MemberListDecorators"; import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
import { addDecoration, removeDecoration } from "@api/MessageDecorations"; import { addDecoration, removeDecoration } from "@api/MessageDecorations";
import { Settings } from "@api/Settings"; import { Settings } from "@api/Settings";
@ -27,7 +29,20 @@ import { findByPropsLazy, findStoreLazy } from "@webpack";
import { PresenceStore, Tooltip, UserStore } from "@webpack/common"; import { PresenceStore, Tooltip, UserStore } from "@webpack/common";
import { User } from "discord-types/general"; import { User } from "discord-types/general";
const SessionsStore = findStoreLazy("SessionsStore"); export interface Session {
sessionId: string;
status: string;
active: boolean;
clientInfo: {
version: number;
os: string;
client: string;
};
}
const SessionsStore = findStoreLazy("SessionsStore") as {
getSessions(): Record<string, Session>;
};
function Icon(path: string, opts?: { viewBox?: string; width?: number; height?: number; }) { function Icon(path: string, opts?: { viewBox?: string; width?: number; height?: number; }) {
return ({ color, tooltip, small }: { color: string; tooltip: string; small: boolean; }) => ( return ({ color, tooltip, small }: { color: string; tooltip: string; small: boolean; }) => (
@ -67,15 +82,11 @@ const PlatformIcon = ({ platform, status, small }: { platform: Platform, status:
return <Icon color={StatusUtils.useStatusFillColor(status)} tooltip={tooltip} small={small} />; return <Icon color={StatusUtils.useStatusFillColor(status)} tooltip={tooltip} small={small} />;
}; };
const getStatus = (id: string): Record<Platform, string> => PresenceStore.getState()?.clientStatuses?.[id]; function ensureOwnStatus(user: User) {
const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => {
if (!user || user.bot) return null;
if (user.id === UserStore.getCurrentUser().id) { if (user.id === UserStore.getCurrentUser().id) {
const sessions = SessionsStore.getSessions(); const sessions = SessionsStore.getSessions();
if (typeof sessions !== "object") return null; if (typeof sessions !== "object") return null;
const sortedSessions = Object.values(sessions).sort(({ status: a }: any, { status: b }: any) => { const sortedSessions = Object.values(sessions).sort(({ status: a }, { status: b }) => {
if (a === b) return 0; if (a === b) return 0;
if (a === "online") return 1; if (a === "online") return 1;
if (b === "online") return -1; if (b === "online") return -1;
@ -84,7 +95,7 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
return 0; return 0;
}); });
const ownStatus = Object.values(sortedSessions).reduce((acc: any, curr: any) => { const ownStatus = Object.values(sortedSessions).reduce((acc, curr) => {
if (curr.clientInfo.client !== "unknown") if (curr.clientInfo.client !== "unknown")
acc[curr.clientInfo.client] = curr.status; acc[curr.clientInfo.client] = curr.status;
return acc; return acc;
@ -93,6 +104,37 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
const { clientStatuses } = PresenceStore.getState(); const { clientStatuses } = PresenceStore.getState();
clientStatuses[UserStore.getCurrentUser().id] = ownStatus; clientStatuses[UserStore.getCurrentUser().id] = ownStatus;
} }
}
function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] {
const user = UserStore.getUser(userId);
if (!user || user.bot) return [];
ensureOwnStatus(user);
const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>;
if (!status) return [];
return Object.entries(status).map(([platform, status]) => ({
component: () => (
<span className="vc-platform-indicator">
<PlatformIcon
key={platform}
platform={platform as Platform}
status={status}
small={false}
/>
</span>
),
key: `vc-platform-indicator-${platform}`
}));
}
const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => {
if (!user || user.bot) return null;
ensureOwnStatus(user);
const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>; const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>;
if (!status) return null; if (!status) return null;
@ -112,16 +154,10 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
<span <span
className="vc-platform-indicator" className="vc-platform-indicator"
style={{ style={{
display: "inline-flex",
justifyContent: "center",
alignItems: "center",
marginLeft: wantMargin ? 4 : 0, marginLeft: wantMargin ? 4 : 0,
verticalAlign: "top",
position: "relative",
top: wantTopMargin ? 2 : 0, top: wantTopMargin ? 2 : 0,
gap: 2 gap: 2
}} }}
> >
{icons} {icons}
</span> </span>
@ -129,10 +165,8 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
}; };
const badge: ProfileBadge = { const badge: ProfileBadge = {
component: p => <PlatformIndicator {...p} user={UserStore.getUser(p.userId)} wantMargin={false} />, getBadges,
position: BadgePosition.START, position: BadgePosition.START,
shouldShow: userInfo => !!Object.keys(getStatus(userInfo.userId) ?? {}).length,
key: "indicator"
}; };
const indicatorLocations = { const indicatorLocations = {

View file

@ -0,0 +1,7 @@
.vc-platform-indicator {
display: inline-flex;
justify-content: center;
align-items: center;
vertical-align: top;
position: relative;
}