Patch notes page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-21 15:36:16 +01:00
parent eb51bc80b6
commit b27f8682c5
4 changed files with 59 additions and 6 deletions

View file

@ -276,6 +276,7 @@ function render() {
for (const el of document.querySelectorAll("[data-keep]")) kept[el.dataset.keep] = el.value;
const focus = document.activeElement?.dataset?.keep;
if (page === "notes") remember("notes", notesKey());
setHtml($("#side"), S.me ? sidebar() : `<div class="brand"><img src="/static/icon.svg" alt="">Guildhall <small>beta</small></div>${S.dev ? devbar() : ""}`);
setHtml($("#top"), topbar());
// The fires keep burning through a re-render: put the old canvases back in place of the new ones.
@ -349,6 +350,7 @@ function sidebar() {
${nav("orders", ORDER_ICON(), "Work orders", "", takeable ? `<span class="badge">${takeable}</span>` : "", takeable ? `${takeable} for you` : "")}
${nav("board", "💬", "Town board")}
${nav("roster", "👥", "Guild roster", `${S.players.length}`, "", `${S.players.length} ${S.players.length === 1 ? "adventurer" : "adventurers"}`)}
${nav("notes", "📰", "Patch notes", "", notesUnread() ? `<span class="badge">new</span>` : "", notesUnread() ? `What's new: ${C.patch_notes[0].title}` : "")}
<div class="navhead">You</div>
${nav("character", cls.icon, "Character", `${skillOf("combat").icon} ${me.levels.combat}`, "", `Combat level ${me.levels.combat}`)}
${nav("bank", "🏦", "Bank", `${me.slots_used}/${me.slots}`, "", `${me.slots_used} of ${me.slots} bank slots used`)}`;
@ -379,7 +381,7 @@ function devbar() {
</div></div>`;
}
const TITLES = { town: "Town square", council: "Council & threats", orders: "Work orders", board: "Town board", roster: "Guild roster", bank: "Bank", character: "Character" };
const TITLES = { town: "Town square", council: "Council & threats", orders: "Work orders", board: "Town board", roster: "Guild roster", notes: "Patch notes", bank: "Bank", character: "Character" };
function topbar() {
let title = TITLES[page] || "Guildhall";
@ -439,7 +441,7 @@ function pageHtml() {
}
if (page.startsWith("character:")) return characterSheet(page.slice(10));
if (page === "character") return characterSheet(S.uid);
return ({ town, council, orders, board, roster, bank }[page] || town)();
return ({ town, council, orders, board, roster, notes, bank }[page] || town)();
}
// Recipe input as "have / need"; without `have`, just the quantity.
@ -1663,6 +1665,19 @@ function roster() {
}).join("")}</div>`;
}
// Patch notes, newest first. The badge stays until this browser has opened the page since the last release.
const NOTE_KINDS = { new: ["✨", "good", "New"], balance: ["⚖️", "gold", "Balance"], fix: ["🔧", "warn", "Fixed"] };
const notesKey = () => C.patch_notes[0] ? `${C.patch_notes[0].date} ${C.patch_notes[0].title}` : "";
const notesUnread = () => !!C.patch_notes[0] && remember("notes") !== notesKey();
function notes() {
return C.patch_notes.map((release) => `<div class="panel"><h2>${esc(release.title)} <span class="muted small">${esc(release.date)}</span></h2>
<ul class="ledger">${release.notes.map(([kind, text]) => {
const [icon, tone, label] = NOTE_KINDS[kind];
return `<li><span class="tag ${tone}" title="${label}">${icon}</span> ${esc(text)}</li>`;
}).join("")}</ul></div>`).join("");
}
// --- character sheet -----------------------------------------------------
const SLOT_NAMES = { weapon: "Weapon", shield: "Shield", helmet: "Helmet", body: "Body", legs: "Legs" };