diff --git a/src/plugins/relationshipIndicators/README.md b/src/plugins/relationshipIndicators/README.md
new file mode 100644
index 0000000000..a7ebe9d4a2
--- /dev/null
+++ b/src/plugins/relationshipIndicators/README.md
@@ -0,0 +1,16 @@
+# Relationship Indicators
+
+## Description
+Adds a display to the badges, messages, and member list to indicate your relationship with the user.
+
+
+### Friend Indicator
+![friend indicator in chat](https://github.com/Vendicated/Vencord/assets/97131358/10a33c55-cbe5-4369-bb49-6f3aee59059c)
+![friend indicator in member list](https://github.com/Vendicated/Vencord/assets/97131358/614653e6-b51b-4082-998d-d123fbac595f)
+![friend indicator in profile (badge)](https://github.com/Vendicated/Vencord/assets/97131358/270c6667-e810-40a6-861a-40984f575aa6)
+
+### Blocked Indicator
+
+![blocked indicator in chat](https://github.com/Vendicated/Vencord/assets/97131358/bfdebf30-6b5c-480f-94fd-acc5cd736d9b)
+![blocked indicator in member list](https://github.com/Vendicated/Vencord/assets/97131358/5054729a-e30c-4104-945b-8652df6cf71c)
+![blocked indicator in profile (badge)](https://github.com/Vendicated/Vencord/assets/97131358/f0ee1279-ffa0-464d-b62a-3ff7d8d3a646)
diff --git a/src/plugins/relationshipIndicators/icons.tsx b/src/plugins/relationshipIndicators/icons.tsx
new file mode 100644
index 0000000000..6bc95ce51d
--- /dev/null
+++ b/src/plugins/relationshipIndicators/icons.tsx
@@ -0,0 +1,49 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+// uhh... can i put this in Icons.tsx?
+import { Tooltip } from "@webpack/common";
+
+type IconProps = {
+ tooltip?: string,
+ paths: { fill: string, path: string }[]
+ viewBox?: string
+}
+
+function Icon(iconProps: IconProps) {
+ return (
+
+ {props => (
+
+ )}
+
+
+ );
+}
+
+export function FriendIcon() {
+ return (
+
+ );
+}
+
+export function BlockedIcon() {
+ return (
+
+ );
+}
diff --git a/src/plugins/relationshipIndicators/index.tsx b/src/plugins/relationshipIndicators/index.tsx
new file mode 100644
index 0000000000..b15972aa3e
--- /dev/null
+++ b/src/plugins/relationshipIndicators/index.tsx
@@ -0,0 +1,85 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import {
+ addBadge,
+ BadgePosition,
+ ProfileBadge,
+ removeBadge
+} from "@api/Badges";
+import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
+import { addDecoration, removeDecoration } from "@api/MessageDecorations";
+import { definePluginSettings } from "@api/Settings";
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Devs } from "@utils/constants";
+import definePlugin, { OptionType } from "@utils/types";
+
+import { getBadges, RelationshipIndicator } from "./utils";
+
+const indicatorLocations = {
+ list: {
+ description: "In the member list",
+ onEnable: () => addDecorator("friend-indicator", props =>
+
+
+
+ ),
+ onDisable: () => removeDecorator("friend-indicator")
+ },
+ badges: {
+ description: "In user profiles, as badges",
+ onEnable: () => addBadge(badge),
+ onDisable: () => removeBadge(badge)
+ },
+ messages: {
+ description: "Inside messages",
+ onEnable: () => addDecoration("friend-indicator", props =>
+
+
+
+ ),
+ onDisable: () => removeDecoration("friend-indicator")
+ }
+};
+
+const badge: ProfileBadge = {
+ getBadges,
+ position: BadgePosition.START
+};
+
+const settings = definePluginSettings({
+ ...Object.fromEntries(
+ Object.entries(indicatorLocations).map(([key, value]) => {
+ return [key, {
+ type: OptionType.BOOLEAN,
+ description: `Show indicators ${value.description.toLowerCase()}`,
+ // onChange doesn't give any way to know which setting was changed, so restart required
+ restartNeeded: true,
+ default: true
+ }];
+ })
+ ),
+});
+
+export default definePlugin({
+ name: "RelationshipIndicators",
+ authors: [Devs.Scyye],
+ settings,
+ description: "Adds icons to indicate relationships with users.",
+ start() {
+ Object.entries(indicatorLocations).forEach(([key, value]) => {
+ if (settings.store[key]) value.onEnable();
+ });
+ },
+ stop() {
+ Object.entries(indicatorLocations).forEach(([key, value]) => {
+ if (settings.store[key]) value.onDisable();
+ });
+ },
+});
+
+
+
diff --git a/src/plugins/relationshipIndicators/utils.tsx b/src/plugins/relationshipIndicators/utils.tsx
new file mode 100644
index 0000000000..2a16ba7967
--- /dev/null
+++ b/src/plugins/relationshipIndicators/utils.tsx
@@ -0,0 +1,52 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { BadgeUserArgs, ProfileBadge } from "@api/Badges";
+import { RelationshipStore, UserStore } from "@webpack/common";
+import { User } from "discord-types/general";
+
+import { BlockedIcon, FriendIcon } from "./icons";
+
+const shouldShowIndicator = (user?: User|null) => {
+ return user && !user.bot && (RelationshipStore.isFriend(user.id) || RelationshipStore.isBlocked(user.id));
+};
+
+export const RelationshipIndicator = ({ user, wantMargin = true, wantTopMargin = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; }) => {
+ if (!shouldShowIndicator(user)) return null;
+
+ return (
+
+ {RelationshipStore.isFriend(user.id)? : }
+
+ );
+};
+
+export function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] {
+ const user = UserStore.getUser(userId);
+ if (!shouldShowIndicator(user)) return [];
+
+ return [{
+ component: () => (
+
+
+
+ ),
+ key: `vc-${RelationshipStore.isFriend(userId)?"friend":"blocked"}-indicator`,
+ }];
+}
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index c399baafea..572247e024 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -533,6 +533,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
Antti: {
name: "Antti",
id: 312974985876471810n
+ },
+ Scyye: {
+ name: "Scyye",
+ id: 553652308295155723n
}
} satisfies Record);