impr(settings): replace sound volume with a slider (@amarnathsama) (#5702)

* replaced sound volume settings with a slider

* used SettingsGroup instead of custom class, minor css change

* use common structure, remove css

* notify if sound volume is out of range

* command input goes from 0 to 1

* fix test

---------

Co-authored-by: Jack <jack@monkeytype.com>
This commit is contained in:
amarnathsama 2024-08-03 00:45:40 +05:30 committed by GitHub
parent c791156848
commit 8c7ece3721
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 39 additions and 17 deletions

View file

@ -19,8 +19,8 @@ describe("Config", () => {
expect(Config.setPlaySoundOnClick("invalid" as any)).toBe(false);
});
it("setSoundVolume", () => {
expect(Config.setSoundVolume("0.1")).toBe(true);
expect(Config.setSoundVolume("1.0")).toBe(true);
expect(Config.setSoundVolume(0.1)).toBe(true);
expect(Config.setSoundVolume(1.0)).toBe(true);
expect(Config.setSoundVolume("invalid" as any)).toBe(false);
});
it("setDifficulty", () => {

View file

@ -581,10 +581,11 @@
<span>sound volume</span>
</div>
<div class="text">Change the volume of the sound effects.</div>
<div class="buttons">
<button data-config-value="0.1">quiet</button>
<button data-config-value="0.5">medium</button>
<button data-config-value="1.0">loud</button>
<div class="inputs">
<div class="rangeGroup">
<div class="value">100</div>
<input type="range" min="0" max="1" step="0.1" />
</div>
</div>
</div>
<div class="section fullWidth" data-config-name="playSoundOnClick">

View file

@ -10,7 +10,7 @@ const subgroup: MonkeyTypes.CommandsSubgroup = {
display: "quiet",
configValue: "0.1",
exec: (): void => {
UpdateConfig.setSoundVolume("0.1");
UpdateConfig.setSoundVolume(0.1);
void SoundController.playClick();
},
},
@ -19,7 +19,7 @@ const subgroup: MonkeyTypes.CommandsSubgroup = {
display: "medium",
configValue: "0.5",
exec: (): void => {
UpdateConfig.setSoundVolume("0.5");
UpdateConfig.setSoundVolume(0.5);
void SoundController.playClick();
},
},
@ -28,7 +28,17 @@ const subgroup: MonkeyTypes.CommandsSubgroup = {
display: "loud",
configValue: "1.0",
exec: (): void => {
UpdateConfig.setSoundVolume("1.0");
UpdateConfig.setSoundVolume(1.0);
void SoundController.playClick();
},
},
{
id: "setSoundVolumeCustom",
display: "custom...",
input: true,
exec: ({ input }): void => {
if (input === undefined || input === "") return;
UpdateConfig.setSoundVolume(parseFloat(input));
void SoundController.playClick();
},
},

View file

@ -182,6 +182,11 @@ export function setSoundVolume(
val: ConfigSchemas.SoundVolume,
nosave?: boolean
): boolean {
if (val < 0 || val > 1) {
Notifications.add("Sound volume must be between 0 and 1", 0);
val = 0.5;
}
if (
!isConfigValueValid("sound volume", val, ConfigSchemas.SoundVolumeSchema)
) {
@ -2176,6 +2181,10 @@ function replaceLegacyValues(
configObj.liveAccStyle = val;
}
if (typeof configObj.soundVolume === "string") {
configObj.soundVolume = parseFloat(configObj.soundVolume);
}
return configObj;
}

View file

@ -68,7 +68,7 @@ export default {
capsLockWarning: true,
playSoundOnError: "off",
playSoundOnClick: "off",
soundVolume: "0.5",
soundVolume: 0.5,
startGraphsAtZero: true,
showOutOfFocusWarning: true,
paceCaret: "off",

View file

@ -81,7 +81,7 @@ async function initErrorSound(): Promise<void> {
},
],
};
Howler.volume(parseFloat(Config.soundVolume));
Howler.volume(Config.soundVolume);
}
async function init(): Promise<void> {
@ -387,7 +387,7 @@ async function init(): Promise<void> {
},
],
};
Howler.volume(parseFloat(Config.soundVolume));
Howler.volume(Config.soundVolume);
}
export async function previewClick(val: string): Promise<void> {
@ -591,7 +591,7 @@ function playScale(scale: ValidScales, scaleMeta: ScaleData): void {
const gainNode = audioCtx.createGain();
oscillatorNode.type = "sine";
gainNode.gain.value = parseFloat(Config.soundVolume) / 10;
gainNode.gain.value = Config.soundVolume / 10;
oscillatorNode.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillatorNode.frequency.value = currentFrequency;
@ -626,7 +626,7 @@ export function playNote(
clickSoundIdsToOscillatorType[
Config.playSoundOnClick as DynamicClickSounds
];
gainNode.gain.value = parseFloat(Config.soundVolume) / 10;
gainNode.gain.value = Config.soundVolume / 10;
oscillatorNode.connect(gainNode);
gainNode.connect(audioCtx.destination);
@ -695,5 +695,7 @@ function setVolume(val: number): void {
ConfigEvent.subscribe((eventKey, eventValue) => {
if (eventKey === "playSoundOnClick" && eventValue !== "off") void init();
if (eventKey === "soundVolume") setVolume(parseFloat(eventValue as string));
if (eventKey === "soundVolume") {
setVolume(parseFloat(eventValue as string));
}
});

View file

@ -250,7 +250,7 @@ async function initGroups(): Promise<void> {
groups["soundVolume"] = new SettingsGroup(
"soundVolume",
UpdateConfig.setSoundVolume,
"button"
"range"
) as SettingsGroup<ConfigValue>;
groups["playSoundOnError"] = new SettingsGroup(
"playSoundOnError",

View file

@ -120,7 +120,7 @@ export const PlaySoundOnClickSchema = z.enum([
]);
export type PlaySoundOnClick = z.infer<typeof PlaySoundOnClickSchema>;
export const SoundVolumeSchema = z.enum(["0.1", "0.5", "1.0"]);
export const SoundVolumeSchema = z.number().min(0).max(1);
export type SoundVolume = z.infer<typeof SoundVolumeSchema>;
export const PaceCaretSchema = z.enum([