mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-27 09:46:28 +00:00
feat(memberListActivities): add tooltips
This commit is contained in:
parent
3cfefad3f5
commit
99420e2cbe
1 changed files with 116 additions and 73 deletions
|
@ -24,6 +24,8 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
||||||
|
import { Tooltip } from "@webpack/common";
|
||||||
|
import type { ImgHTMLAttributes } from "react";
|
||||||
|
|
||||||
import { SpotifyIcon } from "./components/SpotifyIcon";
|
import { SpotifyIcon } from "./components/SpotifyIcon";
|
||||||
import { TwitchIcon } from "./components/TwitchIcon";
|
import { TwitchIcon } from "./components/TwitchIcon";
|
||||||
|
@ -97,6 +99,17 @@ interface Executable {
|
||||||
is_launcher: boolean;
|
is_launcher: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImageAttributes = ImgHTMLAttributes<HTMLImageElement> & {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
activity: Activity;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ActivityListIcon {
|
||||||
|
iconElement: JSX.Element;
|
||||||
|
tooltip?: JSX.Element | string;
|
||||||
|
}
|
||||||
|
|
||||||
const ApplicationStore: {
|
const ApplicationStore: {
|
||||||
getApplication: (id: string) => Application | null;
|
getApplication: (id: string) => Application | null;
|
||||||
} = findStoreLazy("ApplicationStore");
|
} = findStoreLazy("ApplicationStore");
|
||||||
|
@ -112,30 +125,14 @@ const fetchedApplications = new Map<string, Application | null>();
|
||||||
|
|
||||||
const xboxUrl = "https://discord.com/assets/9a15d086141be29d9fcd.png";
|
const xboxUrl = "https://discord.com/assets/9a15d086141be29d9fcd.png";
|
||||||
|
|
||||||
export default definePlugin({
|
function getApplicationIcons(activities: Activity[]) {
|
||||||
name: "MemberListActivities",
|
const applicationIcons: ImageAttributes[] = [];
|
||||||
description: "Shows activity icons in the member list",
|
|
||||||
authors: [Devs.D3SOX],
|
|
||||||
tags: ["activity"],
|
|
||||||
|
|
||||||
settings,
|
|
||||||
|
|
||||||
patchActivityList: (activities: Activity[]): JSX.Element | null => {
|
|
||||||
const icons: JSX.Element[] = [];
|
|
||||||
|
|
||||||
if (activities.some(activity => activity.name === "Spotify")) {
|
|
||||||
icons.push(<SpotifyIcon />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activities.some(activity => activity.name === "Twitch")) {
|
|
||||||
icons.push(<TwitchIcon />);
|
|
||||||
}
|
|
||||||
|
|
||||||
const applications = activities.filter(activity => activity.application_id || activity.platform);
|
const applications = activities.filter(activity => activity.application_id || activity.platform);
|
||||||
applications.forEach(activity => {
|
|
||||||
|
for (const activity of applications) {
|
||||||
const { assets, application_id, platform } = activity;
|
const { assets, application_id, platform } = activity;
|
||||||
if (!application_id && !platform) {
|
if (!application_id && !platform) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
if (assets) {
|
if (assets) {
|
||||||
|
|
||||||
|
@ -143,11 +140,11 @@ export default definePlugin({
|
||||||
if (image.startsWith("mp:")) {
|
if (image.startsWith("mp:")) {
|
||||||
const discordMediaLink = `https://media.discordapp.net/${image.replace(/mp:/, "")}`;
|
const discordMediaLink = `https://media.discordapp.net/${image.replace(/mp:/, "")}`;
|
||||||
if (settings.store.renderGifs || !discordMediaLink.endsWith(".gif")) {
|
if (settings.store.renderGifs || !discordMediaLink.endsWith(".gif")) {
|
||||||
icons.push(<img src={discordMediaLink} alt={alt}/>);
|
applicationIcons.push({ src: discordMediaLink, alt, activity });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const src = `https://cdn.discordapp.com/app-assets/${application_id}/${image}.png`;
|
const src = `https://cdn.discordapp.com/app-assets/${application_id}/${image}.png`;
|
||||||
icons.push(<img src={src} alt={alt}/>);
|
applicationIcons.push({ src, alt, activity });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -177,32 +174,78 @@ export default definePlugin({
|
||||||
if (application) {
|
if (application) {
|
||||||
if (application.icon) {
|
if (application.icon) {
|
||||||
const src = `https://cdn.discordapp.com/app-icons/${application.id}/${application.icon}.png`;
|
const src = `https://cdn.discordapp.com/app-icons/${application.id}/${application.icon}.png`;
|
||||||
icons.push(<img src={src} alt={application.name} />);
|
applicationIcons.push({ src, alt: application.name, activity });
|
||||||
} else if (platform === "xbox") {
|
} else if (platform === "xbox") {
|
||||||
icons.push(<img src={xboxUrl} alt="Xbox" />);
|
applicationIcons.push({ src: xboxUrl, alt: "Xbox", activity });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (platform === "xbox") {
|
if (platform === "xbox") {
|
||||||
icons.push(<img src={xboxUrl} alt="Xbox" />);
|
applicationIcons.push({ src: xboxUrl, alt: "Xbox", activity });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return applicationIcons;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "MemberListActivities",
|
||||||
|
description: "Shows activity icons in the member list",
|
||||||
|
authors: [Devs.D3SOX],
|
||||||
|
tags: ["activity"],
|
||||||
|
|
||||||
|
settings,
|
||||||
|
|
||||||
|
patchActivityList: (activities: Activity[]): JSX.Element | null => {
|
||||||
|
const icons: ActivityListIcon[] = [];
|
||||||
|
|
||||||
|
const spotifyActivity = activities.find(({ name }) => name === "Spotify");
|
||||||
|
if (spotifyActivity) {
|
||||||
|
icons.push({ iconElement: <SpotifyIcon />, tooltip: spotifyActivity.details ?? spotifyActivity.name });
|
||||||
|
}
|
||||||
|
|
||||||
|
const twitchActivity = activities.find(({ name }) => name === "Twitch");
|
||||||
|
if (twitchActivity) {
|
||||||
|
icons.push({ iconElement: <TwitchIcon />, tooltip: twitchActivity.details ?? twitchActivity.name });
|
||||||
|
}
|
||||||
|
const applicationIcons = getApplicationIcons(activities);
|
||||||
|
if (applicationIcons.length) {
|
||||||
|
const compareImageSource = (a: ImageAttributes, b: ImageAttributes) => {
|
||||||
|
return a.src === b.src;
|
||||||
|
};
|
||||||
|
const uniqueIcons = applicationIcons.filter((element, index, array) => {
|
||||||
|
return array.findIndex(el => compareImageSource(el, element)) === index;
|
||||||
});
|
});
|
||||||
|
for (const iconAttrs of uniqueIcons) {
|
||||||
|
icons.push({
|
||||||
|
iconElement: <img {...iconAttrs} />,
|
||||||
|
tooltip: iconAttrs.activity.details ?? iconAttrs.activity.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (icons.length) {
|
if (icons.length) {
|
||||||
const compareJSXElementsSource = (a: JSX.Element, b: JSX.Element) => {
|
|
||||||
return a.props?.src === b.props?.src;
|
|
||||||
};
|
|
||||||
const uniqueIcons = icons.filter((element, index, array) => {
|
|
||||||
return array.findIndex(el => compareJSXElementsSource(el, element)) === index;
|
|
||||||
});
|
|
||||||
return <ErrorBoundary noop>
|
return <ErrorBoundary noop>
|
||||||
<div className={cl("row")}>
|
<div className={cl("row")}>
|
||||||
{uniqueIcons.map((icon, i) => (
|
{icons.map(({ iconElement, tooltip }, i) => {
|
||||||
<div key={i} className={cl("icon")} style={{ width: `${settings.store.iconSize}px`, height: `${settings.store.iconSize}px` }}>
|
return (
|
||||||
{icon}
|
<div key={i} className={cl("icon")} style={{
|
||||||
|
width: `${settings.store.iconSize}px`,
|
||||||
|
height: `${settings.store.iconSize}px`
|
||||||
|
}}>
|
||||||
|
{tooltip ? <Tooltip text={tooltip}>
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => (
|
||||||
|
<div
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}>
|
||||||
|
{iconElement}
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
|
</Tooltip> : iconElement}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</ErrorBoundary>;
|
</ErrorBoundary>;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue