PlatformIndicators: update indicators in real time if status changes
Closes #3516
This commit is contained in:
parent
746c824020
commit
cb845b5224
4 changed files with 21 additions and 38 deletions
8
packages/discord-types/src/utils.d.ts
vendored
8
packages/discord-types/src/utils.d.ts
vendored
|
|
@ -6,13 +6,15 @@ import type { FluxEvents } from "./fluxEvents";
|
||||||
|
|
||||||
export { FluxEvents };
|
export { FluxEvents };
|
||||||
|
|
||||||
|
type FluxEventsAutoComplete = LiteralUnion<FluxEvents, string>;
|
||||||
|
|
||||||
export interface FluxDispatcher {
|
export interface FluxDispatcher {
|
||||||
_actionHandlers: any;
|
_actionHandlers: any;
|
||||||
_subscriptions: any;
|
_subscriptions: any;
|
||||||
dispatch(event: { [key: string]: unknown; type: FluxEvents; }): Promise<void>;
|
dispatch(event: { [key: string]: unknown; type: FluxEventsAutoComplete; }): Promise<void>;
|
||||||
isDispatching(): boolean;
|
isDispatching(): boolean;
|
||||||
subscribe(event: FluxEvents, callback: (data: any) => void): void;
|
subscribe(event: FluxEventsAutoComplete, callback: (data: any) => void): void;
|
||||||
unsubscribe(event: FluxEvents, callback: (data: any) => void): void;
|
unsubscribe(event: FluxEventsAutoComplete, callback: (data: any) => void): void;
|
||||||
wait(callback: () => void): void;
|
wait(callback: () => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Flux
|
||||||
for (const [event, handler] of Object.entries(p.flux)) {
|
for (const [event, handler] of Object.entries(p.flux)) {
|
||||||
const wrappedHandler = p.flux[event] = function () {
|
const wrappedHandler = p.flux[event] = function () {
|
||||||
try {
|
try {
|
||||||
const res = handler.apply(p, arguments as any);
|
const res = handler!.apply(p, arguments as any);
|
||||||
return res instanceof Promise
|
return res instanceof Promise
|
||||||
? res.catch(e => logger.error(`${p.name}: Error while handling ${event}\n`, e))
|
? res.catch(e => logger.error(`${p.name}: Error while handling ${event}\n`, e))
|
||||||
: res;
|
: res;
|
||||||
|
|
@ -242,7 +242,7 @@ export function unsubscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Fl
|
||||||
|
|
||||||
logger.debug("Unsubscribing from flux events of plugin", p.name);
|
logger.debug("Unsubscribing from flux events of plugin", p.name);
|
||||||
for (const [event, handler] of Object.entries(p.flux)) {
|
for (const [event, handler] of Object.entries(p.flux)) {
|
||||||
fluxDispatcher.unsubscribe(event as FluxEvents, handler);
|
fluxDispatcher.unsubscribe(event as FluxEvents, handler!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,11 @@ import { addProfileBadge, BadgePosition, BadgeUserArgs, ProfileBadge, removeProf
|
||||||
import { addMemberListDecorator, removeMemberListDecorator } from "@api/MemberListDecorators";
|
import { addMemberListDecorator, removeMemberListDecorator } from "@api/MemberListDecorators";
|
||||||
import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecorations";
|
import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecorations";
|
||||||
import { Settings } from "@api/Settings";
|
import { Settings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { User } from "@vencord/discord-types";
|
import { User } from "@vencord/discord-types";
|
||||||
import { filters, findStoreLazy, mapMangledModuleLazy } from "@webpack";
|
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 {
|
export interface Session {
|
||||||
sessionId: string;
|
sessionId: string;
|
||||||
|
|
@ -85,7 +84,7 @@ const PlatformIcon = ({ platform, status, small }: { platform: Platform, status:
|
||||||
};
|
};
|
||||||
|
|
||||||
function ensureOwnStatus(user: User) {
|
function ensureOwnStatus(user: User) {
|
||||||
if (user.id === UserStore.getCurrentUser().id) {
|
if (user.id === AuthenticationStore.getId()) {
|
||||||
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 }, { status: b }) => {
|
const sortedSessions = Object.values(sessions).sort(({ status: a }, { status: b }) => {
|
||||||
|
|
@ -104,7 +103,7 @@ function ensureOwnStatus(user: User) {
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const { clientStatuses } = PresenceStore.getState();
|
const { clientStatuses } = PresenceStore.getState();
|
||||||
clientStatuses[UserStore.getCurrentUser().id] = ownStatus;
|
clientStatuses[AuthenticationStore.getId()] = ownStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +114,7 @@ function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] {
|
||||||
|
|
||||||
ensureOwnStatus(user);
|
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 [];
|
if (!status) return [];
|
||||||
|
|
||||||
return Object.entries(status).map(([platform, status]) => ({
|
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; }) => {
|
const PlatformIndicator = ({ user, small = false }: { user: User; small?: boolean; }) => {
|
||||||
if (!user || user.bot) return null;
|
|
||||||
|
|
||||||
ensureOwnStatus(user);
|
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;
|
if (!status) return null;
|
||||||
|
|
||||||
const icons = Object.entries(status).map(([platform, status]) => (
|
const icons = Object.entries(status).map(([platform, status]) => (
|
||||||
|
|
@ -170,10 +167,8 @@ const badge: ProfileBadge = {
|
||||||
const indicatorLocations = {
|
const indicatorLocations = {
|
||||||
list: {
|
list: {
|
||||||
description: "In the member list",
|
description: "In the member list",
|
||||||
onEnable: () => addMemberListDecorator("platform-indicator", props =>
|
onEnable: () => addMemberListDecorator("platform-indicator", ({ user }) =>
|
||||||
<ErrorBoundary noop>
|
user && !user.bot ? <PlatformIndicator user={user} small={true} /> : null
|
||||||
<PlatformIndicator user={props.user} small={true} />
|
|
||||||
</ErrorBoundary>
|
|
||||||
),
|
),
|
||||||
onDisable: () => removeMemberListDecorator("platform-indicator")
|
onDisable: () => removeMemberListDecorator("platform-indicator")
|
||||||
},
|
},
|
||||||
|
|
@ -184,11 +179,10 @@ const indicatorLocations = {
|
||||||
},
|
},
|
||||||
messages: {
|
messages: {
|
||||||
description: "Inside messages",
|
description: "Inside messages",
|
||||||
onEnable: () => addMessageDecoration("platform-indicator", props =>
|
onEnable: () => addMessageDecoration("platform-indicator", props => {
|
||||||
<ErrorBoundary noop>
|
const user = props.message?.author;
|
||||||
<PlatformIndicator user={props.message?.author} />
|
return user && !user.bot ? <PlatformIndicator user={props.message?.author} /> : null;
|
||||||
</ErrorBoundary>
|
}),
|
||||||
),
|
|
||||||
onDisable: () => removeMessageDecoration("platform-indicator")
|
onDisable: () => removeMessageDecoration("platform-indicator")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -201,19 +195,6 @@ export default definePlugin({
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
const settings = Settings.plugins.PlatformIndicators;
|
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]) => {
|
Object.entries(indicatorLocations).forEach(([key, value]) => {
|
||||||
if (settings[key]) value.onEnable();
|
if (settings[key]) value.onEnable();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -151,9 +151,9 @@ export interface PluginDef {
|
||||||
/**
|
/**
|
||||||
* Allows you to subscribe to Flux events
|
* Allows you to subscribe to Flux events
|
||||||
*/
|
*/
|
||||||
flux?: {
|
flux?: Partial<{
|
||||||
[E in LiteralUnion<FluxEvents, string>]?: (event: any) => void | Promise<void>;
|
[E in LiteralUnion<FluxEvents, string>]: (event: any) => void | Promise<void>;
|
||||||
};
|
}>;
|
||||||
/**
|
/**
|
||||||
* Allows you to manipulate context menus
|
* Allows you to manipulate context menus
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue