Equicord/src/equicordplugins/keyboardSounds/index.ts
Etorix 60dcdc966b
keyboardSounds: Add osu! and update structure. (#407)
* Add osu and update structure.

* Fixes.
2025-09-20 15:07:04 -04:00

142 lines
4.9 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { AudioPlayerInterface, createAudioPlayer } from "@api/AudioPlayer";
import { definePluginSettings } from "@api/Settings";
import { Devs, EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { ignoredKeys, packs } from "./packs";
const allSounds = {
backspaces: [] as { playing: boolean; player: AudioPlayerInterface; }[],
caps: [] as { playing: boolean; player: AudioPlayerInterface; }[],
enters: [] as { playing: boolean; player: AudioPlayerInterface; }[],
arrows: [] as { playing: boolean; player: AudioPlayerInterface; }[],
others: [] as { playing: boolean; player: AudioPlayerInterface; }[]
};
let chosenPack: typeof packs[keyof typeof packs];
const keysCurrentlyPressed = new Set<string>();
const keyup = (e: KeyboardEvent) => { keysCurrentlyPressed.delete(e.code); };
const keydown = (e: KeyboardEvent) => {
if (!chosenPack) return;
if (ignoredKeys.includes(e.code) && !chosenPack.allowedIgnored?.includes(e.key)) return;
if (keysCurrentlyPressed.has(e.code)) return;
keysCurrentlyPressed.add(e.code);
function getRandomSound(soundsArray: { playing: boolean; player: AudioPlayerInterface; }[]) {
const nonplayingSounds = soundsArray.filter(sound => !sound?.playing);
let randomIndex;
let chosenSound;
if (nonplayingSounds.length) {
randomIndex = Math.floor(Math.random() * nonplayingSounds.length);
chosenSound = nonplayingSounds[randomIndex];
} else {
randomIndex = Math.floor(Math.random() * soundsArray.length);
chosenSound = soundsArray[randomIndex];
}
if (chosenSound) {
chosenSound.playing = true;
chosenSound.player.restart();
}
}
if (e.code === "Backspace" && allSounds.backspaces.length) {
getRandomSound(allSounds.backspaces);
} else if (e.code === "CapsLock" && allSounds.caps.length) {
getRandomSound(allSounds.caps);
} else if (e.code === "Enter" && allSounds.enters.length) {
getRandomSound(allSounds.enters);
} else if (["ArrowUp", "ArrowRight", "ArrowLeft", "ArrowDown"].includes(e.code) && allSounds.arrows.length) {
getRandomSound(allSounds.arrows);
} else if (allSounds.others.length) {
getRandomSound(allSounds.others);
}
};
function clearSounds() {
Array.from(Object.values(allSounds)).forEach(soundsArray => { soundsArray.forEach(sound => sound.player.delete()); });
Object.keys(allSounds).forEach(key => { allSounds[key as keyof typeof allSounds] = []; });
}
function assignSounds(volume: number, pack: "operagx" | "osu") {
clearSounds();
chosenPack = packs[pack];
if (!chosenPack) {
return;
}
function addSounds(key: keyof typeof allSounds) {
if (!chosenPack[key]) return;
let soundIndex = -1;
for (let i = 0; i < 3; i++) {
for (const url of chosenPack[key]) {
soundIndex++;
allSounds[key].push({
playing: false,
player: createAudioPlayer(url, {
volume,
preload: true,
persistent: true,
onEnded: () => { allSounds[key][soundIndex].playing = false; }
})
});
}
}
}
chosenPack.backspaces && addSounds("backspaces");
chosenPack.caps && addSounds("caps");
chosenPack.enters && addSounds("enters");
chosenPack.arrows && addSounds("arrows");
chosenPack.others && addSounds("others");
}
const settings = definePluginSettings({
volume: {
description: "Volume of the keyboard sounds.",
type: OptionType.SLIDER,
markers: [0, 25, 50, 75, 100],
stickToMarkers: false,
default: 100,
onChange: value => { assignSounds(value, settings.store.soundPack); }
},
soundPack: {
description: "Sound pack to use.",
type: OptionType.SELECT,
options: [
{ label: "OperaGX", value: "operagx" as "operagx", default: true },
{ label: "osu!", value: "osu" as "osu" }
],
onChange: value => { assignSounds(settings.store.volume, value); }
}
});
export default definePlugin({
name: "KeyboardSounds",
description: "Adds OperaGX or osu! sound effects when typing on your keyboard.",
authors: [Devs.HypedDomi, EquicordDevs.Etorix],
dependencies: ["AudioPlayerAPI"],
settings,
start() {
assignSounds(settings.store.volume, settings.store.soundPack);
document.addEventListener("keyup", keyup);
document.addEventListener("keydown", keydown);
},
stop: () => {
clearSounds();
document.removeEventListener("keyup", keyup);
document.removeEventListener("keydown", keydown);
},
});