mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-26 14:48:21 -04:00
Fixes
This commit is contained in:
parent
65bb12c33b
commit
76746c0c4a
17 changed files with 74 additions and 548 deletions
|
@ -1,193 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2023 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Flex } from "@components/Flex";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import { closeModal, ModalCloseButton,ModalContent, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { find, findByPropsLazy } from "@webpack";
|
||||
import { Button, Clickable, Forms, GuildStore, PermissionsBits, PermissionStore, Popout, SearchableSelect, showToast, Text, TextInput, Toasts, useMemo, UserStore, useState } from "@webpack/common";
|
||||
import { Guild } from "discord-types/general";
|
||||
import { HtmlHTMLAttributes } from "react";
|
||||
|
||||
import { cl, getEmojiUrl,SoundEvent } from "../utils";
|
||||
|
||||
export function openCloneSoundModal(item) {
|
||||
const key = openModal(props =>
|
||||
<ModalRoot {...props}>
|
||||
<CloneSoundModal item={item} closeModal={() => closeModal(key)} />
|
||||
</ModalRoot>
|
||||
);
|
||||
}
|
||||
|
||||
// Thanks https://github.com/Vendicated/Vencord/blob/ea11f2244fde469ce308f8a4e7224430be62f8f1/src/plugins/emoteCloner/index.tsx#L173-L177
|
||||
const getFontSize = (s: string, small: boolean = false) => {
|
||||
const sizes = [20, 20, 18, 18, 16, 14, 12];
|
||||
return sizes[s.length + (small ? 1 : 0)] ?? 8;
|
||||
};
|
||||
|
||||
function GuildAcronym({ acronym, small, style = {} }) {
|
||||
return (
|
||||
<Flex style={{ alignItems: "center", justifyContent: "center", overflow: "hidden", fontSize: getFontSize(acronym, small), ...style }}>
|
||||
<Text>{acronym}</Text>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
function CustomInput({ children, className = "", ...props }: HtmlHTMLAttributes<HTMLDivElement>) {
|
||||
return <div className={classes(cl("clone-input"), className)} {...props}>
|
||||
{children}
|
||||
</div>;
|
||||
}
|
||||
|
||||
const EmojiPicker = LazyComponent(() => find(e => e.default?.type?.render?.toString?.().includes?.(".updateNewlyAddedLastSeen)")).default);
|
||||
|
||||
const sounds = findByPropsLazy("uploadSound", "updateSound");
|
||||
|
||||
export function CloneSoundModal({ item, closeModal }: { item: SoundEvent, closeModal: () => void; }) {
|
||||
const ownedGuilds = useMemo(() => {
|
||||
return Object.values(GuildStore.getGuilds()).filter(guild =>
|
||||
guild.ownerId === UserStore.getCurrentUser().id ||
|
||||
(PermissionStore.getGuildPermissions({ id: guild.id }) & PermissionsBits.CREATE_GUILD_EXPRESSIONS) === PermissionsBits.CREATE_GUILD_EXPRESSIONS);
|
||||
}, []);
|
||||
|
||||
const [selectedGuild, setSelectedGuild] = useState<Guild | null>(null);
|
||||
const [soundName, setSoundName] = useState<string | undefined>(undefined);
|
||||
const [soundEmoji, setSoundEmoji] = useState<any | undefined>(undefined);
|
||||
const [loadingButton, setLoadingButton] = useState<boolean>(false);
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const isEmojiValid = soundEmoji?.guildId ? soundEmoji.guildId === selectedGuild?.id : true;
|
||||
|
||||
const styles = {
|
||||
selected: { height: "24px", width: "24px" },
|
||||
nonselected: { width: "36px", height: "36px", marginTop: "4px" }
|
||||
};
|
||||
const getStyle = key => key === "selected" ? styles.selected : styles.nonselected;
|
||||
|
||||
function onSelectEmoji(emoji) {
|
||||
setShow(false);
|
||||
setSoundEmoji(emoji);
|
||||
}
|
||||
|
||||
return <>
|
||||
<ModalHeader>
|
||||
<Flex style={{ width: "100%", justifyContent: "center" }}>
|
||||
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>Clone Sound</Text>
|
||||
<ModalCloseButton onClick={closeModal} />
|
||||
</Flex>
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<Forms.FormTitle className={Margins.top16}>Cloning Sound</Forms.FormTitle>
|
||||
<CustomInput style={{ display: "flex", flexDirection: "row", gap: "10px", alignItems: "center" }} className={Margins.bottom16}>
|
||||
<img src={getEmojiUrl(item.emoji)} width="24" height="24" />
|
||||
<Text>{item.soundId}</Text>
|
||||
</CustomInput>
|
||||
<Forms.FormTitle required={true} aria-required="true">Add to server:</Forms.FormTitle>
|
||||
<SearchableSelect
|
||||
options={
|
||||
ownedGuilds.map(guild => ({
|
||||
label: guild.name,
|
||||
value: guild
|
||||
}))
|
||||
}
|
||||
|
||||
placeholder="Select a server"
|
||||
value={selectedGuild ? ({
|
||||
label: selectedGuild.name,
|
||||
value: selectedGuild,
|
||||
key: "selected"
|
||||
}) : undefined}
|
||||
|
||||
onChange={v => setSelectedGuild(v)}
|
||||
closeOnSelect={true}
|
||||
renderOptionPrefix={v => v ? (
|
||||
v.value.icon ?
|
||||
<img width={36} height={36} src={v.value.getIconURL(96, true)} style={{ borderRadius: "50%", ...getStyle(v.key) }} /> :
|
||||
<GuildAcronym acronym={v.value.acronym} style={getStyle(v.key)} small={v.key === "selected"} />
|
||||
) : null}
|
||||
/>
|
||||
<Flex flexDirection="row" style={{ gap: "10px", justifyContent: "space-between" }} className={classes(Margins.top16, Margins.bottom16)}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Forms.FormTitle required={true} aria-required="true">Sound Name</Forms.FormTitle>
|
||||
<TextInput value={soundName} onChange={v => setSoundName(v)} placeholder="Sound Name" />
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Forms.FormTitle>Related Emoji</Forms.FormTitle>
|
||||
<Popout
|
||||
position="bottom"
|
||||
align="right"
|
||||
animation={Popout.Animation.NONE}
|
||||
shouldShow={show}
|
||||
onRequestClose={() => setShow(false)}
|
||||
renderPopout={() => <EmojiPicker pickerIntention={2} channel={{ getGuildId: () => selectedGuild?.id }} onSelectEmoji={onSelectEmoji} />}
|
||||
>
|
||||
{() => (
|
||||
<Clickable onClick={() => setShow(v => !v)}>
|
||||
<CustomInput style={{ display: "flex", flexDirection: "row", gap: "10px", alignItems: "center", cursor: "pointer" }}>
|
||||
{soundEmoji ?
|
||||
<>
|
||||
<img src={getEmojiUrl({ name: soundEmoji.surrogates, id: soundEmoji.id })} width="24" height="24" style={{ cursor: "pointer" }} />
|
||||
<Text style={{ color: "var(--text-muted)", cursor: "pointer" }}>:{soundEmoji.name ? soundEmoji.name.split("~")[0] : soundEmoji.uniqueName}:</Text>
|
||||
</> :
|
||||
<>
|
||||
<img src={getEmojiUrl({ name: "😊" })} width="24" height="24" style={{ filter: "grayscale(100%)", cursor: "pointer" }} />
|
||||
<Text style={{ color: "var(--text-muted)", cursor: "pointer" }}>Click to Select</Text>
|
||||
</>
|
||||
}
|
||||
</CustomInput>
|
||||
</Clickable>
|
||||
)}
|
||||
</Popout>
|
||||
</div>
|
||||
</Flex>
|
||||
{!isEmojiValid && <Forms.FormText style={{ color: "var(--text-danger)" }} className={Margins.bottom16}>You can't use that emoji in that server</Forms.FormText>}
|
||||
<Button onClick={() => {
|
||||
setLoadingButton(true);
|
||||
fetch(`https://cdn.discordapp.com/soundboard-sounds/${item.soundId}`).then(function (response) {
|
||||
if (!response.body) {
|
||||
setLoadingButton(false);
|
||||
showToast("Error fetching the sound", Toasts.Type.FAILURE);
|
||||
return;
|
||||
}
|
||||
response.body.getReader().read().then(function (result) {
|
||||
if (!result.value) {
|
||||
setLoadingButton(false);
|
||||
showToast("Error reading the sound content", Toasts.Type.FAILURE);
|
||||
return;
|
||||
}
|
||||
return btoa(String.fromCharCode(...result.value));
|
||||
}).then(function (b64) {
|
||||
|
||||
sounds.uploadSound({
|
||||
guildId: selectedGuild?.id,
|
||||
name: soundName,
|
||||
sound: `data:audio/ogg;base64,${b64}`,
|
||||
...(soundEmoji.id ? { emojiId: soundEmoji.id } : { emojiName: soundEmoji.surrogates }),
|
||||
volume: 1
|
||||
}).then(() => {
|
||||
showToast(`Sound added to ${selectedGuild?.name}`, Toasts.Type.SUCCESS);
|
||||
closeModal();
|
||||
}).catch(() => {
|
||||
setLoadingButton(false);
|
||||
showToast("Error while adding sound", Toasts.Type.FAILURE);
|
||||
});
|
||||
|
||||
});
|
||||
}).catch(e => {
|
||||
setLoadingButton(false);
|
||||
showToast("Error fetching the sound", Toasts.Type.FAILURE);
|
||||
return;
|
||||
});
|
||||
}}
|
||||
disabled={(!(selectedGuild && soundName && isEmojiValid)) || loadingButton}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
style={{ width: "100%" }}
|
||||
className={Margins.bottom16}>Add to Server</Button>
|
||||
</ModalContent>
|
||||
</>;
|
||||
}
|
|
@ -13,8 +13,7 @@ import { Button, Clickable, ContextMenuApi, FluxDispatcher, Forms, Menu, Text, T
|
|||
import { User } from "discord-types/general";
|
||||
|
||||
import { clearLoggedSounds, getLoggedSounds } from "../store";
|
||||
import { addListener, AvatarStyles, cl, downloadAudio, getEmojiUrl, getSoundboardVolume, playSound, removeListener, SoundLogEntry, UserSummaryItem } from "../utils";
|
||||
import { openCloneSoundModal } from "./CloneSoundModal";
|
||||
import { addListener, AvatarStyles, cl, downloadAudio, getEmojiUrl, playSound, removeListener, SoundLogEntry, UserSummaryItem } from "../utils";
|
||||
import { openMoreUsersModal } from "./MoreUsersModal";
|
||||
import { openUserModal } from "./UserModal";
|
||||
|
||||
|
@ -100,13 +99,6 @@ export default function SoundBoardLog({ data, closeModal }) {
|
|||
navId="soundboardlogger-sound-menu"
|
||||
onClose={() => FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })}
|
||||
>
|
||||
<Menu.MenuGroup label="Extra buttons">
|
||||
<Menu.MenuItem
|
||||
id={label("clone")}
|
||||
label="Clone sound"
|
||||
action={() => openCloneSoundModal(item)}
|
||||
/>
|
||||
</Menu.MenuGroup>
|
||||
</Menu.Menu>
|
||||
);
|
||||
}
|
||||
|
@ -164,7 +156,7 @@ export default function SoundBoardLog({ data, closeModal }) {
|
|||
<Flex flexDirection="row" className={cl("sound-buttons")}>
|
||||
<Button color={Button.Colors.PRIMARY} size={Button.Sizes.SMALL} onClick={() => downloadAudio(item.soundId)}>Download</Button>
|
||||
<Button color={Button.Colors.GREEN} size={Button.Sizes.SMALL} onClick={() => copyWithToast(item.soundId, "ID copied to clipboard!")}>Copy ID</Button>
|
||||
<Tooltip text={`Soundboard volume: ${Math.floor(getSoundboardVolume())}%`}>
|
||||
<Tooltip text={"Soundboard volume: currently broken"}>
|
||||
{({ onMouseEnter, onMouseLeave }) =>
|
||||
<Button color={Button.Colors.BRAND} size={Button.Sizes.SMALL} onClick={() => playSound(item.soundId)} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>Play Sound</Button>
|
||||
}
|
||||
|
|
|
@ -39,14 +39,9 @@ export function getEmojiUrl(emoji) {
|
|||
return emoji.id ? `https://cdn.discordapp.com/emojis/${emoji.id}.png?size=32` : getURL(emoji.name);
|
||||
}
|
||||
|
||||
const v1 = findByPropsLazy("amplitudeToPerceptual");
|
||||
const v2 = findByPropsLazy("getAmplitudinalSoundboardVolume");
|
||||
|
||||
export const getSoundboardVolume = () => v1.amplitudeToPerceptual(v2.getAmplitudinalSoundboardVolume());
|
||||
|
||||
export const playSound = id => {
|
||||
const audio = new Audio(`https://cdn.discordapp.com/soundboard-sounds/${id}`);
|
||||
audio.volume = getSoundboardVolume() / 100;
|
||||
audio.volume = 75 / 100;
|
||||
audio.play();
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue