diff --git a/package.json b/package.json
index dbf8aaf34..9d7b6347a 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "vencord",
"private": "true",
- "version": "1.7.1",
+ "version": "1.7.2",
"description": "The cutest Discord client mod",
"homepage": "https://github.com/Vendicated/Vencord#readme",
"bugs": {
diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx
index 7a914293a..e73779adf 100644
--- a/src/plugins/betterRoleContext/index.tsx
+++ b/src/plugins/betterRoleContext/index.tsx
@@ -5,7 +5,7 @@
*/
import { Devs } from "@utils/constants";
-import { getCurrentGuild } from "@utils/discord";
+import { getCurrentGuild, getGuildRoles } from "@utils/discord";
import definePlugin from "@utils/types";
import { findByPropsLazy } from "@webpack";
import { Clipboard, Menu, PermissionStore, TextAndImagesSettingsStores } from "@webpack/common";
@@ -47,7 +47,9 @@ export default definePlugin({
contextMenus: {
"dev-context"(children, { id }: { id: string; }) {
const guild = getCurrentGuild();
- const role = guild?.roles[id];
+ if (!guild) return;
+
+ const role = getGuildRoles(guild.id)[id];
if (!role) return;
if (role.colorString) {
diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx
index 8cfd8c036..713b17d76 100644
--- a/src/plugins/decor/index.tsx
+++ b/src/plugins/decor/index.tsx
@@ -131,9 +131,10 @@ export default definePlugin({
getDecorAvatarDecorationURL({ avatarDecoration, canAnimate }: { avatarDecoration: AvatarDecoration | null; canAnimate?: boolean; }) {
// Only Decor avatar decorations have this SKU ID
if (avatarDecoration?.skuId === SKU_ID) {
- const url = new URL(`${CDN_URL}/${avatarDecoration.asset}.png`);
- url.searchParams.set("animate", (!!canAnimate && isAnimatedAvatarDecoration(avatarDecoration.asset)).toString());
- return url.toString();
+ const parts = avatarDecoration.asset.split("_");
+ // Remove a_ prefix if it's animated and animation is disabled
+ if (isAnimatedAvatarDecoration(avatarDecoration.asset) && !canAnimate) parts.shift();
+ return `${CDN_URL}/${parts.join("_")}.png`;
} else if (avatarDecoration?.skuId === RAW_SKU_ID) {
return avatarDecoration.asset;
}
diff --git a/src/plugins/friendsSince/README.md b/src/plugins/friendsSince/README.md
new file mode 100644
index 000000000..ccbb09b67
--- /dev/null
+++ b/src/plugins/friendsSince/README.md
@@ -0,0 +1,5 @@
+# FriendsSince
+
+Shows when you became friends with someone in the user popout
+
+![](https://github.com/Vendicated/Vencord/assets/45497981/bb258188-ab48-4c4d-9858-1e90ba41e926)
diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx
new file mode 100644
index 000000000..ab3320dfe
--- /dev/null
+++ b/src/plugins/friendsSince/index.tsx
@@ -0,0 +1,60 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Devs } from "@utils/constants";
+import definePlugin from "@utils/types";
+import { findByPropsLazy } from "@webpack";
+import { React, RelationshipStore } from "@webpack/common";
+
+const { Heading, Text } = findByPropsLazy("Heading", "Text");
+const container = findByPropsLazy("memberSinceContainer");
+const { getCreatedAtDate } = findByPropsLazy("getCreatedAtDate");
+const clydeMoreInfo = findByPropsLazy("clydeMoreInfo");
+const locale = findByPropsLazy("getLocale");
+const lastSection = findByPropsLazy("lastSection");
+
+export default definePlugin({
+ name: "FriendsSince",
+ description: "Shows when you became friends with someone in the user popout",
+ authors: [Devs.Elvyra],
+ patches: [
+ {
+ find: ".AnalyticsSections.USER_PROFILE}",
+ replacement: {
+ match: /\i.default,\{userId:(\i.id).{0,30}}\)/,
+ replace: "$&,$self.friendsSince({ userId: $1 })"
+ }
+ },
+ {
+ find: ".UserPopoutUpsellSource.PROFILE_PANEL,",
+ replacement: {
+ match: /\i.default,\{userId:(\i)}\)/,
+ replace: "$&,$self.friendsSince({ userId: $1 })"
+ }
+ }
+ ],
+
+ friendsSince: ErrorBoundary.wrap(({ userId }: { userId: string; }) => {
+ const friendsSince = RelationshipStore.getSince(userId);
+ if (!friendsSince) return null;
+
+ return (
+
+
+ Friends Since
+
+
+
+
+ {getCreatedAtDate(friendsSince, locale.getLocale())}
+
+
+
+ );
+ }, { noop: true })
+});
+
diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx
index e0d25c7ab..adadc90b5 100644
--- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx
+++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx
@@ -19,7 +19,7 @@
import ErrorBoundary from "@components/ErrorBoundary";
import { Flex } from "@components/Flex";
import { InfoIcon, OwnerCrownIcon } from "@components/Icons";
-import { getUniqueUsername } from "@utils/discord";
+import { getGuildRoles, getUniqueUsername } from "@utils/discord";
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { ContextMenuApi, FluxDispatcher, GuildMemberStore, Menu, PermissionsBits, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common";
import type { Guild } from "discord-types/general";
@@ -78,6 +78,8 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea
const [selectedItemIndex, selectItem] = useState(0);
const selectedItem = permissions[selectedItemIndex];
+ const roles = getGuildRoles(guild.id);
+
return (
{permissions.map((permission, index) => {
const user = UserStore.getUser(permission.id ?? "");
- const role = guild.roles[permission.id ?? ""];
+ const role = roles[permission.id ?? ""];
return (