diff --git a/src/equicordplugins/keyboardSounds/index.ts b/src/equicordplugins/keyboardSounds/index.ts
index f9217c0b3..14c8018ff 100644
--- a/src/equicordplugins/keyboardSounds/index.ts
+++ b/src/equicordplugins/keyboardSounds/index.ts
@@ -1,63 +1,106 @@
/*
- * Vencord, a modification for Discord's desktop app
- * Copyright (c) 2022 Vendicated and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
+ * 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 } from "@utils/constants";
+import { Devs, EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
-import { ignoredKeys } from "./packs";
+import { ignoredKeys, packs } from "./packs";
-let backspace: AudioPlayerInterface;
-let clicks: Array<{ playing: boolean; player: AudioPlayerInterface; }> = [];
+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();
-let previousSoundIndex = 0;
const keyup = (e: KeyboardEvent) => { keysCurrentlyPressed.delete(e.code); };
const keydown = (e: KeyboardEvent) => {
- if (ignoredKeys.includes(e.code)) return;
- if (!clicks.length || !backspace) return;
+ if (!chosenPack) return;
+ if (ignoredKeys.includes(e.code) && !chosenPack.allowedIgnored?.includes(e.key)) return;
if (keysCurrentlyPressed.has(e.code)) return;
keysCurrentlyPressed.add(e.code);
- if (e.code === "Backspace") {
- backspace.restart();
- } else {
- const nonplayingClicks = clicks.filter(click => !click.playing);
- const randomIndex = Math.floor(Math.random() * nonplayingClicks.length);
- const chosenClick = nonplayingClicks.length ? nonplayingClicks[randomIndex] : clicks[previousSoundIndex];
- previousSoundIndex = randomIndex;
- chosenClick.playing = true;
- chosenClick.player.restart();
+ 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 assignSounds(volume: number) {
- backspace = createAudioPlayer("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/backspace.wav", { volume, preload: true, persistent: true });
- clicks = [];
+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] = []; });
+}
- for (let i = 0; i < 3; i++) {
- const baseIndex = i * 3;
- clicks.push({ playing: false, player: createAudioPlayer("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click1.wav", { volume, preload: true, persistent: true, onEnded: () => { clicks[baseIndex].playing = false; } }) });
- clicks.push({ playing: false, player: createAudioPlayer("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click2.wav", { volume, preload: true, persistent: true, onEnded: () => { clicks[baseIndex + 1].playing = false; } }) });
- clicks.push({ playing: false, player: createAudioPlayer("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click3.wav", { volume, preload: true, persistent: true, onEnded: () => { clicks[baseIndex + 2].playing = false; } }) });
+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({
@@ -67,23 +110,32 @@ const settings = definePluginSettings({
markers: [0, 25, 50, 75, 100],
stickToMarkers: false,
default: 100,
- onChange: value => { assignSounds(value); }
+ 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 the Opera GX Keyboard Sounds to Discord",
- authors: [Devs.HypedDomi],
+ 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);
+ assignSounds(settings.store.volume, settings.store.soundPack);
document.addEventListener("keyup", keyup);
document.addEventListener("keydown", keydown);
},
stop: () => {
- [...clicks, { player: backspace }].forEach(sound => sound.player.delete());
+ clearSounds();
document.removeEventListener("keyup", keyup);
document.removeEventListener("keydown", keydown);
},
diff --git a/src/equicordplugins/keyboardSounds/packs.ts b/src/equicordplugins/keyboardSounds/packs.ts
index 378971eb7..8eb839fa6 100644
--- a/src/equicordplugins/keyboardSounds/packs.ts
+++ b/src/equicordplugins/keyboardSounds/packs.ts
@@ -5,23 +5,36 @@
*/
export const packs = {
- "OperaGX": {
- click1: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click1.wav"),
- click2: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click2.wav"),
- click3: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click3.wav"),
- backspace: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/backspace.wav"),
- allowedKeys: []
+ "operagx": {
+ others: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click1.wav",
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click2.wav",
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/click3.wav"
+ ],
+ backspaces: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/operagx/backspace.wav"
+ ]
},
"osu": {
- caps: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-caps.mp3"),
- enter: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-confirm.mp3"),
- backspace: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-delete.mp3"),
- arrow: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-movement.mp3"),
- click1: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-1.mp3"),
- click2: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-2.mp3"),
- click3: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-3.mp3"),
- click4: new Audio("https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-4.mp3"),
- allowedKeys: [
+ others: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-1.mp3",
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-2.mp3",
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-3.mp3",
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-press-4.mp3"
+ ],
+ backspaces: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-delete.mp3"
+ ],
+ caps: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-caps.mp3"
+ ],
+ enters: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-confirm.mp3"
+ ],
+ arrows: [
+ "https://github.com/Equicord/Equibored/raw/main/sounds/keyboardSounds/osu/key-movement.mp3"
+ ],
+ allowedIgnored: [
"CapsLock",
"ArrowUp",
"ArrowRight",
@@ -29,7 +42,14 @@ export const packs = {
"ArrowDown"
]
}
-};
+} as Record<"operagx" | "osu", {
+ others: string[];
+ backspaces: string[];
+ caps?: string[];
+ enters?: string[];
+ arrows?: string[];
+ allowedIgnored?: string[];
+}>;
export const ignoredKeys = [
"CapsLock",