2026-03-16 19:19:22 +01:00
{% extends "base.html" %}
{% block title %}diora — radio player{% endblock %}
{% block content %}
<!-- ===== NOW PLAYING BAR ===== -->
< section class = "now-playing-bar" id = "now-playing-bar" >
< div class = "now-playing-info" >
< span class = "now-playing-station" id = "now-playing-station" > — no station —< / span >
< span class = "now-playing-track" id = "now-playing-track" > < / span >
< / div >
< div class = "now-playing-controls" >
2026-03-16 20:38:08 +01:00
< button class = "btn btn-play" id = "play-stop-btn" onclick = "togglePlayStop()" style = "display:none;" > ▶ Play< / button >
2026-03-16 19:19:22 +01:00
< label class = "volume-label" >
< span > vol< / span >
2026-03-16 21:07:12 +01:00
< input type = "range" id = "volume" min = "0" max = "255" value = "204" class = "volume-slider" >
< input type = "number" id = "volume-num" min = "0" max = "255" value = "204" class = "volume-num" >
2026-03-16 19:19:22 +01:00
< / label >
< button class = "btn btn-save" id = "save-station-btn" style = "display:none;" onclick = "saveCurrentStation()" > ★ Save< / button >
2026-03-16 20:18:39 +01:00
< button class = "btn-icon" id = "dnd-btn" onclick = "toggleDND()" title = "Focus mode (hides UI, press Esc to exit)" > ⊙< / button >
2026-08-04 09:01:52 +02:00
< button class = "btn-icon" id = "focus-station-btn" onclick = "openRadioSidebar()" title = "Radio" > ◉< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / div >
< div class = "podcast-seek-bar" id = "podcast-seek-bar" style = "display:none;" >
2026-08-04 09:01:52 +02:00
< button class = "btn-icon skip-btn" onclick = "skipBack()" title = "Back 15s" > «  15< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< span class = "seek-time" id = "seek-current" > 0:00< / span >
< input type = "range" id = "seek-slider" class = "seek-slider" min = "0" max = "100" value = "0" >
< span class = "seek-time" id = "seek-duration" > 0:00< / span >
2026-08-04 09:01:52 +02:00
< button class = "btn-icon skip-btn" onclick = "skipForward()" title = "Forward 30s" > 30  »< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div class = "speed-btns" id = "speed-btns" >
< button class = "speed-btn" onclick = "setPlaybackRate(0.75)" > ¾×< / button >
< button class = "speed-btn active" onclick = "setPlaybackRate(1)" > 1× < / button >
< button class = "speed-btn" onclick = "setPlaybackRate(1.25)" > 1¼× < / button >
< button class = "speed-btn" onclick = "setPlaybackRate(1.5)" > 1½× < / button >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< button class = "speed-btn" onclick = "setPlaybackRate(1.75)" > 1¾× < / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< button class = "speed-btn" onclick = "setPlaybackRate(2)" > 2× < / button >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< button class = "speed-btn" onclick = "setPlaybackRate(2.5)" > 2½× < / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / div >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< button class = "btn-icon sleep-timer-btn" id = "sleep-timer-btn" onclick = "openSleepTimerMenu()" title = "Sleep timer" > Sleep< / button >
2026-03-16 19:19:22 +01:00
< / div >
< div class = "timer-widget" id = "timer-widget" >
< span class = "timer-phase" id = "timer-phase-label" > focus< / span >
< span class = "timer-display" id = "timer-display" > 25:00< / span >
< button class = "btn-icon" id = "timer-toggle-btn" onclick = "toggleTimer()" title = "Start/pause timer" > ▶< / button >
< button class = "btn-icon" id = "timer-reset-btn" onclick = "resetTimer()" title = "Reset timer" > ↺< / button >
< span class = "focus-today" id = "focus-today-widget" style = "display:none;" > < / span >
2026-08-04 09:01:52 +02:00
< button class = "btn-icon dnd-only" id = "dnd-light-btn" onclick = "toggleDNDLight()" title = "Toggle black background" > ☼< / button >
2026-03-16 19:19:22 +01:00
< / div >
< / section >
<!-- ===== AFFILIATE / TRACK INFO ===== -->
2026-03-16 20:47:02 +01:00
< section class = "affiliate-section" id = "affiliate-section" style = "display:none;" { % if not amazon_enabled % } data-disabled = "true" { % endif % } >
2026-03-16 19:19:22 +01:00
< img class = "affiliate-artwork" id = "affiliate-artwork" src = "" alt = "Album art" >
< div class = "affiliate-info" >
< div class = "affiliate-track" id = "affiliate-track-name" > < / div >
< div class = "affiliate-artist" id = "affiliate-artist-name" > < / div >
< div class = "affiliate-album" id = "affiliate-album-name" > < / div >
< a class = "btn btn-amazon" id = "affiliate-amazon-link" href = "#" target = "_blank" rel = "noopener noreferrer" >
Buy on Amazon Music
< / a >
< / div >
< / section >
<!-- ===== TABS ===== -->
< div class = "tabs" id = "tabs" >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< button class = "tab-btn active" onclick = "showTab('radio')" > Radio< / button >
2026-03-16 19:19:22 +01:00
< button class = "tab-btn" onclick = "showTab('focus')" > Focus< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< button class = "tab-btn" onclick = "showTab('podcasts')" > Podcasts< / button >
< button class = "tab-btn" onclick = "showTab('books')" > Books< / button >
2026-03-16 19:19:22 +01:00
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
<!-- ===== RADIO TAB ===== -->
< section class = "tab-panel" id = "tab-radio" >
< div class = "tabs sub-tabs" id = "radio-sub-tabs" >
2026-03-19 19:43:23 +01:00
< button class = "tab-btn" onclick = "showRadioTab('search')" > Search< / button >
< button class = "tab-btn active" onclick = "showRadioTab('saved')" > Saved< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< button class = "tab-btn" onclick = "showRadioTab('history')" > History< / button >
2026-03-16 19:19:22 +01:00
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
<!-- ===== SEARCH SUB - PANEL ===== -->
2026-03-19 19:43:23 +01:00
< div class = "sub-tab-panel" id = "tab-search" style = "display:none;" >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div class = "search-bar" >
< input type = "text" id = "search-input" class = "search-input" placeholder = "Search radio-browser.info…" onkeydown = "if(event.key==='Enter') doSearch()" >
< button class = "btn" onclick = "doSearch()" > Search< / button >
2026-03-16 19:19:22 +01:00
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div class = "mood-chips" id = "mood-chips" > < / div >
< div id = "curated-lists" class = "curated-lists-container" > < / div >
< div id = "search-status" class = "status-msg" > < / div >
< table class = "data-table" id = "search-results-table" style = "display:none;" >
2026-03-16 19:19:22 +01:00
< thead >
< tr >
< th > Name< / th >
< th > Bitrate< / th >
< th > Country< / th >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< th > Tags< / th >
2026-03-16 19:19:22 +01:00
< th > < / th >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / tr >
< / thead >
< tbody id = "search-results-body" > < / tbody >
< / table >
< / div >
<!-- ===== SAVED SUB - PANEL ===== -->
2026-03-19 19:43:23 +01:00
< div class = "sub-tab-panel" id = "tab-saved" >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
{% if featured_stations %}
< div class = "featured-section" >
< p class = "featured-label" > ★ Featured< / p >
< ul class = "featured-list" >
{% for s in featured_stations %}
< li >
{% if s.favicon_url %}< img src = "{{ s.favicon_url }}" class = "station-favicon" alt = "" > {% endif %}
< button class = "btn btn-sm" onclick = "playStation('{{ s.url|escapejs }}', '{{ s.name|escapejs }}', null)" >
▶ {{ s.name }}
< / button >
{% if s.description %}< span class = "muted" > {{ s.description }}< / span > {% endif %}
< / li >
{% endfor %}
< / ul >
< / div >
{% endif %}
{% if user.is_authenticated %}
< div id = "recommendations" class = "recommendations-section" >
<!-- populated by JS -->
< / div >
< div class = "import-bar" >
< label class = "btn btn-sm" for = "m3u-file-input" title = "Import .m3u / .m3u8 from the desktop app" >
⇧ Import M3U
< / label >
< input type = "file" id = "m3u-file-input" accept = ".m3u,.m3u8" style = "display:none;" onchange = "importM3U(this)" >
< span id = "import-status" class = "muted" > < / span >
< / div >
< table class = "data-table" id = "saved-table" >
< thead >
< tr >
2026-08-04 09:01:52 +02:00
< th title = "Favorite" > ★ < / th >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< th > Name< / th >
< th > Bitrate< / th >
< th > Country< / th >
< th title = "Notes" > ✎< / th >
< th > < / th >
< th > < / th >
< / tr >
< / thead >
< tbody id = "saved-tbody" >
{% for station in saved_stations %}
< tr id = "saved-row-{{ station.id }}" data-id = "{{ station.id }}" data-url = "{{ station.url }}" data-name = "{{ station.name }}" >
< td >
< button class = "btn-icon fav-btn {% if station.is_favorite %}active{% endif %}"
onclick="toggleFav({{ station.id }})"
title="Toggle favorite">★ < / button >
< / td >
< td class = "station-name-cell" > {{ station.name }}< / td >
< td > {{ station.bitrate }}< / td >
< td > {{ station.country }}< / td >
< td class = "notes-cell" onclick = "editNotes({{ station.id }}, this.textContent.trim())" title = "{{ station.notes|default:'' }}" style = "cursor:pointer; color:#666; max-width:120px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" > {{ station.notes }}< / td >
< td >
< button class = "btn btn-sm"
onclick="playStation('{{ station.url }}', '{{ station.name|escapejs }}', {{ station.id }})">
▶ Play
< / button >
< / td >
< td >
< button class = "btn btn-sm btn-danger"
onclick="removeStation({{ station.id }})">
Remove
< / button >
< / td >
< / tr >
{% empty %}
< tr id = "saved-empty-row" > < td colspan = "7" class = "empty-msg" > No saved stations yet.< / td > < / tr >
{% endfor %}
< / tbody >
< / table >
{% else %}
< p class = "auth-prompt" >
< a href = "{% url 'login' %}" > Log in< / a > or < a href = "{% url 'register' %}" > register< / a >
to save stations and sync across devices.
< / p >
{% endif %}
< / div >
<!-- ===== HISTORY SUB - PANEL ===== -->
< div class = "sub-tab-panel" id = "tab-history" style = "display:none;" >
< table class = "data-table" id = "history-table" >
< thead >
< tr >
< th > Time< / th >
< th > Station< / th >
< th > Track< / th >
< th > ♬ < / th >
2026-03-16 19:19:22 +01:00
< th > < / th >
< / tr >
< / thead >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< tbody id = "history-tbody" >
{% for entry in history %}
< tr data-id = "{{ entry.id }}" >
< td class = "history-time" > {{ entry.played_at|slice:":16"|cut:"T" }}< / td >
< td > {{ entry.station_name }}< / td >
< td > {{ entry.track }}< / td >
< td > {% if entry.scrobbled %}< span title = "Scrobbled to Last.fm" > ✓ < / span > {% endif %}< / td >
< td > < button class = "btn-delete-history" onclick = "deleteHistoryEntry({{ entry.id }}, this)" title = "Remove" > ✕< / button > < / td >
2026-03-16 19:19:22 +01:00
< / tr >
{% empty %}
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< tr id = "history-empty-row" > < td colspan = "5" class = "empty-msg" > No history yet.< / td > < / tr >
2026-03-16 19:19:22 +01:00
{% endfor %}
< / tbody >
< / table >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / div >
2026-03-16 19:19:22 +01:00
< / section >
<!-- ===== FOCUS TAB ===== -->
< section class = "tab-panel" id = "tab-focus" style = "display:none;" >
< table class = "data-table" id = "focus-table" >
< thead >
< tr >
< th > Time< / th >
< th > Station< / th >
< th > Duration< / th >
< / tr >
< / thead >
< tbody id = "focus-tbody" >
< tr > < td colspan = "3" class = "empty-msg" > No focus sessions yet. Start the timer!< / td > < / tr >
< / tbody >
< / table >
< / section >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
<!-- ===== PODCASTS TAB ===== -->
< section class = "tab-panel" id = "tab-podcasts" style = "display:none;" >
{% if user.is_authenticated %}
< div class = "podcast-toolbar" >
< button class = "btn btn-sm" onclick = "showPodcastView('feeds')" > Feeds< / button >
< button class = "btn btn-sm" onclick = "showPodcastView('inbox')" > Inbox< / button >
< button class = "btn btn-sm" onclick = "showPodcastView('queue')" > Queue< / button >
< button class = "btn btn-sm" onclick = "podcastSearchOpen()" > + Search< / button >
2026-03-20 09:18:38 +01:00
< button class = "btn btn-sm" id = "refresh-all-btn" onclick = "refreshAllFeedsBtn(this)" title = "Refresh all feeds" > ↻ All< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< label class = "btn btn-sm" for = "opml-file-input" > Import OPML< / label >
< input type = "file" id = "opml-file-input" accept = ".opml,.xml" style = "display:none;" onchange = "importOPML(this)" >
< span id = "opml-status" class = "muted" > < / span >
< / div >
<!-- Search pane -->
< div class = "podcast-pane" id = "podcast-search-pane" style = "display:none;" >
< div class = "search-bar" >
< input type = "text" id = "podcast-search-input" class = "search-input" placeholder = "Search podcasts…"
onkeydown="if(event.key==='Enter') doPodcastSearch()">
< button class = "btn" onclick = "doPodcastSearch()" > Search< / button >
< / div >
< div id = "podcast-search-status" class = "status-msg" > < / div >
< div id = "podcast-search-list" class = "podcast-search-list" > < / div >
< / div >
<!-- Feeds pane -->
< div class = "podcast-pane" id = "podcast-feeds-pane" >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< div class = "feed-list-toolbar" >
< input type = "text" id = "feed-filter-input" class = "search-input" placeholder = "Search subscriptions…"
oninput="filterFeeds(this.value)">
< select id = "feed-sort-select" onchange = "sortFeeds(this.value)" class = "feed-sort-select" >
< option value = "alpha" > A– Z< / option >
< option value = "alpha-desc" > Z– A< / option >
< option value = "added" > Recently added< / option >
2026-03-20 09:07:01 +01:00
< option value = "latest_episode" > Most recent episode< / option >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< / select >
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div id = "podcast-feed-list" class = "podcast-feed-list" >
< p class = "muted" > Loading…< / p >
< / div >
< / div >
<!-- Inbox pane -->
< div class = "podcast-pane" id = "podcast-inbox-pane" style = "display:none;" >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< div class = "inbox-toolbar" >
< label class = "inbox-select-all-label" >
< input type = "checkbox" id = "inbox-select-all" onchange = "inboxSelectAll(this.checked)" >
< span > All< / span >
< / label >
< div class = "inbox-bulk-actions" id = "inbox-bulk-actions" style = "display:none;" >
< span id = "inbox-selection-count" class = "muted" > < / span >
< button class = "btn btn-sm" onclick = "inboxBulkQueueAdd()" > +Queue< / button >
< button class = "btn btn-sm" onclick = "inboxBulkMarkPlayed()" > ✓ Played< / button >
< button class = "btn btn-sm" onclick = "inboxBulkDownload()" > ⬇ Download< / button >
< button class = "btn btn-sm btn-danger" onclick = "inboxBulkDismiss()" > ✕ Dismiss< / button >
< / div >
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div id = "podcast-inbox-list" class = "episode-list" > < / div >
2026-03-20 09:13:47 +01:00
< div class = "inbox-load-more" id = "inbox-load-more-bar" style = "display:none;" >
< button class = "btn btn-sm" onclick = "inboxLoadMore()" > Load more< / button >
< span id = "inbox-count-label" class = "muted" > < / span >
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / div >
<!-- Episodes pane -->
< div class = "podcast-pane" id = "podcast-episodes-pane" style = "display:none;" >
Add podcast enhancements: AntennaPod parity features + inbox management
- Auto-play next episode from queue when current episode ends
- Sleep timer (N minutes or end-of-episode) with countdown in button
- In-feed episode filter (client-side search)
- Auto-queue new episodes per feed (⚡Q toggle, inserts at top of queue)
- More playback speeds: 1¾× and 2½× added
- Progress bars + structured meta line in all episode list views (feed, inbox, queue)
- Queue drag-and-drop reorder
- Feed list search filter and sort options (A–Z, Z–A, recently added/refreshed)
- DB migration: PodcastFeed.auto_queue, EpisodeProgress.dismissed
- Inbox: dismiss episodes without marking played, checkboxes for multi-select,
bulk actions (add to queue, mark played, download, dismiss), load-more pagination
- Refresh button in single feed view header
- Hourly background refresh of all subscribed feeds
- Full Media Session API for radio and podcast: Windows taskbar thumbnail buttons
(play/pause/stop/next/seek) now work correctly for both modes
- Playing an episode auto-adds it to the queue if not already there
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:55:11 +01:00
< div class = "episode-search-bar" id = "episode-search-bar" style = "display:none;" >
< input type = "text" id = "episode-filter-input" class = "search-input"
placeholder="Filter episodes…" oninput="filterEpisodes(this.value)">
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div id = "podcast-feed-header" class = "podcast-feed-header" > < / div >
< div id = "podcast-episode-list" class = "episode-list" > < / div >
< / div >
<!-- Queue pane -->
< div class = "podcast-pane" id = "podcast-queue-pane" style = "display:none;" >
< ol id = "podcast-queue-ol" class = "podcast-queue-ol" > < / ol >
< / div >
{% else %}
< p class = "auth-prompt" >
< a href = "{% url 'login' %}" > Log in< / a > or < a href = "{% url 'register' %}" > register< / a >
to subscribe to podcasts.
< / p >
{% endif %}
< / section >
<!-- ===== BOOKS TAB ===== -->
< section class = "tab-panel" id = "tab-books" style = "display:none;" >
{% if user.is_authenticated %}
2026-03-19 22:16:22 +01:00
< div id = "book-upload-area" >
2026-03-19 21:29:51 +01:00
< div class = "book-drop-zone" id = "book-drop-zone" >
< span > Drop .epub or .pdf here or < label for = "book-file-input" style = "cursor:pointer;text-decoration:underline;" > browse< / label > < / span >
< input type = "file" id = "book-file-input" accept = ".epub,.pdf" style = "display:none;" onchange = "bookFileSelected(this)" >
< span id = "book-upload-status" class = "muted" > < / span >
< / div >
Bücher: Cloud-Import aus WebDAV/Nextcloud (SW v41)
Verbindungen werden pro Nutzer in den Einstellungen angelegt (Nextcloud,
ownCloud, Synology oder generisches WebDAV) — der Server ist bewusst nicht
auf eine feste Instanz verdrahtet. Im Bücher-Tab lässt sich der entfernte
Ordner durchblättern und eine .epub/.pdf direkt in die Bibliothek ziehen.
Der Download läuft über den Server, weil der WebDAV-Host cross-origin ist
und keine CORS-Header schickt. Verschlüsselt wird trotzdem erst im Browser:
uploadEbook ist in _importEbookBuffer aufgeteilt, das sich lokaler Upload
und Cloud-Import teilen. Gespeichert wird wie bisher nur Geheimtext.
Weil jeder registrierte Nutzer die Ziel-URL bestimmt und diora im Docker-Netz
neben anderen Diensten läuft, ist der Import eine SSRF-Fläche. Dagegen:
- assert_safe_url weist Hosts ab, die auf nicht-öffentliche Adressen
auflösen (inkl. NAT64 und IPv4-kompatibler v6-Adressen, die is_global
durchlässt)
- _assert_peer_is_safe prüft die tatsächliche Peer-Adresse nach dem
Verbinden — requests löst den Namen ein zweites Mal auf, sonst wäre der
Guard per DNS-Rebinding umgehbar
- Redirects werden abgelehnt statt verfolgt
- identische Fehlermeldung für "nicht auflösbar" und "privat", ohne die
IP zu nennen, damit der Endpunkt kein Scanner für interne Dienste wird
Antwort-Bodies laufen durch _read_capped, und DTDs werden vor dem Parsen
abgewiesen: ElementTree expandiert interne Entities, und seit Python 3.12
gibt es XMLParser.parser nicht mehr, um einen Handler zu setzen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 08:26:22 +00:00
< button type = "button" class = "btn" style = "margin:0.5rem 0;" onclick = "toggleCloudImport()" > ☁ Aus Cloud importieren< / button >
< div id = "cloud-browser" class = "cloud-browser" style = "display:none;" >
< div class = "cloud-browser-head" >
< select id = "cloud-source-select" onchange = "_onCloudSourceChange(this.value)" > < / select >
< button type = "button" class = "btn" onclick = "closeCloudImport()" > Schließen< / button >
< / div >
< div id = "cloud-path" class = "cloud-path" > < / div >
< ul id = "cloud-entries" class = "cloud-entries" > < / ul >
< span id = "cloud-status" class = "muted" > < / span >
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / div >
2026-08-04 18:10:33 +02:00
< label class = "book-list-filter" >
< input type = "checkbox" id = "book-show-read-toggle" onchange = "_onBookShowReadToggle(this.checked)" >
Gelesene Bücher anzeigen
< / label >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< div id = "book-list" class = "book-list" > < / div >
{% else %}
< p class = "auth-prompt" >
< a href = "{% url 'login' %}" > Log in< / a > or < a href = "{% url 'register' %}" > register< / a >
to use the encrypted ebook reader.
< / p >
{% endif %}
< / section >
<!-- ===== READER OVERLAY ===== -->
< div id = "reader-overlay" class = "reader-overlay" style = "display:none;" >
< div class = "reader-header" >
< span id = "reader-title" class = "reader-title" > < / span >
< div class = "reader-header-actions" >
< span class = "reader-progress-wrap" >
2026-08-04 13:51:05 +02:00
< input type = "text" inputmode = "decimal" id = "reader-progress-input" class = "volume-num" value = "0" style = "display:none;" >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< span id = "reader-progress-suffix" class = "muted" > < / span >
< / span >
2026-08-04 09:01:52 +02:00
< button class = "btn-icon" id = "reader-search-btn" onclick = "toggleReaderSearch()" title = "Search" > ⌕< / button >
2026-05-31 15:41:35 +02:00
< button class = "btn-icon" id = "reader-settings-btn" onclick = "toggleSettingsPanel()" title = "Font & layout" > ⚙< / button >
< button class = "btn-icon" id = "reader-bookmark-btn" onclick = "addBookmark()" title = "Bookmark" > ★< / button >
2026-08-04 09:01:52 +02:00
< button class = "btn-icon" id = "reader-bm-list-btn" onclick = "openBookmarksSidebar()" title = "Bookmarks" > ▤< / button >
2026-05-31 15:41:35 +02:00
< button class = "btn-icon" id = "reader-toc-btn" onclick = "openTocSidebar()" title = "Table of contents" > ≡< / button >
2026-08-04 10:17:01 +02:00
< button class = "btn-icon" id = "reader-margin-btn" onclick = "toggleAnnotationsMargin()" title = "Notes & highlights" > ✎< / button >
Reader: Notizen auf Mobile schnell setzbar statt über Randspalte (SW v32)
Auf schmalen Screens saß der Marker-Modus-Button bisher nur in der 150px-
Randspalte — man musste sie erst öffnen (und damit den ohnehin knappen
Lesebereich verkleinern), um überhaupt markieren zu können. Jetzt zusätzlich
ein Marker-Button direkt im Haupt-Header (nur <=600px sichtbar, Desktop
bleibt bei der bisherigen Anordnung in der Notes-Leiste).
Im Marker-Modus legt ein einfacher Tap auf reinen Lesetext (ohne Auswahl)
jetzt direkt eine freie Notiz an der Wortposition an — man muss nicht mehr
den exakten Klick-Punkt in der Randspalte treffen. Das Bearbeiten der
Notiz läuft auf schmalen Viewports über ein neues Bottom-Sheet (volle
Breite) statt über das Inline-Textfeld in der 150px-Spalte, das auf dem
Handy-Keyboard unangenehm zu bedienen ist.
Notiz-Objekte werden jetzt erst bei tatsächlich eingegebenem Text angelegt
und gespeichert (vorher: sofort beim Setzen des Ankers) — verhindert, dass
ein abgebrochener/leerer Tap eine Ghost-Notiz in currentHighlights
hinterlässt. Gilt für alle Eingabewege (Bottom-Sheet UND die bestehende
Inline-Randspalten-Bearbeitung), per Playwright verifiziert inkl. Escape-
Cancel auf Desktop.
Priorität laut Nutzer: Notizen-Erfassung muss auf Mobile gut funktionieren;
dass bestehende Notizen dort weniger prominent sichtbar sind, ist explizit
in Ordnung — die vertiefte Auseinandersetzung mit Notizen bleibt eine
Desktop-Aufgabe.
Verifiziert per Playwright (390×844 mobil + 1280×900 Desktop-Regression):
Marker-Button-Sichtbarkeit, Bottom-Sheet-Flow (Erstellen/Abbrechen/Speichern,
kein Ghost-Eintrag), reale Text-Selektion + Highlight+Notiz weiterhin
funktionsfähig auf Mobile, Desktop-Workflow (Randspalte, Inline-Editor,
Escape-Cancel, Blur-Commit) unverändert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 20:13:55 +02:00
< button class = "btn-icon marker-mode-btn reader-marker-btn-mobile" id = "reader-marker-btn-mobile" onclick = "toggleMarkerMode()" title = "Text markieren" > ✒< / button >
2026-05-31 15:41:35 +02:00
< button class = "btn-icon" id = "reader-reset-pos-btn" onclick = "saveReaderProgress(true)" title = "Diese Position als Lesefortschritt setzen (überschreibt gespeicherten Fortschritt)" > ⚑< / button >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< button class = "btn-icon" onclick = "closeReader()" title = "Close (Esc)" > ✕< / button >
< / div >
< / div >
2026-08-04 10:17:01 +02:00
< div id = "reader-body-row" class = "reader-body-row" >
< aside id = "reader-margin" class = "reader-margin" >
< div class = "reader-margin-header" >
< span class = "reader-margin-title" > Notes< / span >
2026-08-04 11:23:16 +02:00
< span class = "reader-margin-header-actions" >
Reader: Notizen auf Mobile schnell setzbar statt über Randspalte (SW v32)
Auf schmalen Screens saß der Marker-Modus-Button bisher nur in der 150px-
Randspalte — man musste sie erst öffnen (und damit den ohnehin knappen
Lesebereich verkleinern), um überhaupt markieren zu können. Jetzt zusätzlich
ein Marker-Button direkt im Haupt-Header (nur <=600px sichtbar, Desktop
bleibt bei der bisherigen Anordnung in der Notes-Leiste).
Im Marker-Modus legt ein einfacher Tap auf reinen Lesetext (ohne Auswahl)
jetzt direkt eine freie Notiz an der Wortposition an — man muss nicht mehr
den exakten Klick-Punkt in der Randspalte treffen. Das Bearbeiten der
Notiz läuft auf schmalen Viewports über ein neues Bottom-Sheet (volle
Breite) statt über das Inline-Textfeld in der 150px-Spalte, das auf dem
Handy-Keyboard unangenehm zu bedienen ist.
Notiz-Objekte werden jetzt erst bei tatsächlich eingegebenem Text angelegt
und gespeichert (vorher: sofort beim Setzen des Ankers) — verhindert, dass
ein abgebrochener/leerer Tap eine Ghost-Notiz in currentHighlights
hinterlässt. Gilt für alle Eingabewege (Bottom-Sheet UND die bestehende
Inline-Randspalten-Bearbeitung), per Playwright verifiziert inkl. Escape-
Cancel auf Desktop.
Priorität laut Nutzer: Notizen-Erfassung muss auf Mobile gut funktionieren;
dass bestehende Notizen dort weniger prominent sichtbar sind, ist explizit
in Ordnung — die vertiefte Auseinandersetzung mit Notizen bleibt eine
Desktop-Aufgabe.
Verifiziert per Playwright (390×844 mobil + 1280×900 Desktop-Regression):
Marker-Button-Sichtbarkeit, Bottom-Sheet-Flow (Erstellen/Abbrechen/Speichern,
kein Ghost-Eintrag), reale Text-Selektion + Highlight+Notiz weiterhin
funktionsfähig auf Mobile, Desktop-Workflow (Randspalte, Inline-Editor,
Escape-Cancel, Blur-Commit) unverändert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 20:13:55 +02:00
< button class = "btn-icon marker-mode-btn" id = "reader-marker-btn" onclick = "toggleMarkerMode()" title = "Mark text" > ✒< / button >
2026-08-04 11:23:16 +02:00
< button class = "btn-icon" id = "reader-margin-list-btn" onclick = "openAnnotationsSidebar()" title = "List all highlights & notes, jump to any of them" > ▦< / button >
< button class = "btn-icon" id = "reader-margin-export-btn" onclick = "exportAnnotations()" title = "Export as text file" > ⭳< / button >
< / span >
2026-08-04 10:17:01 +02:00
< / div >
< div id = "reader-margin-markers" class = "reader-margin-markers" > < / div >
< / aside >
< div id = "reader-content" class = "reader-content" > < / div >
< / div >
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
< / div >
<!-- ===== SIDEBAR ===== -->
< div id = "sidebar-overlay" class = "sidebar-overlay" onclick = "closeSidebar()" style = "display:none;" > < / div >
< aside id = "sidebar" class = "sidebar" >
< div class = "sidebar-header" >
< span id = "sidebar-title" class = "sidebar-title" > < / span >
< button class = "btn-icon sidebar-close" onclick = "closeSidebar()" title = "Close" > ✕< / button >
< / div >
< div id = "sidebar-body" class = "sidebar-body" > < / div >
< / aside >
2026-08-04 09:01:52 +02:00
<!-- ===== MODAL DIALOG (replaces native alert/confirm/prompt) ===== -->
< div id = "modal-overlay" class = "modal-overlay" style = "display:none;" > < / div >
< div id = "modal-dialog" class = "modal-dialog" style = "display:none;" role = "alertdialog" aria-modal = "true" >
< p id = "modal-message" class = "modal-message" > < / p >
< input type = "text" id = "modal-input" class = "search-input modal-input" style = "display:none;" >
< div class = "modal-actions" >
< button type = "button" id = "modal-cancel-btn" class = "btn" style = "display:none;" > Cancel< / button >
< button type = "button" id = "modal-ok-btn" class = "btn btn-primary" > OK< / button >
< / div >
< / div >
2026-03-16 19:19:22 +01:00
{% endblock %}
{% block extra_js %}
< script >
// Pass Django context into JS
2026-03-20 12:58:38 +01:00
const INITIAL_SAVED = {{ saved_stations_json|safe }};
const INITIAL_FEATURED = {{ featured_stations_json|safe }};
2026-03-16 19:19:22 +01:00
const IS_AUTHENTICATED = {{ user.is_authenticated|yesno:"true,false" }};
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
const INITIAL_PODCAST_FEEDS = {{ initial_podcast_feeds|safe }};
2026-03-19 21:04:51 +01:00
window.USER_ID = {{ user.id|default:"null" }};
Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
- Backend: EBookHighlights and EBookBookmarks models with encrypted blob storage;
GET/POST views with size guards (700 KB / 100 KB); migration applied
- Reader header: search, settings, bookmark add/list buttons
- Font & layout settings panel (font size, line height, max width, themes for EPUB;
zoom, invert, paginated for PDF); persisted in localStorage
- Bookmarks: encrypted per-book blob, toast on add, sidebar with jump/delete
- Full-text search: EPUB TreeWalker mark injection, PDF span search; Ctrl+F / F3;
arrow key cycling; highlights re-applied on search clear
- PDF paginated mode: single-page view, tap-zone / swipe / arrow key navigation,
smart zoom (text bounding box → scale+translate canvas), auto-enable on mobile
- Progress tracking fixes: save before hiding overlay (was always writing 100%),
wait for EPUB images to load before restoring scroll, PDF paginated uses page
fraction, sendBeacon cache for unload/visibilitychange reliability
- PDF text layer disabled pending overlay rendering fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:08:42 +01:00
let USER_FOCUS_STATION = {{ focus_station_json|safe }};
2026-03-16 19:19:22 +01:00
< / script >
< script src = "/static/js/app.js" > < / script >
{% endblock %}