diff --git a/src/plugins/bannersEverywhere/README.md b/src/plugins/bannersEverywhere/README.md index a2845ec2d..b868a6a9a 100644 --- a/src/plugins/bannersEverywhere/README.md +++ b/src/plugins/bannersEverywhere/README.md @@ -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) diff --git a/src/plugins/bannersEverywhere/index.css b/src/plugins/bannersEverywhere/index.css index 0d7217e8a..269baf4ad 100644 --- a/src/plugins/bannersEverywhere/index.css +++ b/src/plugins/bannersEverywhere/index.css @@ -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; -} +} \ No newline at end of file diff --git a/src/plugins/bannersEverywhere/index.tsx b/src/plugins/bannersEverywhere/index.tsx index 35fa04705..1f4a5e8ba 100644 --- a/src/plugins/bannersEverywhere/index.tsx +++ b/src/plugins/bannersEverywhere/index.tsx @@ -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(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 ( ); - }, + }, { 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 ""; - }, });