mirror of
https://github.com/Equicord/Equicord.git
synced 2025-03-04 08:20:02 -05:00
Merge branch 'dev'
This commit is contained in:
commit
8f0229675b
8 changed files with 350 additions and 405 deletions
|
@ -31,7 +31,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
|
||||||
- ColorMessage by Kyuuhachi
|
- ColorMessage by Kyuuhachi
|
||||||
- CommandPalette by Ethan
|
- CommandPalette by Ethan
|
||||||
- CopyUserMention by Cortex and castdrian
|
- CopyUserMention by Cortex and castdrian
|
||||||
- CustomSounds by ScattrdBlade
|
- CustomSounds by TheKodeToad and SpikeHD
|
||||||
- CuteAnimeBoys by ShadyGoat
|
- CuteAnimeBoys by ShadyGoat
|
||||||
- CuteNekos by echo
|
- CuteNekos by echo
|
||||||
- CutePats by thororen
|
- CutePats by thororen
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { classNameFactory } from "@api/Styles";
|
||||||
|
import { makeRange } from "@components/PluginSettings/components";
|
||||||
|
import { Margins } from "@utils/margins";
|
||||||
|
import { classes } from "@utils/misc";
|
||||||
|
import { useForceUpdater } from "@utils/react";
|
||||||
|
import { findByCodeLazy, findLazy } from "@webpack";
|
||||||
|
import { Button, Card, Forms, Slider, Switch, useRef } from "@webpack/common";
|
||||||
|
import { ComponentType, Ref, SyntheticEvent } from "react";
|
||||||
|
|
||||||
|
import { SoundOverride, SoundPlayer, SoundType } from "../types";
|
||||||
|
|
||||||
|
type FileInput = ComponentType<{
|
||||||
|
ref: Ref<HTMLInputElement>;
|
||||||
|
onChange: (e: SyntheticEvent<HTMLInputElement>) => void;
|
||||||
|
multiple?: boolean;
|
||||||
|
filters?: { name?: string; extensions: string[]; }[];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
const playSound: (id: string) => SoundPlayer = findByCodeLazy(".playWithListener().then");
|
||||||
|
const FileInput: FileInput = findLazy(m => m.prototype?.activateUploadDialogue && m.prototype.setRef);
|
||||||
|
const cl = classNameFactory("vc-custom-sounds-");
|
||||||
|
|
||||||
|
export function SoundOverrideComponent({ type, override, onChange }: { type: SoundType; override: SoundOverride; onChange: () => Promise<void>; }) {
|
||||||
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
const sound = useRef<SoundPlayer | null>(null);
|
||||||
|
const update = useForceUpdater();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className={cl("card")}>
|
||||||
|
<Switch
|
||||||
|
value={override.enabled}
|
||||||
|
onChange={value => {
|
||||||
|
override.enabled = value;
|
||||||
|
onChange();
|
||||||
|
update();
|
||||||
|
}}
|
||||||
|
className={Margins.bottom16}
|
||||||
|
hideBorder={true}
|
||||||
|
>
|
||||||
|
{type.name} <span className={cl("id")}>({type.id})</span>
|
||||||
|
</Switch>
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
className={Margins.bottom16}
|
||||||
|
onClick={() => {
|
||||||
|
if (sound.current != null)
|
||||||
|
sound.current.stop();
|
||||||
|
sound.current = playSound(type.id);
|
||||||
|
}}
|
||||||
|
disabled={!override.enabled}
|
||||||
|
>
|
||||||
|
Preview
|
||||||
|
</Button>
|
||||||
|
<Forms.FormTitle>Replacement Sound</Forms.FormTitle>
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
disabled={!override.enabled}
|
||||||
|
className={classes(Margins.right8, Margins.bottom16, cl("upload"))}
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
<FileInput
|
||||||
|
ref={fileInputRef}
|
||||||
|
onChange={event => {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (!event.currentTarget?.files?.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const { files } = event.currentTarget;
|
||||||
|
const file = files[0];
|
||||||
|
|
||||||
|
// Set override URL to a data URI
|
||||||
|
const reader = new FileReader;
|
||||||
|
reader.onload = () => {
|
||||||
|
override.url = reader.result as string;
|
||||||
|
onChange();
|
||||||
|
update();
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}}
|
||||||
|
// Sorry .caf lovers, https://en.wikipedia.org/wiki/HTML5_audio#Supported_audio_coding_formats
|
||||||
|
filters={[{ extensions: ["mp3", "wav", "ogg", "webm", "flac"] }]}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.RED}
|
||||||
|
onClick={() => {
|
||||||
|
override.url = "";
|
||||||
|
onChange();
|
||||||
|
update();
|
||||||
|
}}
|
||||||
|
disabled={!(override.enabled && override.url.length !== 0)}
|
||||||
|
style={{ display: "inline" }}
|
||||||
|
className={classes(Margins.right8, Margins.bottom16)}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
<Forms.FormTitle>Volume</Forms.FormTitle>
|
||||||
|
<Slider
|
||||||
|
markers={makeRange(0, 100, 10)}
|
||||||
|
initialValue={override.volume}
|
||||||
|
onValueChange={value => {
|
||||||
|
override.volume = value;
|
||||||
|
onChange();
|
||||||
|
update();
|
||||||
|
}}
|
||||||
|
className={Margins.bottom16}
|
||||||
|
disabled={!override.enabled}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,402 +0,0 @@
|
||||||
/*
|
|
||||||
* Vencord, a Discord client mod
|
|
||||||
* Copyright (c) 2024 Vendicated and contributors
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
|
||||||
import { Devs } from "@utils/constants";
|
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
|
||||||
|
|
||||||
const soundFileMapping: { [key: string]: string[]; } = {
|
|
||||||
discodoDetuneURL: ["c9bfe03395cf2616891f.mp3", "9b8b7e8c94287d5491a8.mp3"],
|
|
||||||
activitiesRocketTimeURL: ["cd402df20cddf4d85b4b.mp3"],
|
|
||||||
activityEndURL: ["37530244cdcd5141095b.mp3"],
|
|
||||||
activityLaunchURL: ["267f72c6f838aac3be94.mp3"],
|
|
||||||
activityUserJoinURL: ["74c606872cea9803e310.mp3"],
|
|
||||||
activityUserLeftURL: ["99bd2585703114d2df64.mp3"],
|
|
||||||
asmrMessage1URL: ["d04d1ee13ab2d7d04e97.mp3"],
|
|
||||||
bitMessage1URL: ["fd9f21c60424f7bbe603.mp3"],
|
|
||||||
bopMessage1URL: ["f9b3c218d2bac00a50a5.mp3"],
|
|
||||||
callCallingURL: ["11b68eb8f243b5f6c8d7.mp3", "ec09898a0bd65dfaa768.mp3"],
|
|
||||||
callRingingURL: ["986703daecf955ce3ce3.mp3", "6345bccfecdfa67fdb97.mp3"],
|
|
||||||
callRingingBeatURL: ["3b3a2f5f29b9cb656efb.mp3"],
|
|
||||||
callRingingHalloweenURL: ["feb12b25f1200b97c4eb.mp3"],
|
|
||||||
callRingingSnowHalationURL: ["99b1d8a6fe0b95e99827.mp3"],
|
|
||||||
callRingingSnowsgivingURL: ["54527e70cf0ddaeff76f.mp3"],
|
|
||||||
clipErrorURL: ["4185e05ac87668c95db7.mp3"],
|
|
||||||
clipSaveURL: ["f96b272b4140be6ce8a9.mp3"],
|
|
||||||
ddrDownURL: ["60b2fa578027733f07b2.mp3"],
|
|
||||||
ddrLeftURL: ["6a2283291b8468b5dcbc.mp3"],
|
|
||||||
ddrRightURL: ["ede3b86253bb4aa1615b.mp3"],
|
|
||||||
ddrUpURL: ["89547833e1e1ebb138a4.mp3"],
|
|
||||||
deafenURL: ["763976e8bc7c745f1bbb.mp3", "1e63dc2f54bef5c5003c.mp3"],
|
|
||||||
disconnectDetuneURL: ["752b32be8f41b5ef55c4.mp3"],
|
|
||||||
duckyMessage1URL: ["7732a4c7760789c64269.mp3"],
|
|
||||||
hangStatusSelectURL: ["6f82a1ced41ffba7e474.mp3"],
|
|
||||||
highfiveClapURL: ["b6765c41e5305ed3ccbf.mp3"],
|
|
||||||
highfiveWhistleURL: ["ea499ca7cb948b4e89f3.mp3"],
|
|
||||||
humanManURL: ["ba335c8e058cf0edef0c.mp3"],
|
|
||||||
lofiMessage1URL: ["8fd01840800c5b8d5d40.mp3"],
|
|
||||||
mention1URL: ["72d6195de7af6f6c522f.mp3"],
|
|
||||||
mention2URL: ["5746c97822ddd998ecaa.mp3"],
|
|
||||||
mention3URL: ["90268f54ea2962dd9a9d.mp3"],
|
|
||||||
message1DetuneURL: ["70ae9d5bc54e4e0954f9.mp3", "ed256a76f3fe748177de.mp3"],
|
|
||||||
message2URL: ["94d97da9d3ca65ca5c48.mp3"],
|
|
||||||
message3URL: ["647a0cfe7a004fa8b20d.mp3"],
|
|
||||||
muteDetuneURL: ["ad1365b07daf20cf62d5.mp3", "e8ffe6892e47d655e796.mp3"],
|
|
||||||
overlayunlockURL: ["cf5424f20c2a9c65b6bc.mp3"],
|
|
||||||
poggermodeAchievementUnlockURL: ["156fff4a60f8bd215dd9.mp3"],
|
|
||||||
poggermodeApplauseURL: ["07ff9c560f9ba1c99cc8.mp3"],
|
|
||||||
poggermodeEnabledURL: ["73eaa6460d4bdb9dcd4d.mp3"],
|
|
||||||
poggermodeMessageSendURL: ["7e01b5cb50d9d1941f16.mp3"],
|
|
||||||
pttStartDetuneURL: ["369f4aaf35687b9f986d.mp3", "3d1f7316482d3b37e947.mp3"],
|
|
||||||
pttStopDetuneURL: ["b843a42563e5f3144483.mp3", "1e1af3535e94d2143b69.mp3"],
|
|
||||||
reconnectURL: ["da2dc3239ecd9ab74be1.mp3"],
|
|
||||||
robotManURL: ["76ff191944dd58f4835f.mp3"],
|
|
||||||
stageWaitingURL: ["e23b4d3cf753989097f4.mp3"],
|
|
||||||
streamEndedDetuneURL: ["9b12ba39365fff66dd95.mp3", "8f4bc39481c815b02e4c.mp3"],
|
|
||||||
streamStartedDetuneURL: ["d954d7bfa51d58a25610.mp3", "7868133f107297d09719.mp3"],
|
|
||||||
streamUserJoinedDetuneURL: ["e9fa25653b507623acbd.mp3", "5320b9eae726f7c7b3f5.mp3"],
|
|
||||||
streamUserLeftDetuneURL: ["0fdb31ebfdaf7e86e7ff.mp3", "b45e91a78a4377b853b8.mp3"],
|
|
||||||
successURL: ["1cc608397adb2bb151de.mp3"],
|
|
||||||
undeafenDetuneURL: ["2f7089b0d3e66e7d6d67.mp3", "c87a93fd4b6918f21b8d.mp3"],
|
|
||||||
unmuteDetuneURL: ["80f50a0752b5cd6028ac.mp3", "1bf3e7ad8588f290f1d8.mp3"],
|
|
||||||
userJoinDetuneURL: ["93034ac8d9eba50e3354.mp3", "376a8b2b79947dabac6d.mp3"],
|
|
||||||
userLeaveDetuneURL: ["fea7a918aecf33a04116.mp3", "9ea3b5ecbcad19a243e6.mp3"],
|
|
||||||
userMovedDetuneURL: ["e490f52f12a18334ae94.mp3", "af380400eb22d2fa80dc.mp3"],
|
|
||||||
vibingWumpusURL: ["38b1c58d275e828aa9b6.mp3"]
|
|
||||||
};
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
|
||||||
discodoDetuneURL: {
|
|
||||||
description: "Audio URL for discodo sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "https://www.myinstants.com/media/sounds/explosion-m.mp3",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
activitiesRocketTimeURL: {
|
|
||||||
description: "Audio URL for activities rocket time sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
activityEndURL: {
|
|
||||||
description: "Audio URL for activity end sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
activityLaunchURL: {
|
|
||||||
description: "Audio URL for activity launch sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
activityUserJoinURL: {
|
|
||||||
description: "Audio URL for activity user join sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
activityUserLeftURL: {
|
|
||||||
description: "Audio URL for activity user left sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
asmrMessage1URL: {
|
|
||||||
description: "Audio URL for asmr message1 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
bitMessage1URL: {
|
|
||||||
description: "Audio URL for bit message1 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
bopMessage1URL: {
|
|
||||||
description: "Audio URL for bop message1 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
callCallingURL: {
|
|
||||||
description: "Audio URL for call calling sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
callRingingURL: {
|
|
||||||
description: "Audio URL for call ringing sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
callRingingBeatURL: {
|
|
||||||
description: "Audio URL for call ringing beat sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
callRingingHalloweenURL: {
|
|
||||||
description: "Audio URL for call ringing halloween sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
callRingingSnowHalationURL: {
|
|
||||||
description: "Audio URL for call ringing snow halation sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
callRingingSnowsgivingURL: {
|
|
||||||
description: "Audio URL for call ringing snowsgiving sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
clipErrorURL: {
|
|
||||||
description: "Audio URL for clip error sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
clipSaveURL: {
|
|
||||||
description: "Audio URL for clip save sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
ddrDownURL: {
|
|
||||||
description: "Audio URL for ddr down sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
ddrLeftURL: {
|
|
||||||
description: "Audio URL for ddr left sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
ddrRightURL: {
|
|
||||||
description: "Audio URL for ddr right sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
ddrUpURL: {
|
|
||||||
description: "Audio URL for ddr up sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
deafenURL: {
|
|
||||||
description: "Audio URL for deafen sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
disconnectDetuneURL: {
|
|
||||||
description: "Audio URL for disconnect sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
duckyMessage1URL: {
|
|
||||||
description: "Audio URL for ducky message1 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
hangStatusSelectURL: {
|
|
||||||
description: "Audio URL for hang status select sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
highfiveClapURL: {
|
|
||||||
description: "Audio URL for highfive clap sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
highfiveWhistleURL: {
|
|
||||||
description: "Audio URL for highfive whistle sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
humanManURL: {
|
|
||||||
description: "Audio URL for human man sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
lofiMessage1URL: {
|
|
||||||
description: "Audio URL for lofi message1 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
mention1URL: {
|
|
||||||
description: "Audio URL for mention1 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
mention2URL: {
|
|
||||||
description: "Audio URL for mention2 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
mention3URL: {
|
|
||||||
description: "Audio URL for mention3 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
message2URL: {
|
|
||||||
description: "Audio URL for message2 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
message3URL: {
|
|
||||||
description: "Audio URL for message3 sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
muteDetuneURL: {
|
|
||||||
description: "Audio URL for mute sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
overlayunlockURL: {
|
|
||||||
description: "Audio URL for overlay unlock sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
poggermodeAchievementUnlockURL: {
|
|
||||||
description: "Audio URL for poggermode achievement unlock sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
poggermodeApplauseURL: {
|
|
||||||
description: "Audio URL for poggermode applause sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
poggermodeEnabledURL: {
|
|
||||||
description: "Audio URL for poggermode enabled sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
poggermodeMessageSendURL: {
|
|
||||||
description: "Audio URL for poggermode message send sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
pttStartDetuneURL: {
|
|
||||||
description: "Audio URL for ptt start sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
pttStopDetuneURL: {
|
|
||||||
description: "Audio URL for ptt stop sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
reconnectURL: {
|
|
||||||
description: "Audio URL for reconnect sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
robotManURL: {
|
|
||||||
description: "Audio URL for robot man sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
stageWaitingURL: {
|
|
||||||
description: "Audio URL for stage waiting sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
successURL: {
|
|
||||||
description: "Audio URL for success sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
},
|
|
||||||
vibingWumpusURL: {
|
|
||||||
description: "Audio URL for vibing wumpus sound",
|
|
||||||
type: OptionType.STRING,
|
|
||||||
default: "",
|
|
||||||
restartNeeded: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function getSoundURL(settingKey: string) {
|
|
||||||
const url = settings.store[settingKey];
|
|
||||||
const knownAudioExtensions = [".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a"];
|
|
||||||
|
|
||||||
const isValidURL = (url: string) => {
|
|
||||||
try {
|
|
||||||
new URL(url);
|
|
||||||
return true;
|
|
||||||
} catch (_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const hasValidExtension = (url: string) => {
|
|
||||||
return knownAudioExtensions.some(ext => url.toLowerCase().endsWith(ext));
|
|
||||||
};
|
|
||||||
|
|
||||||
const addHttpsIfMissing = (url: string) => {
|
|
||||||
if (!/^https?:\/\//i.test(url)) {
|
|
||||||
return `https://${url}`;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
};
|
|
||||||
|
|
||||||
const correctedURL = addHttpsIfMissing(url);
|
|
||||||
|
|
||||||
if (correctedURL && isValidURL(correctedURL) && hasValidExtension(correctedURL)) {
|
|
||||||
return correctedURL;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default definePlugin({
|
|
||||||
name: "CustomSounds",
|
|
||||||
description: "Replace Discord sounds with a custom ones",
|
|
||||||
authors: [Devs.ScattrdBlade],
|
|
||||||
settings,
|
|
||||||
patches: Object.keys(soundFileMapping).flatMap(settingKey =>
|
|
||||||
soundFileMapping[settingKey].map(file => ({
|
|
||||||
find: file,
|
|
||||||
replacement: {
|
|
||||||
match: /e\.exports\s*=\s*n\.p\s*\+\s*"[a-zA-Z0-9]+\.(mp3|wav|ogg|flac|aac|m4a)"/,
|
|
||||||
replace: () => `e.exports="${getSoundURL(settingKey)}"`
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
});
|
|
89
src/equicordplugins/customSounds/index.tsx
Normal file
89
src/equicordplugins/customSounds/index.tsx
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./styles.css";
|
||||||
|
|
||||||
|
import { DataStore } from "@api/index";
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { Devs, EquicordDevs } from "@utils/constants";
|
||||||
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
import { React } from "@webpack/common";
|
||||||
|
|
||||||
|
import { SoundOverrideComponent } from "./components/SoundOverrideComponent";
|
||||||
|
import { makeEmptyOverride, SoundOverride, soundTypes } from "./types";
|
||||||
|
|
||||||
|
const OVERRIDES_KEY = "CustomSounds_overrides";
|
||||||
|
let overrides: Record<string, SoundOverride> = soundTypes.reduce((result, sound) => ({ ...result, [sound.id]: makeEmptyOverride() }), {});
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
overrides: {
|
||||||
|
type: OptionType.COMPONENT,
|
||||||
|
description: "",
|
||||||
|
component: () =>
|
||||||
|
<>
|
||||||
|
{soundTypes.map(type =>
|
||||||
|
<SoundOverrideComponent
|
||||||
|
key={type.id}
|
||||||
|
type={type}
|
||||||
|
override={overrides[type.id]}
|
||||||
|
onChange={() => DataStore.set(OVERRIDES_KEY, overrides)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export function isOverriden(id: string): boolean {
|
||||||
|
return overrides[id]?.enabled ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findOverride(id: string): SoundOverride | null {
|
||||||
|
const result = overrides[id];
|
||||||
|
if (!result?.enabled)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "CustomSounds",
|
||||||
|
description: "Replace Discord's sounds with your own.",
|
||||||
|
authors: [Devs.TheKodeToad, EquicordDevs.SpikeHD],
|
||||||
|
patches: [
|
||||||
|
// sound class
|
||||||
|
{
|
||||||
|
find: 'Error("could not play audio")',
|
||||||
|
replacement: [
|
||||||
|
// override URL
|
||||||
|
{
|
||||||
|
match: /(?<=new Audio;\i\.src=)\i\([0-9]+\)\("\.\/"\.concat\(this\.name,"\.mp3"\)/,
|
||||||
|
replace: "$self.findOverride(this.name)?.url || $&"
|
||||||
|
},
|
||||||
|
// override volume
|
||||||
|
{
|
||||||
|
match: /Math.min\(\i\.\i\.getOutputVolume\(\)\/100\*this\._volume/,
|
||||||
|
replace: "$& * ($self.findOverride(this.name)?.volume ?? 100) / 100"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// force classic soundpack for overriden sounds
|
||||||
|
{
|
||||||
|
find: ".playWithListener().then",
|
||||||
|
replacement: {
|
||||||
|
match: /\i\.\i\.getSoundpack\(\)/,
|
||||||
|
replace: '$self.isOverriden(arguments[0]) ? "classic" : $&'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
settings,
|
||||||
|
findOverride,
|
||||||
|
isOverriden,
|
||||||
|
async start() {
|
||||||
|
overrides = await DataStore.get(OVERRIDES_KEY) ?? {};
|
||||||
|
for (const type of soundTypes)
|
||||||
|
overrides[type.id] ??= makeEmptyOverride();
|
||||||
|
}
|
||||||
|
});
|
11
src/equicordplugins/customSounds/styles.css
Normal file
11
src/equicordplugins/customSounds/styles.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.vc-custom-sounds-card {
|
||||||
|
padding: 1em 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-custom-sounds-id {
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-custom-sounds-upload {
|
||||||
|
display: inline;
|
||||||
|
}
|
57
src/equicordplugins/customSounds/types.ts
Normal file
57
src/equicordplugins/customSounds/types.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface SoundType {
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SoundOverride {
|
||||||
|
enabled: boolean;
|
||||||
|
url: string;
|
||||||
|
volume: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SoundPlayer {
|
||||||
|
loop(): void;
|
||||||
|
play(): void;
|
||||||
|
pause(): void;
|
||||||
|
stop(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const soundTypes: readonly SoundType[] = [
|
||||||
|
{ name: "Message", id: "message1" },
|
||||||
|
{ name: "Message (Focused Channel)", id: "message3" },
|
||||||
|
{ name: "Defean", id: "deafen" },
|
||||||
|
{ name: "Undefean", id: "undeafen" },
|
||||||
|
{ name: "Mute", id: "mute" },
|
||||||
|
{ name: "Unmute", id: "unmute" },
|
||||||
|
{ name: "Voice Disconnected", id: "disconnect" },
|
||||||
|
{ name: "PTT Activate", id: "ptt_start" },
|
||||||
|
{ name: "PTT Deactive", id: "ptt_stop" },
|
||||||
|
{ name: "User Join", id: "user_join" },
|
||||||
|
{ name: "User Leave", id: "user_leave" },
|
||||||
|
{ name: "User Moved", id: "user_moved" },
|
||||||
|
{ name: "Outgoing Ring", id: "call_calling" },
|
||||||
|
{ name: "Incoming Ring", id: "call_ringing" },
|
||||||
|
{ name: "Stream Started", id: "stream_started" },
|
||||||
|
{ name: "Stream Ended", id: "stream_ended" },
|
||||||
|
{ name: "Viewer Join", id: "stream_user_joined" },
|
||||||
|
{ name: "Viewer Leave", id: "stream_user_left" },
|
||||||
|
{ name: "Activity Start", id: "activity_launch" },
|
||||||
|
{ name: "Activity End", id: "activity_end" },
|
||||||
|
{ name: "Activity User Join", id: "activity_user_join" },
|
||||||
|
{ name: "Activity User Leave", id: "activity_user_left" },
|
||||||
|
{ name: "Invited to Speak", id: "reconnect" }
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function makeEmptyOverride(): SoundOverride {
|
||||||
|
return {
|
||||||
|
enabled: false,
|
||||||
|
url: "",
|
||||||
|
volume: 100
|
||||||
|
};
|
||||||
|
}
|
|
@ -40,6 +40,48 @@ const settings = definePluginSettings({
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
description: "Toggle functionality",
|
description: "Toggle functionality",
|
||||||
default: true,
|
default: true,
|
||||||
|
},
|
||||||
|
blockAllTypingIndicators: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Toggle functionality on all typing indicators on avatars",
|
||||||
|
default: false,
|
||||||
|
restartNeeded: true
|
||||||
|
},
|
||||||
|
blockAllIsTyping: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Toggle functionality on all 'Is Typing...'",
|
||||||
|
default: false,
|
||||||
|
restartNeeded: true
|
||||||
|
},
|
||||||
|
oldBlockAllTypingIndicators: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Toggle functionality on all 'Is Typing...'",
|
||||||
|
default: false,
|
||||||
|
restartNeeded: true,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
oldBlockAllIsTyping: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Toggle functionality on all 'Is Typing...'",
|
||||||
|
default: false,
|
||||||
|
restartNeeded: true,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
blockEverything: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Toggle functionality on Everything",
|
||||||
|
default: false,
|
||||||
|
restartNeeded: true,
|
||||||
|
onChange: (value: boolean) => {
|
||||||
|
settings.store.oldBlockAllTypingIndicators = settings.store.blockAllTypingIndicators;
|
||||||
|
settings.store.oldBlockAllIsTyping = settings.store.blockAllIsTyping;
|
||||||
|
if (!value) {
|
||||||
|
settings.store.blockAllTypingIndicators = settings.store.oldBlockAllTypingIndicators;
|
||||||
|
settings.store.blockAllIsTyping = settings.store.oldBlockAllIsTyping;
|
||||||
|
}
|
||||||
|
settings.store.blockAllTypingIndicators = value;
|
||||||
|
settings.store.blockAllIsTyping = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -83,7 +125,6 @@ const ChatBarContextCheckbox: NavContextMenuPatchCallback = children => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "SilentTyping",
|
name: "SilentTyping",
|
||||||
authors: [Devs.Ven, Devs.Rini, Devs.ImBanana],
|
authors: [Devs.Ven, Devs.Rini, Devs.ImBanana],
|
||||||
|
@ -101,6 +142,30 @@ export default definePlugin({
|
||||||
replace: "startTyping:$self.startTyping,stop"
|
replace: "startTyping:$self.startTyping,stop"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
find: "isTyping:",
|
||||||
|
all: true,
|
||||||
|
noWarn: true,
|
||||||
|
replacement: {
|
||||||
|
match: /isTyping:.+?([,}].*?\))/g,
|
||||||
|
replace: (m, rest) => {
|
||||||
|
const destructuringMatch = rest.match(/}=.+/);
|
||||||
|
if (destructuringMatch == null) return `isTyping:!1${rest}`;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
predicate: () => settings.store.blockAllTypingIndicators
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "getTypingUsers(",
|
||||||
|
all: true,
|
||||||
|
noWarn: true,
|
||||||
|
replacement: {
|
||||||
|
match: /getTypingUsers\(.*?\)/,
|
||||||
|
replace: "getTypingUsers()"
|
||||||
|
},
|
||||||
|
predicate: () => settings.store.blockAllIsTyping
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
commands: [{
|
commands: [{
|
||||||
|
@ -128,6 +193,8 @@ export default definePlugin({
|
||||||
FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId });
|
FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId });
|
||||||
},
|
},
|
||||||
|
|
||||||
start: () => addChatBarButton("SilentTyping", SilentTypingToggle),
|
start: () => {
|
||||||
|
addChatBarButton("SilentTyping", SilentTypingToggle);
|
||||||
|
},
|
||||||
stop: () => removeChatBarButton("SilentTyping"),
|
stop: () => removeChatBarButton("SilentTyping"),
|
||||||
});
|
});
|
||||||
|
|
|
@ -779,6 +779,10 @@ export const EquicordDevs = Object.freeze({
|
||||||
name: "vMohammad",
|
name: "vMohammad",
|
||||||
id: 921098159348924457n
|
id: 921098159348924457n
|
||||||
},
|
},
|
||||||
|
SpikeHD: {
|
||||||
|
name: "SpikeHD",
|
||||||
|
id: 221757857836564485n
|
||||||
|
}
|
||||||
} satisfies Record<string, Dev>);
|
} satisfies Record<string, Dev>);
|
||||||
|
|
||||||
// iife so #__PURE__ works correctly
|
// iife so #__PURE__ works correctly
|
||||||
|
|
Loading…
Add table
Reference in a new issue