feat(serverProfilesToolbox): add support for profile effects, avatar decorations and clipboard

This commit is contained in:
D3SOX 2024-05-15 18:33:18 +02:00
parent 92b303b9cc
commit 554c3e2f3c
No known key found for this signature in database
GPG key ID: 39EC1673FC37B048

View file

@ -7,24 +7,59 @@
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
import { Button, GuildMemberStore, UserProfileStore, UserStore } from "@webpack/common"; import {
Button,
Clipboard,
GuildMemberStore,
Text,
Toasts,
UserProfileStore,
UserStore
} from "@webpack/common";
import { GuildMember } from "discord-types/general";
const SummaryItem = findComponentByCodeLazy("borderType", "showBorder", "hideDivider"); const SummaryItem = findComponentByCodeLazy("borderType", "showBorder", "hideDivider");
let savedNick: string | null = null; interface SavedProfile {
let savedPronouns: string | null = null; nick: string | null;
let savedBio: string | undefined = undefined; pronouns: string | null;
let savedThemeColors: number[] | undefined = undefined; bio: string | null;
let savedBanner: string | undefined = undefined; themeColors: number[] | undefined;
let savedAvatar: string | undefined = undefined; banner: string | undefined;
avatar: string | undefined;
profileEffectId: string | undefined;
avatarDecoration: string | undefined;
}
const { setPendingAvatar, setPendingBanner, setPendingBio, setPendingNickname, setPendingPronouns, setPendingThemeColors }: { const savedProfile: SavedProfile = {
nick: null,
pronouns: null,
bio: null,
themeColors: undefined,
banner: undefined,
avatar: undefined,
profileEffectId: undefined,
avatarDecoration: undefined,
};
const {
setPendingAvatar,
setPendingBanner,
setPendingBio,
setPendingNickname,
setPendingPronouns,
setPendingThemeColors,
setPendingProfileEffectId,
setPendingAvatarDecoration,
}: {
setPendingAvatar: (a: string | undefined) => void; setPendingAvatar: (a: string | undefined) => void;
setPendingBanner: (a: string | undefined) => void; setPendingBanner: (a: string | undefined) => void;
setPendingBio: (a: string | undefined) => void; setPendingBio: (a: string | null) => void;
setPendingNickname: (a: string | null) => void; setPendingNickname: (a: string | null) => void;
setPendingPronouns: (a: string | null) => void; setPendingPronouns: (a: string | null) => void;
setPendingThemeColors: (a: number[] | undefined) => void; setPendingThemeColors: (a: number[] | undefined) => void;
setPendingProfileEffectId: (a: string | undefined) => void;
setPendingAvatarDecoration: (a: string | undefined) => void;
} = findByPropsLazy("setPendingNickname", "setPendingPronouns"); } = findByPropsLazy("setPendingNickname", "setPendingPronouns");
export default definePlugin({ export default definePlugin({
@ -36,47 +71,108 @@ export default definePlugin({
const currentUser = UserStore.getCurrentUser(); const currentUser = UserStore.getCurrentUser();
const premiumType = currentUser.premiumType ?? 0; const premiumType = currentUser.premiumType ?? 0;
const copy = () => {
const profile = UserProfileStore.getGuildMemberProfile(currentUser.id, guildId);
const nick = GuildMemberStore.getNick(guildId, currentUser.id);
const selfMember = GuildMemberStore.getMember(guildId, currentUser.id) as GuildMember & { avatarDecoration: string | undefined };
savedProfile.nick = nick ?? "";
savedProfile.pronouns = profile.pronouns;
savedProfile.bio = profile.bio;
savedProfile.themeColors = profile.themeColors;
savedProfile.banner = profile.banner;
savedProfile.avatar = selfMember.avatar;
savedProfile.profileEffectId = profile.profileEffectId;
savedProfile.avatarDecoration = selfMember.avatarDecoration;
};
const paste = () => {
setPendingNickname(savedProfile.nick);
setPendingPronouns(savedProfile.pronouns);
if (premiumType === 2) {
setPendingBio(savedProfile.bio);
setPendingThemeColors(savedProfile.themeColors);
setPendingBanner(savedProfile.banner);
setPendingAvatar(savedProfile.avatar);
setPendingProfileEffectId(savedProfile.profileEffectId);
setPendingAvatarDecoration(savedProfile.avatarDecoration);
}
};
const reset = () => {
setPendingNickname(null);
setPendingPronouns("");
if (premiumType === 2) {
setPendingBio(null);
setPendingThemeColors([]);
setPendingBanner(undefined);
setPendingAvatar(undefined);
setPendingProfileEffectId(undefined);
setPendingAvatarDecoration(undefined);
}
};
const copyToClipboard = () => {
copy();
Clipboard.copy(JSON.stringify(savedProfile));
};
const pasteFromClipboard = async () => {
try {
const clip = await navigator.clipboard.readText();
if (!clip) {
Toasts.show({
message: "Clipboard is empty",
type: Toasts.Type.FAILURE,
id: Toasts.genId(),
});
return;
}
const clipboardProfile: SavedProfile = JSON.parse(clip);
if (!("nick" in clipboardProfile)) {
Toasts.show({
message: "Data is not in correct format",
type: Toasts.Type.FAILURE,
id: Toasts.genId(),
});
return;
}
Object.assign(savedProfile, JSON.parse(clip));
paste();
} catch (e) {
Toasts.show({
message: `Failed to read clipboard data: ${e}`,
type: Toasts.Type.FAILURE,
id: Toasts.genId(),
});
}
};
return <SummaryItem title="Server Profiles Toolbox" hideDivider={false} forcedDivider> return <SummaryItem title="Server Profiles Toolbox" hideDivider={false} forcedDivider>
<div style={{ display: "flex", gap: "5px" }}> <div style={{ display: "flex", alignItems: "center", flexDirection: "column", gap: "5px" }}>
<Button onClick={() => { <Text variant="text-md/normal">
const profile = UserProfileStore.getGuildMemberProfile(currentUser.id, guildId); Use the following buttons to mange the currently selected server
const nick = GuildMemberStore.getNick(guildId, currentUser.id); </Text>
const selfMember = GuildMemberStore.getMember(guildId, currentUser.id); <div style={{ display: "flex", gap: "5px" }}>
savedNick = nick ?? ""; <Button onClick={copy}>
savedPronouns = profile.pronouns; Copy profile
savedBio = profile.bio; </Button>
savedThemeColors = profile.themeColors; <Button onClick={paste}>
savedBanner = profile.banner; Paste profile
savedAvatar = selfMember.avatar; </Button>
}}> <Button onClick={reset}>
Copy profile Reset profile
</Button> </Button>
<Button onClick={() => { </div>
// set pending <div style={{ display: "flex", gap: "5px" }}>
setPendingNickname(savedNick); <Button onClick={copyToClipboard}>
setPendingPronouns(savedPronouns); Copy to clipboard
if (premiumType === 2) { </Button>
setPendingBio(savedBio); <Button onClick={pasteFromClipboard}>
setPendingThemeColors(savedThemeColors); Paste from clipboard
setPendingBanner(savedBanner); </Button>
setPendingAvatar(savedAvatar); </div>
}
}}>
Paste profile
</Button>
<Button onClick={() => {
// reset
setPendingNickname("");
setPendingPronouns("");
if (premiumType === 2) {
setPendingBio("");
setPendingThemeColors([]);
setPendingBanner("");
setPendingAvatar("");
}
}}>
Reset profile
</Button>
</div> </div>
</SummaryItem>; </SummaryItem>;
}, },