Polish: npm test runs every test file, two silent failures now log, Loading placeholders shimmer

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-28 12:43:35 -04:00
1 parent d173555398
commit 551f970721
32 files changed
+68 -47

No files matched your search

+3 -3
View File
@@ -29,7 +29,7 @@ async function viewReader(args = []) {
if (args[0] === 'open' && args[1]) return rdOpen(args[1]);
if (args[0] === 'store') return allowed('store') ? location.replace('#/store/books') : rdStore();
const v = $('#view');
v.innerHTML = '<div class="wrap"><h1>Books</h1><p class="empty">Loading…</p></div>';
v.innerHTML = '<div class="wrap"><h1>Books</h1><p class="empty loading" role="status">Loading…</p></div>';
try { await rdLibrary(); } catch (e) {
if (!location.hash.startsWith('#/read')) return;
v.innerHTML = `<div class="wrap"><h1>Books</h1><p class="err">${esc(e.message)}</p><div class="bar"><button class="btn ghost" id="rdretry">Try again</button></div></div>`;
@@ -167,7 +167,7 @@ async function rdMobiOpen(u8) {
// ======================================================= Book store: free, DRM-free books from Project Gutenberg, Standard Ebooks, the Internet Archive and any OPDS catalogue
async function rdStore(host) { // host: { el, hash } when shown inside the Store tab
const v = host ? host.el : $('#view'), here = () => location.hash.startsWith(host ? host.hash : '#/read/store'); v.innerHTML = '<div class="wrap"><h1>Book store</h1><p class="empty">Loading…</p></div>';
const v = host ? host.el : $('#view'), here = () => location.hash.startsWith(host ? host.hash : '#/read/store'); v.innerHTML = '<div class="wrap"><h1>Book store</h1><p class="empty loading" role="status">Loading…</p></div>';
let sources, mine;
let genreList = []; try { [sources, mine, genreList] = await Promise.all([rdApi('/store/sources'), rdApi('/list'), rdApi('/store/genres').catch(() => [])]); } catch (e) { v.innerHTML = `<div class="wrap"><a class="btn ghost" href="#/read">${icon('back')}Books</a><p class="err">${esc(e.message)}</p></div>`; return; }
if (!here()) return;
@@ -350,7 +350,7 @@ class RdReader {
async deleteNote(n) { this.A.eraseNote?.(n); await this.pushNote({ ...n, del: true }); this.notes = this.notes.filter(x => !x.del); this.$('#rdbm').classList.toggle('on', !!this.isMarked()); this.refreshNotes?.(); }
// ---- panels
async showToc() {
const el = openSheet('Contents', '', '<p class="empty">Loading…</p>'); let items = [];
const el = openSheet('Contents', '', '<p class="empty loading" role="status">Loading…</p>'); let items = [];
try { items = await this.A.toc(); } catch {}
el.querySelector('.empty').outerHTML = items.length ? `<div class="list rdlist">${items.map((t, i) => `<button class="row" data-i="${i}" style="padding-left:${16 + t.depth * 18}px"><span class="grow"><b>${esc(t.label)}</b></span></button>`).join('')}</div>` : '<p class="empty">This book has no table of contents.</p>';
el.querySelectorAll('button.row').forEach(b => b.onclick = () => { closeSheet(); this.A.goto(items[b.dataset.i].loc); });