mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-20 07:16:17 +08:00
impr(sound): add support for various error sounds (W0LFB0MB) (#4679)
* Add files via upload * Delete frontend/static/sound/error/triangle.wav * Delete frontend/static/sound/error/damage.wav * modified error sound code to support multiple sound options and added two error sound alternatives * added compatability for previous users of the error sound, converts legacy true/false config values to 1 or off * fixed opiton names and values in commandline * fix: auto switch theme behavior & footer theme indicator (#4677) * fix: auto switch theme behavior & footer indicator Changing manually to a preset or custom theme now turns auto switch theme mode off with a notification. And now the auto switch mode does override the custom theme as well (statement in settings also updated) if it is the later one set. Fixes #4659, that is the footer theme is now correctly displayed with auto switch themes as well. * removed unnecessary function --------- Co-authored-by: Miodec <jack@monkeytype.com> * fixed off config value * moved compatibilty code to replaceLegacyValues --------- Co-authored-by: Sanidhya Singh <sanidhyas3s@gmail.com> Co-authored-by: Miodec <jack@monkeytype.com>
This commit is contained in:
parent
426694afa1
commit
fa01558876
|
@ -88,7 +88,7 @@ const CONFIG_SCHEMA = joi.object({
|
|||
alwaysShowWordsHistory: joi.boolean(),
|
||||
singleListCommandLine: joi.string().valid("manual", "on"),
|
||||
capsLockWarning: joi.boolean(),
|
||||
playSoundOnError: joi.boolean(),
|
||||
playSoundOnError: joi.string().valid("off", ..._.range(1, 4).map(_.toString)),
|
||||
playSoundOnClick: joi
|
||||
.string()
|
||||
.valid("off", ..._.range(1, 14).map(_.toString)),
|
||||
|
|
|
@ -8,17 +8,35 @@ const subgroup: MonkeyTypes.CommandsSubgroup = {
|
|||
{
|
||||
id: "setPlaySoundOnErrorOff",
|
||||
display: "off",
|
||||
configValue: false,
|
||||
configValue: "off",
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnError(false);
|
||||
UpdateConfig.setPlaySoundOnError("off");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setPlaySoundOnErrorOn",
|
||||
display: "on",
|
||||
configValue: true,
|
||||
id: "setPlaySoundOnError1",
|
||||
display: "damage",
|
||||
configValue: "1",
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnError(true);
|
||||
UpdateConfig.setPlaySoundOnError("1");
|
||||
SoundController.playError();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setPlaySoundOnError2",
|
||||
display: "triangle",
|
||||
configValue: "2",
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnError("2");
|
||||
SoundController.playError();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setPlaySoundOnError3",
|
||||
display: "square",
|
||||
configValue: "3",
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnError("3");
|
||||
SoundController.playError();
|
||||
},
|
||||
},
|
||||
|
|
|
@ -137,8 +137,13 @@ export function setMode(mode: MonkeyTypes.Mode, nosave?: boolean): boolean {
|
|||
return true;
|
||||
}
|
||||
|
||||
export function setPlaySoundOnError(val: boolean, nosave?: boolean): boolean {
|
||||
if (!isConfigValueValid("play sound on error", val, ["boolean"])) {
|
||||
export function setPlaySoundOnError(
|
||||
val: MonkeyTypes.PlaySoundOnError,
|
||||
nosave?: boolean
|
||||
): boolean {
|
||||
if (
|
||||
!isConfigValueValid("play sound on error", val, [["off", "1", "2", "3"]])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1985,6 +1990,10 @@ function replaceLegacyValues(
|
|||
configObj.showAverage = "speed";
|
||||
}
|
||||
|
||||
if (typeof configObj.playSoundOnError === "boolean") {
|
||||
configObj.playSoundOnError = configObj.playSoundOnError ? "1" : "off";
|
||||
}
|
||||
|
||||
return configObj;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ export default <MonkeyTypes.Config>{
|
|||
alwaysShowWordsHistory: false,
|
||||
singleListCommandLine: "manual",
|
||||
capsLockWarning: true,
|
||||
playSoundOnError: false,
|
||||
playSoundOnError: "off",
|
||||
playSoundOnClick: "off",
|
||||
soundVolume: "0.5",
|
||||
startGraphsAtZero: true,
|
||||
|
|
|
@ -216,7 +216,7 @@ function handleSpace(): void {
|
|||
}
|
||||
} else {
|
||||
if (!nospace) {
|
||||
if (!Config.playSoundOnError || Config.blindMode) {
|
||||
if (Config.playSoundOnError === "off" || Config.blindMode) {
|
||||
Sound.playClick();
|
||||
} else {
|
||||
Sound.playError();
|
||||
|
@ -550,7 +550,7 @@ function handleChar(
|
|||
if (thisCharCorrect) {
|
||||
Sound.playClick();
|
||||
} else {
|
||||
if (!Config.playSoundOnError || Config.blindMode) {
|
||||
if (Config.playSoundOnError === "off" || Config.blindMode) {
|
||||
Sound.playClick();
|
||||
} else {
|
||||
Sound.playError();
|
||||
|
|
|
@ -17,12 +17,47 @@ interface ClickSounds {
|
|||
}[];
|
||||
}
|
||||
|
||||
let errorSound: Howler.Howl | null = null;
|
||||
interface ErrorSounds {
|
||||
[key: string]: {
|
||||
sounds: Howler.Howl[];
|
||||
counter: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
let errorSounds: ErrorSounds | null = null;
|
||||
let clickSounds: ClickSounds | null = null;
|
||||
|
||||
function initErrorSound(): void {
|
||||
if (errorSound !== null) return;
|
||||
errorSound = new Howl({ src: ["../sound/error.wav"] });
|
||||
if (errorSounds !== null) return;
|
||||
errorSounds = {
|
||||
1: [
|
||||
{
|
||||
sounds: [
|
||||
new Howl({ src: "../sound/error1/error1_1.wav" }),
|
||||
new Howl({ src: "../sound/error1/error1_1.wav" }),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
],
|
||||
2: [
|
||||
{
|
||||
sounds: [
|
||||
new Howl({ src: "../sound/error2/error2_1.wav" }),
|
||||
new Howl({ src: "../sound/error2/error2_1.wav" }),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
],
|
||||
3: [
|
||||
{
|
||||
sounds: [
|
||||
new Howl({ src: "../sound/error3/error3_1.wav" }),
|
||||
new Howl({ src: "../sound/error3/error3_1.wav" }),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function init(): void {
|
||||
|
@ -504,10 +539,17 @@ export function playClick(codeOverride?: string): void {
|
|||
}
|
||||
|
||||
export function playError(): void {
|
||||
if (!Config.playSoundOnError) return;
|
||||
if (errorSound === null) initErrorSound();
|
||||
(errorSound as Howler.Howl).seek(0);
|
||||
(errorSound as Howler.Howl).play();
|
||||
if (Config.playSoundOnError === "off") return;
|
||||
if (errorSounds === null) initErrorSound();
|
||||
|
||||
const randomSound = randomElementFromArray(
|
||||
(errorSounds as ErrorSounds)[Config.playSoundOnError]
|
||||
);
|
||||
|
||||
randomSound.counter++;
|
||||
if (randomSound.counter === 2) randomSound.counter = 0;
|
||||
randomSound.sounds[randomSound.counter].seek(0);
|
||||
randomSound.sounds[randomSound.counter].play();
|
||||
}
|
||||
|
||||
function setVolume(val: number): void {
|
||||
|
|
|
@ -251,7 +251,7 @@ async function initGroups(): Promise<void> {
|
|||
UpdateConfig.setPlaySoundOnError,
|
||||
"button",
|
||||
() => {
|
||||
if (Config.playSoundOnError) Sound.playError();
|
||||
if (Config.playSoundOnError !== "off") Sound.playError();
|
||||
}
|
||||
) as SettingsGroup<MonkeyTypes.ConfigValues>;
|
||||
groups["playSoundOnClick"] = new SettingsGroup(
|
||||
|
|
|
@ -87,7 +87,7 @@ export function pauseReplay(): void {
|
|||
|
||||
function playSound(error = false): void {
|
||||
if (error) {
|
||||
if (config.playSoundOnError) {
|
||||
if (config.playSoundOnError !== "off") {
|
||||
Sound.playError();
|
||||
} else {
|
||||
Sound.playClick();
|
||||
|
|
4
frontend/src/ts/types/types.d.ts
vendored
4
frontend/src/ts/types/types.d.ts
vendored
|
@ -138,6 +138,8 @@ declare namespace MonkeyTypes {
|
|||
| "12"
|
||||
| "13";
|
||||
|
||||
type PlaySoundOnError = "off" | "1" | "2" | "3";
|
||||
|
||||
type SoundVolume = "0.1" | "0.5" | "1.0";
|
||||
|
||||
type PaceCaret = "off" | "average" | "pb" | "last" | "custom" | "daily";
|
||||
|
@ -470,7 +472,7 @@ declare namespace MonkeyTypes {
|
|||
alwaysShowWordsHistory: boolean;
|
||||
singleListCommandLine: SingleListCommandLine;
|
||||
capsLockWarning: boolean;
|
||||
playSoundOnError: boolean;
|
||||
playSoundOnError: PlaySoundOnError;
|
||||
playSoundOnClick: PlaySoundOnClick;
|
||||
soundVolume: SoundVolume;
|
||||
startGraphsAtZero: boolean;
|
||||
|
|
|
@ -1041,7 +1041,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section playSoundOnError">
|
||||
<div class="section playSoundOnError fullWidth">
|
||||
<div class="groupTitle">
|
||||
<i class="fas fa-volume-mute"></i>
|
||||
<span>play sound on error</span>
|
||||
|
@ -1053,7 +1053,7 @@
|
|||
<div class="buttons">
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnError="false"
|
||||
playSoundOnError="off"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
|
@ -1061,11 +1061,27 @@
|
|||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnError="true"
|
||||
playSoundOnError="1"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
on
|
||||
damage
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnError="2"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
triangle
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnError="3"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
square
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
BIN
frontend/static/sound/error2/error2_1.wav
Normal file
BIN
frontend/static/sound/error2/error2_1.wav
Normal file
Binary file not shown.
BIN
frontend/static/sound/error3/error3_1.wav
Normal file
BIN
frontend/static/sound/error3/error3_1.wav
Normal file
Binary file not shown.
Loading…
Reference in a new issue