feat(PlatformIndicators): add indicator to messages (#343)
This commit is contained in:
parent
1f73cfa91a
commit
d806be1346
8 changed files with 321 additions and 75 deletions
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
import { HTMLProps } from "react";
|
import { ComponentType, HTMLProps } from "react";
|
||||||
|
|
||||||
import Plugins from "~plugins";
|
import Plugins from "~plugins";
|
||||||
|
|
||||||
|
@ -27,20 +27,21 @@ export enum BadgePosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProfileBadge {
|
export interface ProfileBadge {
|
||||||
/** The tooltip to show on hover */
|
/** The tooltip to show on hover. Required for image badges */
|
||||||
tooltip: string;
|
tooltip?: string;
|
||||||
|
/** Custom component for the badge (tooltip not included) */
|
||||||
|
component?: ComponentType<ProfileBadge & BadgeUserArgs>;
|
||||||
/** The custom image to use */
|
/** The custom image to use */
|
||||||
image?: string;
|
image?: string;
|
||||||
/** Action to perform when you click the badge */
|
/** Action to perform when you click the badge */
|
||||||
onClick?(): void;
|
onClick?(): void;
|
||||||
/** Should the user display this badge? */
|
/** Should the user display this badge? */
|
||||||
shouldShow?(userInfo: BadgeUserArgs): boolean;
|
shouldShow?(userInfo: BadgeUserArgs): boolean;
|
||||||
/** Optional props (e.g. style) for the badge */
|
/** Optional props (e.g. style) for the badge, ignored for component badges */
|
||||||
props?: HTMLProps<HTMLImageElement>;
|
props?: HTMLProps<HTMLImageElement>;
|
||||||
/** Insert at start or end? */
|
/** Insert at start or end? */
|
||||||
position?: BadgePosition;
|
position?: BadgePosition;
|
||||||
|
/** The badge name to display, Discord uses this. Required for component badges */
|
||||||
/** The badge name to display. Discord uses this, but we don't. */
|
|
||||||
key?: string;
|
key?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +71,8 @@ export function inject(badgeArray: ProfileBadge[], args: BadgeUserArgs) {
|
||||||
for (const badge of Badges) {
|
for (const badge of Badges) {
|
||||||
if (!badge.shouldShow || badge.shouldShow(args)) {
|
if (!badge.shouldShow || badge.shouldShow(args)) {
|
||||||
badge.position === BadgePosition.START
|
badge.position === BadgePosition.START
|
||||||
? badgeArray.unshift(badge)
|
? badgeArray.unshift({ ...badge, ...args })
|
||||||
: badgeArray.push(badge);
|
: badgeArray.push({ ...badge, ...args });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Plugins.BadgeAPI as any).addDonorBadge(badgeArray, args.user.id);
|
(Plugins.BadgeAPI as any).addDonorBadge(badgeArray, args.user.id);
|
||||||
|
|
65
src/api/MemberListDecorators.ts
Normal file
65
src/api/MemberListDecorators.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Channel, User } from "discord-types/general/index.js";
|
||||||
|
|
||||||
|
interface DecoratorProps {
|
||||||
|
activities: any[];
|
||||||
|
canUseAvatarDecorations: boolean;
|
||||||
|
channel: Channel;
|
||||||
|
/**
|
||||||
|
* Only for DM members
|
||||||
|
*/
|
||||||
|
channelName?: string;
|
||||||
|
/**
|
||||||
|
* Only for server members
|
||||||
|
*/
|
||||||
|
currentUser?: User;
|
||||||
|
guildId?: string;
|
||||||
|
isMobile: boolean;
|
||||||
|
isOwner?: boolean;
|
||||||
|
isTyping: boolean;
|
||||||
|
selected: boolean;
|
||||||
|
status: string;
|
||||||
|
user: User;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
export type Decorator = (props: DecoratorProps) => JSX.Element | null;
|
||||||
|
type OnlyIn = "guilds" | "dms";
|
||||||
|
|
||||||
|
export const decorators = new Map<string, { decorator: Decorator, onlyIn?: OnlyIn; }>();
|
||||||
|
|
||||||
|
export function addDecorator(identifier: string, decorator: Decorator, onlyIn?: OnlyIn) {
|
||||||
|
decorators.set(identifier, { decorator, onlyIn });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeDecorator(identifier: string) {
|
||||||
|
decorators.delete(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __addDecoratorsToList(props: DecoratorProps): (JSX.Element | null)[] {
|
||||||
|
const isInGuild = !!(props.guildId);
|
||||||
|
return [...decorators.values()].map(decoratorObj => {
|
||||||
|
const { decorator, onlyIn } = decoratorObj;
|
||||||
|
// this can most likely be done cleaner
|
||||||
|
if (!onlyIn || (onlyIn === "guilds" && isInGuild) || (onlyIn === "dms" && !isInGuild)) {
|
||||||
|
return decorator(props);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
63
src/api/MessageDecorations.ts
Normal file
63
src/api/MessageDecorations.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Channel, Message } from "discord-types/general/index.js";
|
||||||
|
|
||||||
|
interface DecorationProps {
|
||||||
|
author: {
|
||||||
|
/**
|
||||||
|
* Will be username if the user has no nickname
|
||||||
|
*/
|
||||||
|
nick: string;
|
||||||
|
iconRoleId: string;
|
||||||
|
guildMemberAvatar: string;
|
||||||
|
colorRoleName: string;
|
||||||
|
colorString: string;
|
||||||
|
};
|
||||||
|
channel: Channel;
|
||||||
|
compact: boolean;
|
||||||
|
decorations: {
|
||||||
|
/**
|
||||||
|
* Element for the [BOT] tag if there is one
|
||||||
|
*/
|
||||||
|
0: JSX.Element | null;
|
||||||
|
/**
|
||||||
|
* Other decorations (including ones added with this api)
|
||||||
|
*/
|
||||||
|
1: JSX.Element[];
|
||||||
|
};
|
||||||
|
message: Message;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
export type Decoration = (props: DecorationProps) => JSX.Element | null;
|
||||||
|
|
||||||
|
export const decorations = new Map<string, Decoration>();
|
||||||
|
|
||||||
|
export function addDecoration(identifier: string, decoration: Decoration) {
|
||||||
|
decorations.set(identifier, decoration);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeDecoration(identifier: string) {
|
||||||
|
decorations.delete(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __addDecorationsToMessage(props: DecorationProps): (JSX.Element | null)[] {
|
||||||
|
return [...decorations.values()].map(decoration => {
|
||||||
|
return decoration(props);
|
||||||
|
});
|
||||||
|
}
|
|
@ -19,7 +19,9 @@
|
||||||
import * as $Badges from "./Badges";
|
import * as $Badges from "./Badges";
|
||||||
import * as $Commands from "./Commands";
|
import * as $Commands from "./Commands";
|
||||||
import * as $DataStore from "./DataStore";
|
import * as $DataStore from "./DataStore";
|
||||||
|
import * as $MemberListDecorators from "./MemberListDecorators";
|
||||||
import * as $MessageAccessories from "./MessageAccessories";
|
import * as $MessageAccessories from "./MessageAccessories";
|
||||||
|
import * as $MessageDecorations from "./MessageDecorations";
|
||||||
import * as $MessageEventsAPI from "./MessageEvents";
|
import * as $MessageEventsAPI from "./MessageEvents";
|
||||||
import * as $MessagePopover from "./MessagePopover";
|
import * as $MessagePopover from "./MessagePopover";
|
||||||
import * as $Notices from "./Notices";
|
import * as $Notices from "./Notices";
|
||||||
|
@ -72,5 +74,13 @@ const Badges = $Badges;
|
||||||
* An API allowing you to add custom elements to the server list
|
* An API allowing you to add custom elements to the server list
|
||||||
*/
|
*/
|
||||||
const ServerList = $ServerList;
|
const ServerList = $ServerList;
|
||||||
|
/**
|
||||||
|
* An API allowing you to add components as message accessories
|
||||||
|
*/
|
||||||
|
const MessageDecorations = $MessageDecorations;
|
||||||
|
/**
|
||||||
|
* An API allowing you to add components to member list users, in both DM's and servers
|
||||||
|
*/
|
||||||
|
const MemberListDecorators = $MemberListDecorators;
|
||||||
|
|
||||||
export { Badges, Commands, DataStore, MessageAccessories, MessageEvents, MessagePopover, Notices, ServerList };
|
export { Badges, Commands, DataStore, MemberListDecorators, MessageAccessories, MessageDecorations, MessageEvents, MessagePopover, Notices, ServerList };
|
||||||
|
|
|
@ -66,11 +66,20 @@ export default definePlugin({
|
||||||
/* Patch the badge list component on user profiles */
|
/* Patch the badge list component on user profiles */
|
||||||
{
|
{
|
||||||
find: "Messages.PROFILE_USER_BADGES,role:",
|
find: "Messages.PROFILE_USER_BADGES,role:",
|
||||||
replacement: {
|
replacement: [
|
||||||
match: /src:(\w{1,3})\[(\w{1,3})\.key\],/,
|
{
|
||||||
// <img src={badge.image ?? imageMap[badge.key]} {...badge.props} />
|
match: /src:(\w{1,3})\[(\w{1,3})\.key\],/,
|
||||||
replace: (_, imageMap, badge) => `src: ${badge}.image ?? ${imageMap}[${badge}.key], ...${badge}.props,`
|
// <img src={badge.image ?? imageMap[badge.key]} {...badge.props} />
|
||||||
}
|
replace: (_, imageMap, badge) => `src: ${badge}.image ?? ${imageMap}[${badge}.key], ...${badge}.props,`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /spacing:(\d{1,2}),children:(.{1,40}(.{1,2})\.jsx.+(.{1,2})\.onClick.+\)})},/,
|
||||||
|
// if the badge provides it's own component, render that instead of an image
|
||||||
|
// the badge also includes info about the user that has it (type BadgeUserArgs), which is why it's passed as props
|
||||||
|
replace: (_, s, origBadgeComponent, React, badge) =>
|
||||||
|
`spacing:${s},children:${badge}.component ? () => (0,${React}.jsx)(${badge}.component, { ...${badge} }) : ${origBadgeComponent}},`
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
42
src/plugins/apiMemberListDecorators.ts
Normal file
42
src/plugins/apiMemberListDecorators.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "MemberListDecoratorsAPI",
|
||||||
|
description: "API to add decorators to member list (both in servers and DMs)",
|
||||||
|
authors: [Devs.TheSun],
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: "lostPermissionTooltipText,",
|
||||||
|
replacement: {
|
||||||
|
match: /Fragment,{children:\[(.{30,80})\]/,
|
||||||
|
replace: "Fragment,{children:Vencord.Api.MemberListDecorators.__addDecoratorsToList(this.props).concat($1)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "PrivateChannel.renderAvatar",
|
||||||
|
replacement: {
|
||||||
|
match: /(subText:(.{1,2})\.renderSubtitle\(\).{1,50}decorators):(.{30,100}:null)/,
|
||||||
|
replace: "$1:Vencord.Api.MemberListDecorators.__addDecoratorsToList($2.props).concat($3)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
35
src/plugins/apiMessageDecorations.ts
Normal file
35
src/plugins/apiMessageDecorations.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "MessageDecorationsAPI",
|
||||||
|
description: "API to add decorations to messages",
|
||||||
|
authors: [Devs.TheSun],
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: ".withMentionPrefix",
|
||||||
|
replacement: {
|
||||||
|
match: /(\(\).roleDot.{10,50}{children:.{1,2})}\)/,
|
||||||
|
replace: "$1.concat(Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0]))})"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
|
@ -16,6 +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 { addDecorator, removeDecorator } from "@api/MemberListDecorators";
|
||||||
|
import { addDecoration, removeDecoration } from "@api/MessageDecorations";
|
||||||
import { Settings } from "@api/settings";
|
import { Settings } from "@api/settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
@ -59,10 +62,12 @@ const PlatformIcon = ({ platform, status }: { platform: Platform, status: string
|
||||||
return <Icon color={`var(--${getStatusColor(status)}`} tooltip={tooltip} />;
|
return <Icon color={`var(--${getStatusColor(status)}`} tooltip={tooltip} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getStatus = (id: string): Record<Platform, string> => PresenceStore.getState()?.clientStatuses?.[id];
|
||||||
|
|
||||||
const PlatformIndicator = ({ user }: { user: User; }) => {
|
const PlatformIndicator = ({ user }: { user: User; }) => {
|
||||||
if (!user || user.bot) return null;
|
if (!user || user.bot) return null;
|
||||||
|
|
||||||
const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>;
|
const status = getStatus(user.id);
|
||||||
if (!status) return null;
|
if (!status) return null;
|
||||||
|
|
||||||
const icons = Object.entries(status).map(([platform, status]) => (
|
const icons = Object.entries(status).map(([platform, status]) => (
|
||||||
|
@ -75,79 +80,95 @@ const PlatformIndicator = ({ user }: { user: User; }) => {
|
||||||
|
|
||||||
if (!icons.length) return null;
|
if (!icons.length) return null;
|
||||||
|
|
||||||
return (
|
const indicator =
|
||||||
<div
|
<span
|
||||||
className="vc-platform-indicator"
|
className="vc-platform-indicator"
|
||||||
style={{
|
style={{ marginLeft: "4px", gap: "4px" }}
|
||||||
display: "flex", alignItems: "center", marginLeft: "4px", gap: "4px"
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{icons}
|
{icons}
|
||||||
</div>
|
</span>;
|
||||||
);
|
|
||||||
|
return indicator;
|
||||||
|
};
|
||||||
|
|
||||||
|
const badge: ProfileBadge = {
|
||||||
|
component: PlatformIndicator,
|
||||||
|
position: BadgePosition.START,
|
||||||
|
shouldShow: userInfo => !!Object.keys(getStatus(userInfo.user.id) ?? {}).length,
|
||||||
|
key: "indicator"
|
||||||
|
};
|
||||||
|
|
||||||
|
const indicatorLocations = {
|
||||||
|
list: {
|
||||||
|
description: "In the member list",
|
||||||
|
onEnable: () => addDecorator("platform-indicator", props =>
|
||||||
|
<ErrorBoundary noop>
|
||||||
|
<PlatformIndicator user={props.user} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
),
|
||||||
|
onDisable: () => removeDecorator("platform-indicator")
|
||||||
|
},
|
||||||
|
badges: {
|
||||||
|
description: "In user profiles, as badges",
|
||||||
|
onEnable: () => addBadge(badge),
|
||||||
|
onDisable: () => removeBadge(badge)
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
description: "Inside messages",
|
||||||
|
onEnable: () => addDecoration("platform-indicator", props =>
|
||||||
|
<ErrorBoundary noop>
|
||||||
|
<PlatformIndicator user={
|
||||||
|
props.decorations[1]?.find(i => i.key === "new-member")?.props.message?.author
|
||||||
|
} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
),
|
||||||
|
onDisable: () => removeDecoration("platform-indicator")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "PlatformIndicators",
|
name: "PlatformIndicators",
|
||||||
description: "Adds platform indicators (Desktop, Mobile, Web...) to users",
|
description: "Adds platform indicators (Desktop, Mobile, Web...) to users",
|
||||||
authors: [Devs.kemo],
|
authors: [Devs.kemo, Devs.TheSun],
|
||||||
|
dependencies: ["MessageDecorationsAPI", "MemberListDecoratorsAPI"],
|
||||||
|
|
||||||
patches: [
|
start() {
|
||||||
{
|
const settings = Settings.plugins.PlatformIndicators;
|
||||||
// Server member list decorators
|
const { displayMode } = settings;
|
||||||
find: "this.renderPremium()",
|
|
||||||
predicate: () => ["both", "list"].includes(Settings.plugins.PlatformIndicators.displayMode),
|
// transfer settings from the old ones, which had a select menu instead of booleans
|
||||||
replacement: {
|
if (displayMode) {
|
||||||
match: /this.renderPremium\(\)[^\]]*?\]/,
|
if (displayMode !== "both") settings[displayMode] = true;
|
||||||
replace: "$&.concat(Vencord.Plugins.plugins.PlatformIndicators.renderPlatformIndicators(this.props))"
|
else {
|
||||||
}
|
settings.list = true;
|
||||||
},
|
settings.badges = true;
|
||||||
{
|
|
||||||
// Dm list decorators
|
|
||||||
find: "PrivateChannel.renderAvatar",
|
|
||||||
predicate: () => ["both", "list"].includes(Settings.plugins.PlatformIndicators.displayMode),
|
|
||||||
replacement: {
|
|
||||||
match: /(subText:(.{1,3})\..+?decorators:)(.+?:null)/,
|
|
||||||
replace: "$1[$3].concat(Vencord.Plugins.plugins.PlatformIndicators.renderPlatformIndicators($2.props))"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// User badges
|
|
||||||
find: "Messages.PROFILE_USER_BADGES",
|
|
||||||
predicate: () => ["both", "badges"].includes(Settings.plugins.PlatformIndicators.displayMode),
|
|
||||||
replacement: {
|
|
||||||
match: /(Messages\.PROFILE_USER_BADGES,role:"group",children:)(.+?\.key\)\}\)\))/,
|
|
||||||
replace: "$1[Vencord.Plugins.plugins.PlatformIndicators.renderPlatformIndicators(e)].concat($2)"
|
|
||||||
}
|
}
|
||||||
|
settings.messages = true;
|
||||||
|
delete settings.displayMode;
|
||||||
}
|
}
|
||||||
],
|
|
||||||
|
|
||||||
renderPlatformIndicators: ({ user }: { user: User; }) => (
|
Object.entries(indicatorLocations).forEach(([key, value]) => {
|
||||||
<ErrorBoundary noop>
|
if (settings[key]) value.onEnable();
|
||||||
<PlatformIndicator user={user} />
|
});
|
||||||
</ErrorBoundary>
|
},
|
||||||
),
|
|
||||||
|
stop() {
|
||||||
|
Object.entries(indicatorLocations).forEach(([_, value]) => {
|
||||||
|
value.onDisable();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
displayMode: {
|
...Object.fromEntries(
|
||||||
type: OptionType.SELECT,
|
Object.entries(indicatorLocations).map(([key, value]) => {
|
||||||
description: "Where to display the platform indicators",
|
return [key, {
|
||||||
restartNeeded: true,
|
type: OptionType.BOOLEAN,
|
||||||
options: [
|
description: `Show indicators ${value.description.toLowerCase()}`,
|
||||||
{
|
// onChange doesn't give any way to know which setting was changed, so restart required
|
||||||
label: "Member List & Badges",
|
restartNeeded: true,
|
||||||
value: "both",
|
default: false
|
||||||
default: true
|
}];
|
||||||
},
|
})
|
||||||
{
|
)
|
||||||
label: "Member List Only",
|
|
||||||
value: "list"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Badges Only",
|
|
||||||
value: "badges"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue