From 0de6c186fb6c4a55aa98fcd24b6e4b658f3422be Mon Sep 17 00:00:00 2001 From: marwin Date: Mon, 17 Aug 2026 15:37:09 +0200 Subject: [PATCH] =?UTF-8?q?B=C3=BCcher:=20"Zuletzt=20gelesen"=20wieder=20a?= =?UTF-8?q?ls=20normale=20Listenansicht=20statt=20Karten-Leiste=20(SW=20v4?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bleibt an der gleichen Stelle (fest oben, unabhängig von Ordner-Navigation und Lesefilter), nutzt jetzt aber dieselben Listeneinträge wie der Rest der Ansicht (inkl. Drei-Punkte-Menü) statt der horizontal scrollbaren Karten. Da ein Buch dadurch gleichzeitig oben bei "Zuletzt gelesen" und unten in der Ordner-/Gesamtliste gerendert werden kann, darf das Drei-Punkte-Menü nicht mehr über eine (dann doppelt vergebene) id gesucht werden — toggleBookMenu bekommt jetzt den geklickten Button und findet sein Menü relativ dazu im DOM. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_011j4LcoeddwFt6Rw8Wyaknj --- static/css/app.css | 45 ++++++++------------------------------------- static/js/app.js | 26 +++++++++++++------------- static/js/sw.js | 2 +- 3 files changed, 22 insertions(+), 51 deletions(-) diff --git a/static/css/app.css b/static/css/app.css index 8242c99..af1ecf6 100644 --- a/static/css/app.css +++ b/static/css/app.css @@ -1658,50 +1658,21 @@ body.dnd-mode .timer-display { cursor: pointer; } -/* --- Recently-read shelf (always pinned atop the books view) --- */ -.book-recent-shelf { +/* --- Recently-read section (always pinned atop the books view, plain list style) --- */ +.book-recent-section { + display: flex; + flex-direction: column; + gap: 6px; margin-bottom: 14px; + padding-bottom: 14px; + border-bottom: 1px solid var(--border); } .book-recent-title { font-size: 13px; font-weight: 600; - margin: 0 0 6px; + margin: 0; color: var(--muted, #888); } -.book-recent-row { - display: flex; - gap: 8px; - overflow-x: auto; - padding-bottom: 2px; -} -.book-recent-item { - flex: 0 0 auto; - display: flex; - flex-direction: column; - gap: 2px; - max-width: 160px; - padding: 8px 10px; - border: 1px solid var(--border); - border-radius: var(--radius); - background: none; - color: var(--fg); - text-align: left; - cursor: pointer; - font: inherit; -} -.book-recent-item-title { - font-size: 13px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.book-recent-item-author { - font-size: 11px; - color: var(--muted, #888); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} /* --- Book folders (single level) --- */ .book-folder-grid { diff --git a/static/js/app.js b/static/js/app.js index 1baa782..39f793a 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -3461,8 +3461,8 @@ function _renderBookItemHtml(b) {
- -
+ +
${broken ? `` : ''} ${b.has_highlights ? `` : ''} @@ -3475,8 +3475,11 @@ function _renderBookItemHtml(b) {
`; } -function toggleBookMenu(bookId) { - const menu = document.getElementById(`book-menu-${bookId}`); +function toggleBookMenu(toggleBtn) { + // Looked up relative to the clicked button (not by id) because the same book — and + // thus the same rendered menu — can appear twice at once: once in the "Zuletzt + // gelesen" section and again further down in the folder/unfiled list. + const menu = toggleBtn.closest('.book-item-menu')?.querySelector('.book-item-menu-list'); if (!menu) return; const willOpen = !menu.classList.contains('open'); document.querySelectorAll('.book-item-menu-list.open').forEach(m => m.classList.remove('open')); @@ -3507,18 +3510,15 @@ function renderBookList(books) { let html = ''; - // Always-visible "recently read" shelf, independent of folder navigation and the - // read/unread filter below — it's a shortcut back into whatever was open last. + // Always-visible "recently read" section, independent of folder navigation and the + // read/unread filter below — it's a shortcut back into whatever was open last. Same + // vertical list-item look as the rest of the list (not a card shelf). const recent = _recentlyReadBooks(books); if (recent.length) { - html += '
' + html += '
' + '

Zuletzt gelesen

' - + '
' - + recent.map(b => ``).join('') - + '
'; + + recent.map(_renderBookItemHtml).join('') + + '
'; } const visible = _bookShowRead ? books : books.filter(b => !b.is_read); diff --git a/static/js/sw.js b/static/js/sw.js index a445d84..990752a 100644 --- a/static/js/sw.js +++ b/static/js/sw.js @@ -2,7 +2,7 @@ * diora service worker — caches the app shell for offline use. */ -const CACHE = 'diora-v39'; +const CACHE = 'diora-v40'; const PODCAST_CACHE = 'diora-podcast-v1'; const SHELL = [ '/static/css/app.css',