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:
W0LFB0MB 2023-10-02 16:09:30 +01:00 committed by GitHub
parent 426694afa1
commit fa01558876
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 113 additions and 26 deletions

View file

@ -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)),

View file

@ -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();
},
},

View file

@ -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;
}

View file

@ -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,

View file

@ -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();

View file

@ -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 {

View file

@ -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(

View file

@ -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();

View file

@ -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;

View file

@ -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>

Binary file not shown.

Binary file not shown.