diff --git a/src/api/Badges.ts b/src/api/Badges.ts index 24c68c4e..7a041f1e 100644 --- a/src/api/Badges.ts +++ b/src/api/Badges.ts @@ -44,6 +44,11 @@ export interface ProfileBadge { position?: BadgePosition; /** The badge name to display, Discord uses this. Required for component badges */ key?: string; + + /** + * Allows dynamically returning multiple badges + */ + getBadges?(userInfo: BadgeUserArgs): ProfileBadge[]; } const Badges = new Set(); @@ -73,9 +78,16 @@ export function _getBadges(args: BadgeUserArgs) { const badges = [] as ProfileBadge[]; for (const badge of Badges) { 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 - ? badges.unshift({ ...badge, ...args }) - : badges.push({ ...badge, ...args }); + ? badges.unshift(...b) + : badges.push(...b); } } const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId); diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index cb153c6a..94dc673a 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -136,6 +136,8 @@ export default definePlugin({ }, getBadges(props: { userId: string; user?: User; guildId: string; }) { + if (!props) return []; + try { props.userId ??= props.user?.id!; diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index 2b8a8938..1dc76e9d 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -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 { addDecoration, removeDecoration } from "@api/MessageDecorations"; import { Settings } from "@api/Settings"; @@ -27,7 +29,20 @@ import { findByPropsLazy, findStoreLazy } from "@webpack"; import { PresenceStore, Tooltip, UserStore } from "@webpack/common"; 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; +}; function Icon(path: string, opts?: { viewBox?: string; width?: number; height?: number; }) { return ({ color, tooltip, small }: { color: string; tooltip: string; small: boolean; }) => ( @@ -67,15 +82,11 @@ const PlatformIcon = ({ platform, status, small }: { platform: Platform, status: return ; }; -const getStatus = (id: string): Record => PresenceStore.getState()?.clientStatuses?.[id]; - -const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => { - if (!user || user.bot) return null; - +function ensureOwnStatus(user: User) { if (user.id === UserStore.getCurrentUser().id) { const sessions = SessionsStore.getSessions(); 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 === "online") return 1; if (b === "online") return -1; @@ -84,7 +95,7 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma 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") acc[curr.clientInfo.client] = curr.status; return acc; @@ -93,6 +104,37 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma const { clientStatuses } = PresenceStore.getState(); 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; + if (!status) return []; + + return Object.entries(status).map(([platform, status]) => ({ + component: () => ( + + + + ), + 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; if (!status) return null; @@ -112,16 +154,10 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma {icons} @@ -129,10 +165,8 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma }; const badge: ProfileBadge = { - component: p => , + getBadges, position: BadgePosition.START, - shouldShow: userInfo => !!Object.keys(getStatus(userInfo.userId) ?? {}).length, - key: "indicator" }; const indicatorLocations = { diff --git a/src/plugins/platformIndicators/style.css b/src/plugins/platformIndicators/style.css new file mode 100644 index 00000000..38ea5ef4 --- /dev/null +++ b/src/plugins/platformIndicators/style.css @@ -0,0 +1,7 @@ +.vc-platform-indicator { + display: inline-flex; + justify-content: center; + align-items: center; + vertical-align: top; + position: relative; +}