From 1df566d85da6a18122b44b3340eb9f390fc44175 Mon Sep 17 00:00:00 2001 From: nmemmert <67961292+nmemmert@users.noreply.github.com> Date: Wed, 14 Oct 2026 16:02:39 -0400 Subject: [PATCH] Fix mobile header, merge author name variants, clearer playback errors Co-Authored-By: Claude Sonnet 5.5 --- index.html | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 7e9a768..628ad29 100644 --- a/index.html +++ b/index.html @@ -100,7 +100,9 @@ a.pill{text-decoration:none;color:var(--fg);display:inline-block} .chlist .on{color:var(--acc);font-weight:700} #toast{position:fixed;left:50%;bottom:110px;transform:translateX(-50%);background:var(--fg);color:var(--bg);padding:10px 16px;border-radius:99px;font-weight:600;z-index:30;opacity:0;pointer-events:none;transition:opacity .2s} #toast.on{opacity:1} -@media(max-width:560px){.logo span{display:none}.hd{padding:calc(12px + env(safe-area-inset-top)) 14px 12px}main{padding:4px 14px}.grid{grid-template-columns:repeat(auto-fill,minmax(130px,1fr))}} +.brk{display:none} +@media(max-width:560px){.logo span{display:inline}.logo{margin-right:auto}.hd{flex-wrap:wrap;gap:10px;padding:calc(12px + env(safe-area-inset-top)) 14px 12px} +#adminlink,#who{order:1}.brk{display:block;order:2;flex:0 0 100%;height:0}.search{order:3;margin-left:0;min-width:0}#sort{order:3;max-width:48%}main{padding:4px 14px}.grid{grid-template-columns:repeat(auto-fill,minmax(130px,1fr))}} @@ -116,6 +118,7 @@ a.pill{text-decoration:none;color:var(--fg);display:inline-block}
+
Admin @@ -222,7 +225,15 @@ function render() { $('count').textContent = books.length ? `${list.length} book${list.length === 1 ? '' : 's'}` : ''; if (sort === 'author') { const groups = new Map(); - for (const b of list) { const a = author(b) || 'Unknown author'; if (!groups.has(a)) groups.set(a, []); groups.get(a).push(b); } + const labels = new Map(); + for (const b of list) { + const a = author(b) || 'Unknown author', k = a.toLowerCase().replace(/[^\p{L}\p{N}]/gu, ''); + if (!groups.has(k)) { groups.set(k, []); labels.set(k, a); } + groups.get(k).push(b); + } + for (const [k, bs] of groups) groups.set(k, { label: labels.get(k), bs }); + const sorted = [...groups.values()].sort((x, y) => x.label.localeCompare(y.label)); + groups.clear(); sorted.forEach(g => groups.set(g.label, g.bs)); $('grid').className = ''; $('grid').replaceChildren(...[...groups].map(([a, bs]) => { const s = document.createElement('section'); @@ -312,7 +323,11 @@ $('fwd').onclick = () => skip(30); $('pch').onclick = () => jump(-1); $('nch').o audio.onplay = () => { ico('play', 'pause'); ico('mplay', 'pause'); }; audio.onpause = () => { ico('play', 'play'); ico('mplay', 'play'); saveProgress(); }; audio.onended = () => { if (current) setProg(bookId(current), { pos: 0, dur: audio.duration, t: Date.now() }); render(); }; -audio.onerror = () => toast("Playback failed (this browser can't play that format)"); +audio.onerror = () => { + const c = audio.error && audio.error.code, why = { 1: 'aborted', 2: 'network error', 3: 'could not decode', 4: 'format or stream not supported' }[c] || 'unknown'; + console.error('audio error', c, audio.error && audio.error.message, audio.src); + toast(`Playback failed: ${why}${current ? ' ยท ' + (audio.src.split('.').pop().slice(0, 5)) : ''}`); +}; $('seek').oninput = e => { audio.currentTime = e.target.value; }; // ---- cross-device sync (progress is kept by server.py; newest timestamp wins) ----