1
0
Fork 1
mirror of https://github.com/Vendicated/Vencord.git synced 2025-01-10 09:56:24 +00:00

use store instead of manual fetching

This commit is contained in:
Luna 2024-05-27 15:42:46 -04:00
parent f124164447
commit 77975c0664
3 changed files with 40 additions and 95 deletions

View file

@ -2,4 +2,4 @@
Displays nitro and USRBG banners as a background in the member list
![Adds banners to member list](https://github.com/Vendicated/Vencord/assets/44179559/d8a3a2f2-8491-4a4f-b43e-22fdf46622e5)
![](https://github.com/Vendicated/Vencord/assets/44179559/d8a3a2f2-8491-4a4f-b43e-22fdf46622e5)

View file

@ -2,10 +2,12 @@
.vc-banners-everywhere-memberlist {
opacity: 0.8;
-webkit-mask-image: linear-gradient(to right, transparent 20%, #fff);
mask-image: linear-gradient(to right, transparent 20%, #fff);
height: 100%;
width: 100%;
background-size: cover;
background-position: center;
position: absolute;
border-radius: 4px;
cursor: pointer;
}
}

View file

@ -8,10 +8,13 @@ import { definePluginSettings } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { RestAPI } from "@webpack/common";
import { RestAPI, UserProfileStore, useEffect, useStateFromStores } from "@webpack/common";
import { User } from "discord-types/general";
import style from "./index.css?managed";
import style from "./index.css";
import { fetchUserProfile, getCurrentGuild } from "@utils/discord";
import ErrorBoundary from "@components/ErrorBoundary";
import { Queue } from "@utils/Queue";
const settings = definePluginSettings({
animate: {
@ -20,103 +23,51 @@ const settings = definePluginSettings({
default: false
},
});
const data: { [key: string]: string | null; } = {};
let enabled = false;
let queue = new Queue();
async function refreshVisibleMembers() {
// TODO - move away from dom query
for await (const elem of document.querySelectorAll(
'div[role="listitem"][class*="member"]'
)) {
const rect = elem.getBoundingClientRect();
if (
!(
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <=
(window.innerHeight || document.documentElement.clientHeight) &&
rect.right <=
(window.innerWidth || document.documentElement.clientWidth)
)
)
continue;
const useFetchMemberProfile = (userId: string): string => {
const profile = useStateFromStores([UserProfileStore], () => UserProfileStore.getUserProfile(userId));
const avatar = (
elem.querySelector('img[class*="avatar"]') as any
).src.split("/");
useEffect(() => {
let cancel = false;
let memberId = "";
if (avatar[3] === "avatars") memberId = avatar[4];
else if (avatar[3] === "guilds") memberId = avatar[6];
else continue;
queue.push(() => {
if (cancel) return Promise.resolve(void 0);
return fetchUserProfile(userId).finally(async () => {
await new Promise<void>(resolve => setTimeout(resolve, 1000));
});
});
if (data[memberId]) continue;
let res: any;
try {
res = (await RestAPI.get({
url: `/users/${memberId}`,
})) as { body: { banner: string; }; };
} catch (e: any) {
if (e.status === 429) {
await new Promise(r => setTimeout(r, e.body.retry_after * 2000));
continue;
}
}
const { banner } = res.body;
if (!banner) {
data[memberId] = null;
continue;
}
data[
memberId
] = `https://cdn.discordapp.com/banners/${memberId}/${banner}.${banner.startsWith("a_") ? "gif" : "png"
}?size=4096`;
// Trigger a rerender via hovering
elem.dispatchEvent(
new MouseEvent("mouseover", {
bubbles: true,
cancelable: true,
view: window,
})
);
// Please dont ratelimit us :pleadey:
await new Promise(r => setTimeout(r, 1000));
}
if (enabled) {
setTimeout(refreshVisibleMembers, 1000);
}
}
return () => { cancel = true; };
}, []);
if (!profile?.banner) return "";
return `https://cdn.discordapp.com/banners/${userId}/${profile.banner}`;
};
export default definePlugin({
name: "BannersEverywhere",
description: "Displays nitro and USRBG banners in the member list",
description: "Displays banners in the member list ",
authors: [Devs.ImLvna, Devs.AutumnVN],
settings,
patches: [
{
find: "lostPermissionTooltipText",
find: ".Messages.GUILD_OWNER,",
replacement:
{
// We add the banner as a property while we can still access the user id
match: /((\i)=\i\.user.+)(,avatar:function)/,
replace: "$1,banner:$self.memberListBannerHook($2)$3",
match: /verified:(\i).isVerifiedBot.*?name:null.*?(?=avatar:)/,
replace: "$&banner:$self.memberListBanner({user: $1}),",
},
},
{
find: "apply(this,arguments)).handleKeyPress",
find: "role:\"listitem\",innerRef",
replacement:
{
// We cant access the user id here, so we take the banner property we set earlier
match: /(renderInner=function.+\i=)(\i)\.children/,
replace: "$1[$2.banner, $2.children]",
match: /let{avatar:\i.*?focusProps:\i.*?=(\i).*?children:\[/,
replace: "$&$1.banner,"
}
}
@ -124,31 +75,23 @@ export default definePlugin({
start() {
enableStyle(style);
enabled = true;
refreshVisibleMembers();
},
stop() {
enabled = false;
disableStyle(style);
},
memberListBannerHook(user: User) {
let url = this.getBanner(user.id);
if (url === "") return;
if (!settings.store.animate) url = url.replace(".gif", ".png");
memberListBanner: ErrorBoundary.wrap(({ user }: { user: User; }) => {
let url = useFetchMemberProfile(user.id);
if (url === "") return null;
if (!settings.store.animate) url = url.replace(".gif", ".png");
return (
<img src={url} className="vc-banners-everywhere-memberlist"></img>
);
},
}, { noop: true }),
getBanner(userId: string): string {
if (data[userId]) return data[userId] as string;
if (Vencord.Plugins.isPluginEnabled("USRBG") && (Vencord.Plugins.plugins.USRBG as any).data[userId]) {
data[userId] = (Vencord.Plugins.plugins.USRBG as any).data[userId];
return data[userId] as string;
}
return "";
},
});