mirror of
https://github.com/Equicord/Equicord.git
synced 2025-02-21 15:48:52 -05:00
Add Block Typing To SilentTyping
This commit is contained in:
parent
a27c1cc163
commit
9cc0531ae1
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
|
||||
- CommandPalette by Ethan
|
||||
- CopyUserMention by Cortex and castdrian
|
||||
- CustomSounds by ScattrdBlade
|
||||
- CustomSounds by TheKodeToad and SpikeHD
|
||||
- CuteAnimeBoys by ShadyGoat
|
||||
- CuteNekos by echo
|
||||
- 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,
|
||||
description: "Toggle functionality",
|
||||
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({
|
||||
name: "SilentTyping",
|
||||
authors: [Devs.Ven, Devs.Rini, Devs.ImBanana],
|
||||
|
@ -101,6 +142,30 @@ export default definePlugin({
|
|||
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: [{
|
||||
|
@ -128,6 +193,8 @@ export default definePlugin({
|
|||
FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId });
|
||||
},
|
||||
|
||||
start: () => addChatBarButton("SilentTyping", SilentTypingToggle),
|
||||
start: () => {
|
||||
addChatBarButton("SilentTyping", SilentTypingToggle);
|
||||
},
|
||||
stop: () => removeChatBarButton("SilentTyping"),
|
||||
});
|
||||
|
|
|
@ -779,6 +779,10 @@ export const EquicordDevs = Object.freeze({
|
|||
name: "vMohammad",
|
||||
id: 921098159348924457n
|
||||
},
|
||||
SpikeHD: {
|
||||
name: "SpikeHD",
|
||||
id: 221757857836564485n
|
||||
}
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
// iife so #__PURE__ works correctly
|
||||
|
|
Loading…
Add table
Reference in a new issue