From cb845b522458532479c077ed82279c27e025601e Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 23 Sep 2025 23:58:38 +0200 Subject: [PATCH] PlatformIndicators: update indicators in real time if status changes Closes #3516 --- packages/discord-types/src/utils.d.ts | 8 +++-- src/plugins/index.ts | 4 +-- src/plugins/platformIndicators/index.tsx | 41 +++++++----------------- src/utils/types.ts | 6 ++-- 4 files changed, 21 insertions(+), 38 deletions(-) diff --git a/packages/discord-types/src/utils.d.ts b/packages/discord-types/src/utils.d.ts index 77b6f88b..14b8fa50 100644 --- a/packages/discord-types/src/utils.d.ts +++ b/packages/discord-types/src/utils.d.ts @@ -6,13 +6,15 @@ import type { FluxEvents } from "./fluxEvents"; export { FluxEvents }; +type FluxEventsAutoComplete = LiteralUnion; + export interface FluxDispatcher { _actionHandlers: any; _subscriptions: any; - dispatch(event: { [key: string]: unknown; type: FluxEvents; }): Promise; + dispatch(event: { [key: string]: unknown; type: FluxEventsAutoComplete; }): Promise; isDispatching(): boolean; - subscribe(event: FluxEvents, callback: (data: any) => void): void; - unsubscribe(event: FluxEvents, callback: (data: any) => void): void; + subscribe(event: FluxEventsAutoComplete, callback: (data: any) => void): void; + unsubscribe(event: FluxEventsAutoComplete, callback: (data: any) => void): void; wait(callback: () => void): void; } diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 8288935b..5bb60a13 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -222,7 +222,7 @@ export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Flux for (const [event, handler] of Object.entries(p.flux)) { const wrappedHandler = p.flux[event] = function () { try { - const res = handler.apply(p, arguments as any); + const res = handler!.apply(p, arguments as any); return res instanceof Promise ? res.catch(e => logger.error(`${p.name}: Error while handling ${event}\n`, e)) : res; @@ -242,7 +242,7 @@ export function unsubscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Fl logger.debug("Unsubscribing from flux events of plugin", p.name); for (const [event, handler] of Object.entries(p.flux)) { - fluxDispatcher.unsubscribe(event as FluxEvents, handler); + fluxDispatcher.unsubscribe(event as FluxEvents, handler!); } } } diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index f804e987..add93064 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -22,12 +22,11 @@ import { addProfileBadge, BadgePosition, BadgeUserArgs, ProfileBadge, removeProf import { addMemberListDecorator, removeMemberListDecorator } from "@api/MemberListDecorators"; import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecorations"; import { Settings } from "@api/Settings"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { User } from "@vencord/discord-types"; import { filters, findStoreLazy, mapMangledModuleLazy } from "@webpack"; -import { PresenceStore, Tooltip, UserStore } from "@webpack/common"; +import { AuthenticationStore, PresenceStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; export interface Session { sessionId: string; @@ -85,7 +84,7 @@ const PlatformIcon = ({ platform, status, small }: { platform: Platform, status: }; function ensureOwnStatus(user: User) { - if (user.id === UserStore.getCurrentUser().id) { + if (user.id === AuthenticationStore.getId()) { const sessions = SessionsStore.getSessions(); if (typeof sessions !== "object") return null; const sortedSessions = Object.values(sessions).sort(({ status: a }, { status: b }) => { @@ -104,7 +103,7 @@ function ensureOwnStatus(user: User) { }, {}); const { clientStatuses } = PresenceStore.getState(); - clientStatuses[UserStore.getCurrentUser().id] = ownStatus; + clientStatuses[AuthenticationStore.getId()] = ownStatus; } } @@ -115,7 +114,7 @@ function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] { ensureOwnStatus(user); - const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record; + const status = PresenceStore.getClientStatus(user.id) as Record; if (!status) return []; return Object.entries(status).map(([platform, status]) => ({ @@ -134,11 +133,9 @@ function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] { } const PlatformIndicator = ({ user, small = false }: { user: User; small?: boolean; }) => { - if (!user || user.bot) return null; - ensureOwnStatus(user); - const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record; + const status = useStateFromStores([PresenceStore], () => PresenceStore.getClientStatus(user.id) as Record); if (!status) return null; const icons = Object.entries(status).map(([platform, status]) => ( @@ -170,10 +167,8 @@ const badge: ProfileBadge = { const indicatorLocations = { list: { description: "In the member list", - onEnable: () => addMemberListDecorator("platform-indicator", props => - - - + onEnable: () => addMemberListDecorator("platform-indicator", ({ user }) => + user && !user.bot ? : null ), onDisable: () => removeMemberListDecorator("platform-indicator") }, @@ -184,11 +179,10 @@ const indicatorLocations = { }, messages: { description: "Inside messages", - onEnable: () => addMessageDecoration("platform-indicator", props => - - - - ), + onEnable: () => addMessageDecoration("platform-indicator", props => { + const user = props.message?.author; + return user && !user.bot ? : null; + }), onDisable: () => removeMessageDecoration("platform-indicator") } }; @@ -201,19 +195,6 @@ export default definePlugin({ start() { const settings = Settings.plugins.PlatformIndicators; - const { displayMode } = settings; - - // transfer settings from the old ones, which had a select menu instead of booleans - if (displayMode) { - if (displayMode !== "both") settings[displayMode] = true; - else { - settings.list = true; - settings.badges = true; - } - settings.messages = true; - delete settings.displayMode; - } - Object.entries(indicatorLocations).forEach(([key, value]) => { if (settings[key]) value.onEnable(); }); diff --git a/src/utils/types.ts b/src/utils/types.ts index 2293b2ff..2d21eaff 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -151,9 +151,9 @@ export interface PluginDef { /** * Allows you to subscribe to Flux events */ - flux?: { - [E in LiteralUnion]?: (event: any) => void | Promise; - }; + flux?: Partial<{ + [E in LiteralUnion]: (event: any) => void | Promise; + }>; /** * Allows you to manipulate context menus */