feat: Doing more polishing (M8b)
This commit is contained in:
+31
-1
@@ -7,6 +7,7 @@ import { dateOfDay, restoreState, PRONOUNS } from "../engine/index.js";
|
||||
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";
|
||||
|
||||
const ARM_MS = 4000; // how long a "Sure?" button stays armed
|
||||
|
||||
@@ -17,6 +18,7 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
let armed = null; // "action:arg" waiting for a second click
|
||||
let armTimer = 0;
|
||||
let exportText = "";
|
||||
const rulesCache = {}; // language -> rendered html, or "error"
|
||||
|
||||
const say = (text, kind = "ok") => { message = { text, kind }; };
|
||||
const go = (next) => { screen = next; message = null; disarm(); render(); };
|
||||
@@ -85,6 +87,7 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
${button("load", t("menu.load"))}
|
||||
${button("export", t("menu.export"))}
|
||||
${button("import", t("menu.import"))}
|
||||
${button("rules", t("menu.rules"))}
|
||||
${button("settings", t("menu.settings"))}
|
||||
${button("quit", t("menu.quit"))}
|
||||
</div>`;
|
||||
@@ -100,6 +103,7 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
${button("new", t("menu.new"))}
|
||||
${button("load", t("menu.load"))}
|
||||
${button("import", t("menu.import"))}
|
||||
${button("rules", t("menu.rules"))}
|
||||
${button("settings", t("menu.settings"))}
|
||||
${button("credits", t("menu.credits"))}
|
||||
</div>`;
|
||||
@@ -213,6 +217,13 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
<input type="checkbox" id="setting-slow" ${s.slow ? "checked" : ""}>
|
||||
<span><b>${t("settings.slow")}</b><small>${t("settings.slowHint")}</small></span>
|
||||
</label>
|
||||
<label class="menu__field menu__check">
|
||||
<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>
|
||||
${storage.persistent ? "" : `<p class="menu__msg menu__msg--error">${t("settings.storage")}</p>`}
|
||||
${back()}`;
|
||||
}
|
||||
@@ -226,7 +237,23 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
${back()}`;
|
||||
}
|
||||
|
||||
const SCREENS = { home, new: newGame, load, save, export: exportScreen, import: importScreen, settings, credits };
|
||||
// The rules are plain Markdown files (data/rules/rules.<lang>.md), fetched on first use.
|
||||
function rules() {
|
||||
const lang = getLang();
|
||||
const body = rulesCache[lang];
|
||||
if (body === undefined) {
|
||||
rulesCache[lang] = null; // loading
|
||||
fetch(`data/rules/rules.${lang}.md`)
|
||||
.then((r) => (r.ok ? r.text() : Promise.reject(new Error(String(r.status)))))
|
||||
.then((md) => { rulesCache[lang] = renderMarkdown(md); })
|
||||
.catch(() => { rulesCache[lang] = "error"; })
|
||||
.finally(() => { if (screen === "rules" && !root.hidden) render(); });
|
||||
}
|
||||
const html = body === "error" ? `<p class="menu__msg menu__msg--error">${t("rules.error")}</p>` : body ?? `<p class="menu__sub">${t("rules.loading")}</p>`;
|
||||
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 };
|
||||
|
||||
function render() {
|
||||
root.innerHTML = `
|
||||
@@ -296,6 +323,7 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
export: () => { exportText = encodeSave(getState()); go("export"); },
|
||||
import: () => go("import"),
|
||||
settings: () => go("settings"),
|
||||
rules: () => go("rules"),
|
||||
credits: () => go("credits"),
|
||||
back: () => go("home"),
|
||||
resume: () => handlers.onResume(),
|
||||
@@ -336,6 +364,8 @@ export function createMenu(root, { content, storage, getState, getSettings, hand
|
||||
|
||||
root.addEventListener("change", async (e) => {
|
||||
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