Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Plugin): showBadgeInChat #2347

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f11a1fe
Add files via upload
KrstlSkll69 Apr 10, 2024
2016c8f
Update constants.ts (add me)
KrstlSkll69 Apr 10, 2024
58028c0
Update README.md (added discalmer too end)
KrstlSkll69 Apr 11, 2024
04fc3fc
Add files via upload
KrstlSkll69 Apr 11, 2024
d3ff848
Delete src/plugins/showBadgesInChat/README.md
KrstlSkll69 Apr 11, 2024
d73f515
Delete src/plugins/showBadgesInChat/index.tsx
KrstlSkll69 Apr 11, 2024
02c2f9c
Delete src/plugins/showBadgesInChat/settings.tsx
KrstlSkll69 Apr 11, 2024
8c23a7c
Delete src/plugins/showBadgesInChat/styles.css
KrstlSkll69 Apr 11, 2024
dc438b9
Update and rename src/plugins/showBadgesInChat/showBadgesInChat/READM…
KrstlSkll69 Apr 11, 2024
1242a55
Update and rename src/plugins/showBadgesInChat/showBadgesInChat/index…
KrstlSkll69 Apr 11, 2024
a0752c6
Update and rename src/plugins/showBadgesInChat/showBadgesInChat/setti…
KrstlSkll69 Apr 11, 2024
2e8370a
Update and rename src/plugins/showBadgesInChat/showBadgesInChat/style…
KrstlSkll69 Apr 11, 2024
4c8f4d4
Update README.md (add disclaimer)
KrstlSkll69 Apr 11, 2024
57e5801
fix
KrstlSkll69 Apr 11, 2024
10e031f
Update README.md update
KrstlSkll69 Apr 11, 2024
ebb757f
Update index.tsx (fix Margin)
KrstlSkll69 Apr 12, 2024
7e3d318
Update src/plugins/showBadgesInChat/README.md
KrstlSkll69 May 28, 2024
d2edabc
Update src/plugins/showBadgesInChat/README.md
KrstlSkll69 May 28, 2024
763e80d
Update src/plugins/showBadgesInChat/index.tsx
KrstlSkll69 May 28, 2024
68fb6be
Add files via upload
KrstlSkll69 May 28, 2024
50ac7ba
Merge branch 'main' into main
KrstlSkll69 May 28, 2024
93d8f7a
Apply suggestions from code review
KrstlSkll69 May 28, 2024
352d3b0
Add files via upload
KrstlSkll69 May 28, 2024
384cd0f
Add files via upload
KrstlSkll69 May 28, 2024
90409b7
Merge branch 'Vendicated:main' into main
KrstlSkll69 Jan 11, 2025
4865c6e
key
KrstlSkll69 Jan 11, 2025
dfe4fa1
intl, and style fix
KrstlSkll69 Jan 11, 2025
134f476
Merge branch 'Vendicated:main' into main
KrstlSkll69 Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/plugins/showBadgesInChat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# ShowBadgesInChat

Shows profile badges in chat. The badges include all built-in Discord badges. It also proudly displays your Vencord donor/contributor badges.

---

The settings editor lets you:

- Drag to reorder
- Click to enable/disable a specific badge type
- Hover over a badge for the tool-tip about what badges it represents

https://github.com/Vendicated/Vencord/assets/119569726/c7543516-f691-42c5-baa2-68dbda96d46a

![](https://github.com/Vendicated/Vencord/assets/119569726/ca736d0d-c09a-4737-9cfa-4fc88cfc91ae)

---

All badges can fit easily, for example here's Vencord's creator: Vee (vending.machine):
![](https://github.com/Vendicated/Vencord/assets/119569726/fc768079-5027-482b-ac52-a652812d482d)

---

_Discord currently has a small bug where an author who isn't the current user will return their premiumType as undefined. There is nothing we can do about this until Discord fixes this bug_
117 changes: 117 additions & 0 deletions src/plugins/showBadgesInChat/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import { addDecoration, removeDecoration } from "@api/MessageDecorations";
import { Devs } from "@utils/constants";
import { isPluginDev } from "@utils/misc";
import definePlugin from "@utils/types";
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
import badges from "plugins/_api/badges";
const roleIconClassName = findByPropsLazy("roleIcon", "separator").roleIcon;
const RoleIconComponent = findComponentByCodeLazy(".Messages.ROLE_ICON_ALT_TEXT");

import settings from "./settings";

const discordBadges: readonly [number, string, string][] = Object.freeze([
[0, "Discord Staff", "5e74e9b61934fc1f67c65515d1f7e60d"],
[1, "Partnered Server Owner", "3f9748e53446a137a052f3454e2de41e"],
[2, "HypeSquad Events", "bf01d1073931f921909045f3a39fd264"],
[6, "HypeSquad Bravery", "8a88d63823d8a71cd5e390baa45efa02"],
[7, "HypeSquad Brilliance", "011940fd013da3f7fb926e4a1cd2e618"],
[8, "HypeSquad Balance", "3aa41de486fa12454c3761e8e223442e"],
[3, "Discord Bug Hunter", "2717692c7dca7289b35297368a940dd0"],
[14, "Discord Bug Hunter", "848f79194d4be5ff5f81505cbd0ce1e6"],
[22, "Active Developer", "6bdc42827a38498929a4920da12695d9"],
[17, "Early Verified Bot Developer", "6df5892e0f35b051f8b61eace34f4967"],
[9, "Early Supporter", "7060786766c9c840eb3019e725d2b358"],
[18, "Moderator Programs Alumni", "fee1624003e2fee35cb398e125dc479b"]
]);

function CheckBadge({ badge, author }: { badge: string; author: any; }): JSX.Element | null {
KrstlSkll69 marked this conversation as resolved.
Show resolved Hide resolved
switch (badge) {
case "VencordDonor":
return (
<span style={{ order: settings.store.VencordDonorPosition }}>
{badges.getDonorBadges(author.id)?.map((badge: any) => (
KrstlSkll69 marked this conversation as resolved.
Show resolved Hide resolved
<RoleIconComponent
className={roleIconClassName}
name={badge.description}
size={20}
src={badge.image}
/>
))}
</span>
);
case "VencordContributer":
return isPluginDev(author.id) ? (
<span style={{ order: settings.store.VencordContributorPosition }}>
<RoleIconComponent
className={roleIconClassName}
name="Vencord Contributor"
size={20}
src={"https://vencord.dev/assets/favicon.png"}
/>
</span>
) : null;
case "DiscordProfile":
const chatBadges = discordBadges
.filter((badge: any) => (author.flags || author.publicFlags) & (1 << badge[0]))
KrstlSkll69 marked this conversation as resolved.
Show resolved Hide resolved
.map((badge: any) => (
KrstlSkll69 marked this conversation as resolved.
Show resolved Hide resolved
<RoleIconComponent
className={roleIconClassName}
name={badge[1]}
size={20}
src={`https://cdn.discordapp.com/badge-icons/${badge[2]}.png`}
/>
));
return chatBadges.length > 0 ? (
<span style={{ order: settings.store.DiscordProfilePosition }}>
{chatBadges}
</span>
) : null;
case "DiscordNitro":
return (author?.premiumType ?? 0) > 0 ? (
<span style={{ order: settings.store.DiscordNitroPosition }}>
<RoleIconComponent
className={roleIconClassName}
name={
"Discord Nitro" +
(author.premiumType === 3 ? " Basic" : author.premiumType === 1 ? " Classic" : "")
}
size={20}
src={"https://cdn.discordapp.com/badge-icons/2ba85e8026a8614b640c2837bcdfe21b.png"}
/>
</span>
) : null;
default:
return null;
}
}

function ChatBadges({ author }: any) {
KrstlSkll69 marked this conversation as resolved.
Show resolved Hide resolved
return (
<span className="vc-sbic-badge-row">
{settings.store.showVencordDonor && <CheckBadge badge={"VencordDonor"} author={author} />}
{settings.store.showVencordContributor && <CheckBadge badge={"VencordContributer"} author={author} />}
{settings.store.showDiscordProfile && <CheckBadge badge={"DiscordProfile"} author={author} />}
{settings.store.showDiscordNitro && <CheckBadge badge={"DiscordNitro"} author={author} />}
</span>
);
}

export default definePlugin({
name: "ShowBadgesInChat",
authors: [Devs.Inbestigator, Devs.KrystalSkull],
description: "Shows the message author's badges beside their name in chat.",
dependencies: ["MessageDecorationsAPI"],
settings,
start: () => {
addDecoration("vc-show-badges-in-chat", props => <ChatBadges author={props.message?.author} />);
KrstlSkll69 marked this conversation as resolved.
Show resolved Hide resolved
},
stop: () => {
removeDecoration("vc-show-badges-in-chat");
}
});
163 changes: 163 additions & 0 deletions src/plugins/showBadgesInChat/settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import { definePluginSettings } from "@api/Settings";
import { OptionType } from "@utils/types";
import { Text, useEffect, UserStore, useState } from "@webpack/common";

const settings = definePluginSettings({
showVencordDonor: {
type: OptionType.BOOLEAN,
description: "Enable to show Vencord donor badges in chat.",
hidden: true,
default: true
},
VencordDonorPosition: {
type: OptionType.NUMBER,
description: "The position of the Vencord Donor badges.",
hidden: true,
default: 0
},
showVencordContributor: {
type: OptionType.BOOLEAN,
description: "Enable to show Vencord contributor badges in chat.",
hidden: true,
default: true
},
VencordContributorPosition: {
type: OptionType.NUMBER,
description: "The position of the Vencord Contributor badge.",
hidden: true,
default: 1
},
showDiscordProfile: {
type: OptionType.BOOLEAN,
description: "Enable to show Discord profile badges in chat.",
hidden: true,
default: true
},
DiscordProfilePosition: {
type: OptionType.NUMBER,
description: "The position of the Discord profile badges.",
hidden: true,
default: 2
},
showDiscordNitro: {
type: OptionType.BOOLEAN,
description: "Enable to show Discord Nitro badges in chat.",
hidden: true,
default: true
},
DiscordNitroPosition: {
type: OptionType.NUMBER,
description: "The position of the Discord Nitro badge.",
hidden: true,
default: 3
},
badgeSettings: {
type: OptionType.COMPONENT,
description: "Setup badge layout and visibility",
component: () => <BadgeSettings />
}
});

export default settings;

const BadgeSettings = () => {
const [images, setImages] = useState([
{ src: "https://cdn.discordapp.com/emojis/1026533070955872337.png", shown: settings.store.showVencordDonor, title: "Vencord donor badges", key: "VencordDonor", position: settings.store.VencordDonorPosition },
{ src: "https://vencord.dev/assets/favicon.png", shown: settings.store.showVencordContributor, title: "Vencord contributor badge", key: "VencordContributer", position: settings.store.VencordContributorPosition },
{ src: "https://cdn.discordapp.com/badge-icons/bf01d1073931f921909045f3a39fd264.png", shown: settings.store.showDiscordProfile, title: "Discord profile badges (HypeSquad, Discord Staff, Active Developer, etc.)", key: "DiscordProfile", position: settings.store.DiscordProfilePosition },
{ src: "https://cdn.discordapp.com/badge-icons/2ba85e8026a8614b640c2837bcdfe21b.png", shown: settings.store.showDiscordNitro, title: "Nitro badge", key: "DiscordNitro", position: settings.store.DiscordNitroPosition }
]);

useEffect(() => {
images.forEach(image => {
switch (image.key) {
case "VencordDonor":
settings.store.VencordDonorPosition = image.position;
settings.store.showVencordDonor = image.shown;
break;
case "VencordContributer":
settings.store.VencordContributorPosition = image.position;
settings.store.showVencordContributor = image.shown;
break;
case "DiscordProfile":
settings.store.DiscordProfilePosition = image.position;
settings.store.showDiscordProfile = image.shown;
break;
case "DiscordNitro":
settings.store.DiscordNitroPosition = image.position;
settings.store.showDiscordNitro = image.shown;
break;
default:
break;
}
});
}, [images]);

const handleDragStart = (e: any, index: number) => {
if (!images[index].shown) {
e.preventDefault();
} else {
e.dataTransfer.setData("index", index);
}
};

const handleDragOver = e => {
e.preventDefault();
};

const handleDrop = (e: any, dropIndex: number) => {
const dragIndex = e.dataTransfer.getData("index");
const newImages = [...images];
const draggedImage = newImages[dragIndex];

newImages.splice(dragIndex, 1);
newImages.splice(dropIndex, 0, draggedImage);

newImages.forEach((image, index) => {
image.position = index;
});

setImages(newImages);
};

const toggleDisable = (index: number) => {
const newImages = [...images];
newImages[index].shown = !newImages[index].shown;
setImages(newImages);
};

return (
<>
<Text>Drag the badges to reorder them, you can click to enable/disable a specific badge type.</Text>
<div className="vc-sbic-badge-settings">
<img className="vc-sbic-settings-avatar" src={UserStore.getCurrentUser().getAvatarURL()}></img>
<Text className="vc-sbic-settings-username">{(UserStore.getCurrentUser() as any).globalName}</Text>
{images
.sort((a, b) => a.position - b.position)
.map((image, index) => (
<div
key={image.key}
className={`vc-sbic-image-container ${!image.shown ? "vc-sbic-disabled" : ""}`}
onDragOver={e => handleDragOver(e)}
onDrop={e => handleDrop(e, index)}
onClick={() => toggleDisable(index)}
>
<img
src={image.src}
draggable={image.shown}
onDragStart={e => handleDragStart(e, index)}
title={image.title}
/>
</div>
))
}
</div>
</>
);
};
40 changes: 40 additions & 0 deletions src/plugins/showBadgesInChat/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.vc-sbic-badge-settings {
display: flex;
gap: 5px;
flex-direction: row;
}

.vc-sbic-image-container {
position: relative;
transition: 0.15s;
}

.vc-sbic-image-container img {
width: 25px;
height: 25px;
cursor: pointer;
}

.vc-sbic-disabled {
opacity: 0.5;
scale: 0.95;
}

.vc-sbic-settings-avatar {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 12px;
}

.vc-sbic-settings-username {
font-size: 22px;
color: white;
margin-right: 5px;
}

.vc-sbic-badge-row {
display: inline-flex;
margin-left: 2;
vertical-align: top;
}
4 changes: 4 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "verticalsync",
id: 328165170536775680n
},
KrystalSkull: {
name: "KrystalSkullOfficial",
id: 929208515883569182n
},
} satisfies Record<string, Dev>);

// iife so #__PURE__ works correctly
Expand Down