feat: Adding audio player + music to play
This commit is contained in:
+33
-5
@@ -8,6 +8,7 @@ import { encodeSave, decodeSave, migrate } from "../save/codec.js";
|
||||
import { KEYS, SLOT_COUNT, readSave, writeSave } from "../save/storage.js";
|
||||
import { $, esc } from "./desk.js";
|
||||
import { renderMarkdown } from "./markdown.js";
|
||||
import { MIX_GROUPS } from "./audio.js";
|
||||
|
||||
const ARM_MS = 4000; // how long a "Sure?" button stays armed
|
||||
|
||||
@@ -221,9 +222,7 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
<input type="checkbox" id="setting-sound" ${s.sound ? "checked" : ""}>
|
||||
<span><b>${t("settings.sound")}</b><small>${t("settings.soundHint")}</small></span>
|
||||
</label>
|
||||
<label class="menu__field">${t("settings.volume")}
|
||||
<input type="range" id="setting-volume" min="0" max="1" step="0.05" value="${s.volume}" ${s.sound ? "" : "disabled"}>
|
||||
</label>
|
||||
<div class="menu__list">${button("mixer", t("settings.mixer"))}</div>
|
||||
${storage.persistent ? "" : `<p class="menu__msg menu__msg--error">${t("settings.storage")}</p>`}
|
||||
${back()}`;
|
||||
}
|
||||
@@ -253,7 +252,26 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
return `<div class="rules" tabindex="0" aria-label="${t("rules.title")}">${html}</div>${back()}`;
|
||||
}
|
||||
|
||||
const SCREENS = { home, new: newGame, load, save, export: exportScreen, import: importScreen, settings, credits, rules };
|
||||
// One slider per sound group, plus the overall volume and the music. Levels apply as you drag.
|
||||
function mixer() {
|
||||
const s = getSettings();
|
||||
const rows = [["master", s.volume], ["music", s.mix.music], ...MIX_GROUPS.map((g) => [g, s.mix[g]])];
|
||||
return `
|
||||
<h3>${t("mixer.title")}</h3>
|
||||
<p class="menu__sub">${t("mixer.hint")}</p>
|
||||
<div class="mixer">
|
||||
${rows.map(([key, v]) => `
|
||||
<label class="mixer__row ${key === "master" ? "mixer__row--master" : ""}">
|
||||
<span>${t("mixer." + key)}</span>
|
||||
<input type="range" min="0" max="1" step="0.05" value="${v}" data-mix="${key}" aria-label="${t("mixer." + key)}">
|
||||
<output>${Math.round(v * 100)}%</output>
|
||||
</label>`).join("")}
|
||||
</div>
|
||||
<div class="menu__list">${button("mixerReset", t("mixer.reset"))}</div>
|
||||
<footer class="menu__foot">${button("settings", t("menu.back"))}</footer>`;
|
||||
}
|
||||
|
||||
const SCREENS = { home, new: newGame, load, save, export: exportScreen, import: importScreen, settings, credits, rules, mixer };
|
||||
|
||||
function render() {
|
||||
root.innerHTML = `
|
||||
@@ -324,6 +342,8 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
import: () => go("import"),
|
||||
settings: () => go("settings"),
|
||||
rules: () => go("rules"),
|
||||
mixer: () => go("mixer"),
|
||||
mixerReset: () => { handlers.onSettings({ resetMix: true }); render(); },
|
||||
credits: () => go("credits"),
|
||||
back: () => go("home"),
|
||||
resume: () => handlers.onResume(),
|
||||
@@ -362,10 +382,18 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
ACTIONS[action](arg);
|
||||
});
|
||||
|
||||
root.addEventListener("input", (e) => {
|
||||
const key = e.target.dataset?.mix;
|
||||
if (!key) return;
|
||||
const v = Number(e.target.value);
|
||||
e.target.parentElement.querySelector("output").textContent = `${Math.round(v * 100)}%`;
|
||||
handlers.onSettings(key === "master" ? { volume: v } : { mix: { [key]: v } });
|
||||
});
|
||||
|
||||
root.addEventListener("change", async (e) => {
|
||||
if (e.target.dataset?.mix) handlers.onPreview?.(e.target.dataset.mix);
|
||||
if (e.target.id === "setting-slow") handlers.onSettings({ slow: e.target.checked });
|
||||
if (e.target.id === "setting-sound") { handlers.onSettings({ sound: e.target.checked }); render(); }
|
||||
if (e.target.id === "setting-volume") handlers.onSettings({ volume: Number(e.target.value) });
|
||||
if (e.target.id === "import-file" && e.target.files[0]) {
|
||||
$(root, "#import-text").value = await e.target.files[0].text();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user