fix(audio player + dashboard): markdown bookmark notes, horizontal volume, transport glyphs, client-side badges

Bookmarks: notes are markdown now — capture and drawer edit are
textareas (raw source), display renders through the reader's
markdown-it + DOMPurify pipeline (renderNoteHtml) as x-html; the
edit textarea drops the enter-to-save handler so newlines survive.

Volume: the panel dragger is horizontal (mute button beside it,
7.5rem slider) per user feedback — vertical orientation read as a
scrubber clone at a glance.

Play/pause: unicode glyphs replaced with SVG — the triangle is
optically centered (2px right-bias) and the pause bars are longer
and thicker rounded rects (4.2×15 at rx 1.7).

Dashboard: the client-side card renderer (dashboard.ts — the path the
JSON sections actually render through) now mirrors the templ BookCard:
cover-corner badges for audiobook/comic/manga (books unbadged) and the
hover action shows headphones with 'Listen to …' labels for audiobooks.
BookInfo type + Go struct carry format_group end to end.

Verified on-device: pause glyph centered/thicker, horizontal volume
panel, markdown note ('**bold**' + list) rendered in the bookmarks
drawer, badges on dashboard cards, sections JSON carrying
format_group.
This commit is contained in:
John O'Keefe committed 2026-10-15 18:49:42 -04:00
1 parent 5cf34102d6
commit 2c714dcb60
5 files changed
+65 -16

No files matched your search

+20 -11
View File
@@ -155,8 +155,17 @@ templ AudioReader(user User, metadata ReaderMetadata) {
style="background-color: var(--accent); color: var(--bg-primary);"
aria-label="Play or pause"
>
<span x-show="!playing" class="text-3xl leading-none">▶</span>
<span x-show="playing" class="text-3xl leading-none" x-cloak>❚❚</span>
<span x-show="!playing" class="grid place-items-center">
<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" style="margin-left: 2px;">
<path d="M8 5.2v13.6L19.2 12z"></path>
</svg>
</span>
<span x-show="playing" class="grid place-items-center" x-cloak>
<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<rect x="6.2" y="4.5" width="4.2" height="15" rx="1.7"></rect>
<rect x="13.6" y="4.5" width="4.2" height="15" rx="1.7"></rect>
</svg>
</span>
</button>
<button
type="button"
@@ -305,7 +314,7 @@ templ AudioReader(user User, metadata ReaderMetadata) {
<div
x-show="volumeOpen"
x-cloak
class="absolute bottom-full mb-2 left-1/2 -translate-x-1/2 rounded-xl shadow-lg p-3 flex flex-col items-center gap-2"
class="absolute bottom-full mb-2 left-1/2 -translate-x-1/2 rounded-xl shadow-lg px-3 py-2.5 flex items-center gap-3"
style="background-color: var(--bg-secondary); border: 1px solid var(--border); z-index: 30;"
>
<button
@@ -337,7 +346,7 @@ templ AudioReader(user User, metadata ReaderMetadata) {
:value="muted ? 0 : volume"
@input="setVolume(Number($event.target.value))"
class="accent-current"
style="writing-mode: vertical-lr; direction: rtl; width: 1.25rem; height: 6.5rem;"
style="width: 7.5rem;"
aria-label="Volume"
/>
</div>
@@ -418,9 +427,9 @@ templ AudioReader(user User, metadata ReaderMetadata) {
</button>
</div>
</div>
<p class="text-xs mt-1 line-clamp-2" x-show="b.notes && editingBookmarkId !== String(b.id)" style="color: var(--text-secondary);" x-text="b.notes"></p>
<div class="note-rich text-xs mt-1" x-show="b.notes && editingBookmarkId !== String(b.id)" x-html="bookmarkNoteHtml(b)"></div>
<div x-show="editingBookmarkId === String(b.id)" x-cloak class="mt-1">
<input type="text" x-model="editingNote" class="input text-sm" placeholder="Note" @keydown.enter.prevent="saveNote()"/>
<textarea x-model="editingNote" rows="3" class="input text-sm resize-y" placeholder="Note (markdown)"></textarea>
<div class="flex justify-end gap-2 mt-1">
<button type="button" @click="editingBookmarkId = ''" class="btn btn-ghost text-xs px-2 py-1">Cancel</button>
<button type="button" @click="saveNote()" class="btn btn-primary text-xs px-2 py-1">Save note</button>
@@ -443,12 +452,12 @@ templ AudioReader(user User, metadata ReaderMetadata) {
style="background-color: var(--bg-secondary); border: 1px solid var(--border);"
>
<p class="text-sm font-semibold mb-2" style="color: var(--text-primary);">Bookmark at <span class="tabular-nums" x-text="fmtTime(currentTime)">0:00</span></p>
<input
type="text"
<textarea
x-model="bookmarkNote"
placeholder="Optional note (e.g. 'great quote')"
class="input mb-2"
/>
rows="3"
placeholder="Optional note — markdown welcome (e.g. **great quote**, list, [link](https://…))"
class="input mb-2 resize-y"
></textarea>
<div class="flex justify-end gap-2">
<button type="button" @click="bookmarkCaptureOpen = false" class="btn btn-ghost text-sm px-3 py-1.5">Cancel</button>
<button type="button" @click="saveBookmark()" class="btn btn-primary text-sm px-3 py-1.5">Save</button>