CustomRPC: add toggle & Toolbox action for disabling presence (#4636)

Co-authored-by: Vendicated <vendicated@riseup.net>
This commit is contained in:
Connor 2026-09-30 16:02:18 +02:00 • committed by GitHub
parent 7f0c10cc29
commit 40ae4d2a39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 35 deletions

View file

@ -18,20 +18,21 @@
import { definePluginSettings } from "@api/Settings"; import { definePluginSettings } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings"; import { getUserSettingLazy } from "@api/UserSettings";
import { BaseText } from "@components/BaseText";
import { Button } from "@components/Button";
import { Card } from "@components/Card";
import { Divider } from "@components/Divider"; import { Divider } from "@components/Divider";
import { ErrorCard } from "@components/ErrorCard";
import { Flex } from "@components/Flex"; import { Flex } from "@components/Flex";
import { Link } from "@components/Link"; import { Link } from "@components/Link";
import { Paragraph } from "@components/Paragraph";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { isTruthy } from "@utils/guards"; import { isTruthy } from "@utils/guards";
import { Margins } from "@utils/margins";
import { classes } from "@utils/misc";
import { useAwaiter } from "@utils/react"; import { useAwaiter } from "@utils/react";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { Activity } from "@vencord/discord-types"; import { Activity } from "@vencord/discord-types";
import { ActivityType } from "@vencord/discord-types/enums"; import { ActivityType } from "@vencord/discord-types/enums";
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack"; import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, React, UserStore } from "@webpack/common"; import { ApplicationAssetUtils, FluxDispatcher, Menu, React, UserStore } from "@webpack/common";
import { RPCSettings } from "./RpcSettings"; import { RPCSettings } from "./RpcSettings";
@ -52,6 +53,12 @@ export const enum TimestampMode {
} }
export const settings = definePluginSettings({ export const settings = definePluginSettings({
enablePresence: {
type: OptionType.BOOLEAN,
description: "Whether to show the presence",
default: true,
onChange: v => setRpc(!v)
},
config: { config: {
type: OptionType.COMPONENT, type: OptionType.COMPONENT,
component: RPCSettings component: RPCSettings
@ -201,11 +208,12 @@ async function createActivity(): Promise<Activity | undefined> {
} }
export async function setRpc(disable?: boolean) { export async function setRpc(disable?: boolean) {
const shouldDisable = disable ?? !settings.store.enablePresence;
const activity: Activity | undefined = await createActivity(); const activity: Activity | undefined = await createActivity();
FluxDispatcher.dispatch({ FluxDispatcher.dispatch({
type: "LOCAL_ACTIVITY_UPDATE", type: "LOCAL_ACTIVITY_UPDATE",
activity: !disable ? activity : null, activity: !shouldDisable ? activity : null,
socketId: "CustomRPC", socketId: "CustomRPC",
}); });
} }
@ -214,12 +222,28 @@ export default definePlugin({
name: "CustomRPC", name: "CustomRPC",
description: "Add a fully customisable Rich Presence (Game status) to your Discord profile", description: "Add a fully customisable Rich Presence (Game status) to your Discord profile",
tags: ["Activity", "Customisation"], tags: ["Activity", "Customisation"],
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev], authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev, Devs.c0nnorgg],
dependencies: ["UserSettingsAPI"], dependencies: ["UserSettingsAPI"],
// This plugin's patch is not important for functionality, so don't require a restart // This plugin's patch is not important for functionality, so don't require a restart
requiresRestart: false, requiresRestart: false,
settings, settings,
toolboxActions() {
const { enablePresence } = settings.use(["enablePresence"]);
return (
<Menu.MenuCheckboxItem
id="custom-rpc-toggle-toolbox"
label="Show Custom RPC"
checked={enablePresence}
action={() => {
settings.store.enablePresence = !enablePresence;
setRpc();
}}
/>
);
},
start: setRpc, start: setRpc,
stop: () => setRpc(true), stop: () => setRpc(true),
@ -235,59 +259,66 @@ export default definePlugin({
], ],
settingsAboutComponent: () => { settingsAboutComponent: () => {
const { enablePresence } = settings.use(["enablePresence"]);
const [activity] = useAwaiter(createActivity, { fallbackValue: undefined, deps: Object.values(settings.store) }); const [activity] = useAwaiter(createActivity, { fallbackValue: undefined, deps: Object.values(settings.store) });
const gameActivityEnabled = ShowCurrentGame.useSetting(); const gameActivityEnabled = ShowCurrentGame.useSetting();
const { profileThemeStyle } = useProfileThemeStyle({}); const { profileThemeStyle } = useProfileThemeStyle({});
return ( return (
<> <Flex flexDirection="column" gap=".5em">
{!enablePresence && (
<Card variant="warning">
<Flex flexDirection="column" gap=".5em" alignItems="flex-start">
<BaseText size="md" weight="bold">Custom RPC disabled</BaseText>
<Paragraph>The "Enable Presence" setting is disabled, so your presence won't show. If this was unintentional, enable it below.</Paragraph>
</Flex>
</Card>
)}
{!gameActivityEnabled && ( {!gameActivityEnabled && (
<ErrorCard <Card variant="danger">
className={classes(Margins.top16, Margins.bottom16)} <Flex flexDirection="column" gap=".5em" alignItems="flex-start">
style={{ padding: "1em" }} <BaseText size="md" weight="bold">Activity Sharing disabled</BaseText>
> <Paragraph>Activity Sharing isn't enabled, so people won't be able to see your custom rich presence!</Paragraph>
<Forms.FormTitle>Notice</Forms.FormTitle>
<Forms.FormText>Activity Sharing isn't enabled, people won't be able to see your custom rich presence!</Forms.FormText>
<Button <Button
color={Button.Colors.TRANSPARENT} variant="overlayPrimary"
className={Margins.top8} onClick={() => ShowCurrentGame.updateSetting(true)}
onClick={() => ShowCurrentGame.updateSetting(true)} >
> Enable Activity Sharing
Enable </Button>
</Button> </Flex>
</ErrorCard> </Card>
)} )}
<Flex flexDirection="column" gap=".5em" className={Margins.top16}> <Flex flexDirection="column" gap=".5em">
<Forms.FormText> <Paragraph>
Go to the <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and Go to the <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and
get the application ID. get the application ID.
</Forms.FormText> </Paragraph>
<Forms.FormText> <Paragraph>
Upload images in the Rich Presence tab to get the image keys. Upload images in the Rich Presence tab to get the image keys.
</Forms.FormText> </Paragraph>
<Forms.FormText> <Paragraph>
If you want to use an image link, download your image and reupload the image to <Link href="https://imgur.com">Imgur</Link> and get the image link by right-clicking the image and selecting "Copy image address". If you want to use an image link, download your image and reupload the image to <Link href="https://imgur.com">Imgur</Link> and get the image link by right-clicking the image and selecting "Copy image address".
</Forms.FormText> </Paragraph>
<Forms.FormText> <Paragraph>
You can't see your own buttons on your profile, but everyone else can see it fine. You can't see your own buttons on your profile, but everyone else can see it fine.
</Forms.FormText> </Paragraph>
<Forms.FormText> <Paragraph>
Some weird unicode text ("fonts" 𝖑𝖎𝖐𝖊 𝖙𝖍𝖎𝖘) may cause the rich presence to not show up, try using normal letters instead. Some weird unicode text ("fonts" 𝖑𝖎𝖐𝖊 𝖙𝖍𝖎𝖘) may cause the rich presence to not show up, try using normal letters instead.
</Forms.FormText> </Paragraph>
</Flex> </Flex>
<Divider className={Margins.top8} /> <Divider />
<div style={{ width: "284px", ...profileThemeStyle, marginTop: 8, borderRadius: 8, background: "var(--background-mod-muted)" }}> <div style={{ width: "284px", ...profileThemeStyle, borderRadius: 8, background: "var(--background-mod-muted)" }}>
{activity && <ActivityView {activity && <ActivityView
activity={activity} activity={activity}
user={UserStore.getCurrentUser()} user={UserStore.getCurrentUser()}
currentUser={UserStore.getCurrentUser()} currentUser={UserStore.getCurrentUser()}
/>} />}
</div> </div>
</> </Flex>
); );
} }
}); });

View file

@ -677,6 +677,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
Kaede: { Kaede: {
name: "Kaede", name: "Kaede",
id: 1492642701320126504n id: 1492642701320126504n
},
c0nnorgg: {
name: "c0nnorgg",
id: 1088882977985003620n,
} }
} satisfies Record<string, Dev>); } satisfies Record<string, Dev>);