PlatformIndicators: update indicators in real time if status changes

Closes #3516
This commit is contained in:
Vendicated 2025-09-23 23:58:38 +02:00
parent 746c824020
commit cb845b5224
No known key found for this signature in database
GPG key ID: D66986BAF75ECF18
4 changed files with 21 additions and 38 deletions

View file

@ -6,13 +6,15 @@ import type { FluxEvents } from "./fluxEvents";
export { FluxEvents };
type FluxEventsAutoComplete = LiteralUnion<FluxEvents, string>;
export interface FluxDispatcher {
_actionHandlers: any;
_subscriptions: any;
dispatch(event: { [key: string]: unknown; type: FluxEvents; }): Promise<void>;
dispatch(event: { [key: string]: unknown; type: FluxEventsAutoComplete; }): Promise<void>;
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;
}

View file

@ -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!);
}
}
}

View file

@ -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<Platform, string>;
const status = PresenceStore.getClientStatus(user.id) as Record<Platform, string>;
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<Platform, string>;
const status = useStateFromStores([PresenceStore], () => PresenceStore.getClientStatus(user.id) as Record<Platform, string>);
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 =>
<ErrorBoundary noop>
<PlatformIndicator user={props.user} small={true} />
</ErrorBoundary>
onEnable: () => addMemberListDecorator("platform-indicator", ({ user }) =>
user && !user.bot ? <PlatformIndicator user={user} small={true} /> : null
),
onDisable: () => removeMemberListDecorator("platform-indicator")
},
@ -184,11 +179,10 @@ const indicatorLocations = {
},
messages: {
description: "Inside messages",
onEnable: () => addMessageDecoration("platform-indicator", props =>
<ErrorBoundary noop>
<PlatformIndicator user={props.message?.author} />
</ErrorBoundary>
),
onEnable: () => addMessageDecoration("platform-indicator", props => {
const user = props.message?.author;
return user && !user.bot ? <PlatformIndicator user={props.message?.author} /> : 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();
});

View file

@ -151,9 +151,9 @@ export interface PluginDef {
/**
* Allows you to subscribe to Flux events
*/
flux?: {
[E in LiteralUnion<FluxEvents, string>]?: (event: any) => void | Promise<void>;
};
flux?: Partial<{
[E in LiteralUnion<FluxEvents, string>]: (event: any) => void | Promise<void>;
}>;
/**
* Allows you to manipulate context menus
*/