Commit graph

55 commits

Author SHA1 Message Date
marwin
def879de2d Fix radio sidebar play buttons broken by JSON.stringify double quotes
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 16s
Inline onclick='playStation("url", "name", null)' broke because
JSON.stringify wraps strings in double quotes, conflicting with the
onclick attribute quotes. Replaced with data attributes + addEventListener.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 17:32:05 +02:00
marwin
f5c141626f Fix blurry PDF rendering when zoomed in Chrome PWA
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 17s
Zoom is now baked into the canvas render scale instead of being applied
via CSS zoom. CSS zoom only scales pixels already on the canvas, causing
blurriness at high DPR (e.g. PWA on mobile). Now the canvas is rendered
at the correct resolution for the chosen zoom level.

Also: stop nulling currentPdfDoc on re-render so PDF.js page cache is
preserved, making zoom re-renders significantly faster.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 16:14:24 +02:00
marwin
e5dc58d84f Replace focus station sidebar with compact radio player sidebar
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
The 📻 button now opens a sidebar with the currently playing station/track,
play/stop + volume control, and the saved stations list. The old focus
station configuration UI (presets, custom URL input, save-to-server) and
the auto-play-on-book-open behavior are removed.

Closes #6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 14:22:07 +02:00
marwin
554ca93e30 Close reader settings panel when tapping content to hide bars
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 14:13:28 +02:00
marwin
6b419c6fe0 Save reader settings per book in localStorage
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 17s
Each book gets its own key (diora_reader_settings_{bookId}).
Opening a book resets to defaults then applies book-specific overrides,
so zoom, spread, invert, theme etc. are remembered independently per book.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 13:53:38 +02:00
marwin
916e8a568b Add PDF two-page spread mode and mobile pinch-to-zoom
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 16s
Spread mode: new toggle in reader settings renders pages side-by-side
(cover alone, then pairs 2-3, 4-5...) using full screen width. Each
page scales to half the container. Navigation and scroll position
tracking are unchanged since per-page IDs are preserved.

Pinch-to-zoom: captures 2-finger pinch on the PDF reader, blocking
native browser zoom. Live CSS zoom during gesture, snaps to nearest
10% step on release. Single-finger scroll unaffected. applyPdfZoom
moved to module level so touch handlers can call it. Touch listeners
cleaned up on reader close.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 13:18:25 +02:00
marwin
e9c5b8058b Centralize remaining magic numbers in settings.py
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
- HIGHLIGHTS_MAX_BYTES, BOOKMARKS_MAX_BYTES: books size limits now in settings
- PODCAST_INBOX_PAGE_SIZE: shared between podcasts/views.py and app.js via DIORA_CONFIG
- VOLUME_DEFAULT: radio stream player default volume
- ITUNES_TIMEOUT: unified iTunes API timeout (was 5s vs 6s inconsistency)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 21:10:14 +02:00
marwin
0a6ba6feac Inject upload size limits from settings into frontend via DIORA_CONFIG
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
Backend settings are now the single source of truth for EBOOK_MAX_BYTES
and BG_MAX_BYTES. A new context processor exposes them to all templates,
and base.html injects them as window.DIORA_CONFIG so app.js reads from
there instead of hardcoded values.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 21:05:51 +02:00
marwin
9c0a046c57 Fix ebook upload: new books appear at top, 50 MB limit frontend/backend
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 17s
- Create EBookProgress on upload so new books get a last_read timestamp
  and sort to the top of the book list
- Update frontend file size check from 10 MB to 50 MB
- Fix backend error message to say 50 MB instead of 10 MB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 21:01:32 +02:00
marwin
2ba613fdd8 Reconnect audio automatically on device change
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 15s
Listens for navigator.mediaDevices.devicechange and re-routes the
audio element to the new default output device without a page reload.
Debounced 500ms to handle BT device bursts. Podcasts resume at the
correct timestamp via loadedmetadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 02:27:18 +02:00
marwin
aff4f5aef2 Mobile: hide volume, add PDF zoom +/- buttons, fix zoom scroll position
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
- Hide volume label/slider/input on mobile (≤600px)
- Add − and + buttons flanking the PDF zoom slider
- Preserve scroll fraction across zoom changes in PDF scroll mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 12:22:04 +02:00
marwin
1bda59e3fc Fix PDF position restore: timer after restore, add scroll-mode case
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
- Move auto-save timer setup to after position restore so an early
  visibilitychange can't overwrite the saved position with 0
- Add missing restore path for non-paginated PDF scroll mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:46:57 +02:00
marwin
68bb7b5920 Add IndexedDB book cache and fix PDF position on mobile
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 15s
- Cache encrypted book data in IndexedDB (cache-first on open)
- Evict books not read for 4 weeks on book list load
- Fix PDF paginated mode not activating on book open (mobile)
- enterPdfPaginatedMode() now called after position restore in openBook()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 16:10:03 +02:00
marwin
dbe3b46f3e Simplify immersive reader: tap centre to toggle bars
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Replace timer/edge-hover system with a simple click-to-toggle.
Tapping interactive elements (buttons, links, settings) is ignored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:50:31 +02:00
marwin
2448586050 Fix PDF rendering blur on high-DPI/mobile screens
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 14s
Scale canvas by devicePixelRatio and constrain CSS size to logical
pixels so PDF pages render crisp on Retina and mobile displays.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:48:44 +02:00
marwin
1af07c7952 Add anchor-based reading position tracking
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Replaces scroll_fraction-only position tracking with element-based
anchors ("{index}:{innerFraction}"). Position is now stable across
font size changes and different screen sizes. A ResizeObserver
restores the anchor on viewport/orientation changes.

Falls back to scroll_fraction for books without a saved anchor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:41:30 +02:00
marwin
bef8fbc8d8 Revert "Remove immersive reader mode, bars stay always visible"
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
This reverts commit bdb6857c73.
2026-04-01 15:24:00 +02:00
marwin
bdb6857c73 Remove immersive reader mode, bars stay always visible
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:23:10 +02:00
marwin
2859464b14 Open HTTP streams in new tab to bypass mixed content
All checks were successful
Build and push Docker image / build (push) Successful in 11s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 11:45:40 +01:00
marwin
da300b54c7 Revert: remove HTTP stream new-tab workaround
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 10:54:48 +01:00
marwin
f040a45325 Open HTTP streams in raw new tab instead of custom HTTPS player
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 14s
The custom /radio/stream-player/ page is served over HTTPS, so the browser
still applies mixed-content restrictions and upgrades http:// audio to https://,
which fails for streams without TLS support.

Fix: window.open(url, '_blank') navigates the tab directly to the HTTP URL.
The tab itself is then HTTP, bypassing mixed-content restrictions entirely.
Browser plays the stream natively with its built-in audio player.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 10:48:28 +01:00
marwin
ee8cfd8314 Fix immersive reader: extend top zone to cover visible bar heights
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
When top bars are showing, use their actual combined offsetHeight (+12px buffer)
as the hide threshold instead of the fixed 60px. This prevents the bars from
disappearing while the mouse moves from the edge zone down to click header buttons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 19:01:37 +01:00
marwin
0037fd8db4 Reader immersive mode: bars slide out after 5s, return on edge hover/tap
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
After opening a book, a 5-second timer adds body.reader-immersive which:
- Slides navbar up (translateY(-100%))
- Slides now-playing bar down (translateY(100%))
- Expands reader overlay to full viewport (top:0, bottom:0)
- Collapses reader header (max-height:0)

Mouse near top edge (<60px): shows navbar + reader header
Mouse near bottom edge (<60px): shows now-playing bar
Touch at top/bottom edge: shows respective bar for 3s then hides again
closeReader() cleans up all classes and event listeners

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 18:04:11 +01:00
marwin
85776390f6 Open HTTP streams in minimal standalone player tab
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 16s
Instead of trying a HTTPS upgrade (which fails for IP-based streams):
- playStation() detects http:// URL on https:// page, opens /radio/stream-player/
  with url, name, vol as query params, then returns — main stream is already
  stopped by the stopPlayback(false) call at the top of playStation()
- New view stream_player renders a standalone minimal player page
- Template: auto-plays on load, correct volume from URL param, volume changes
  synced back to localStorage so main window picks it up next time,
  live track metadata via SSE, tab title updates on track change,
  close-tab button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 17:50:12 +01:00
marwin
83304c197d Try HTTPS upgrade for HTTP streams, show error on failure
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 16s
Browsers block HTTP (mixed content) audio from HTTPS pages. On playStation,
if the URL is http:// and page is https://, try the https:// version first.
If the stream fails to load, show a clear error in the track display instead
of silently doing nothing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 17:22:51 +01:00
marwin
38451514c2 Remove text marking and PDF pagination from master (moved to testing branch)
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
- Remove mouseup highlight selection listener
- Remove Paginated button from PDF settings panel
- Remove pagination auto-enable on book open

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 20:42:03 +01:00
marwin
7392bbcdcc Sort books by last read (most recently read first)
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
Backend includes last_read from EBookProgress.updated_at.
Frontend sorts by last_read desc, unread books by uploaded_at desc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 20:41:13 +01:00
marwin
1026ed09a7 PDF zoom: use CSS zoom instead of re-render, abort stale renders
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
- Add render generation counter (_pdfRenderGen) to abort overlapping renders
- Wrap all pages in #pdf-viewport div; zoom slider just updates style.zoom
- Use 'input' event on zoom slider for live preview without re-rendering
- enterPdfPaginatedMode resets viewport zoom to 1; exitPdfPaginatedMode restores it
- Remove pdfZoom factor from renderPdf scale (CSS zoom handles it now)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 20:22:11 +01:00
marwin
1cba67b3ed Fix PDF zoom: preserve buffer with slice(0), cap base width to 900px
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
- Use arrayBuffer.slice(0) before passing to pdfjsLib.getDocument so PDF.js
  doesn't transfer/detach currentPdfBuffer, enabling re-renders on zoom change
- Cap containerWidth to min(viewport-32, 900px) so PDF doesn't stretch across
  the full viewport on wide screens

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 20:13:45 +01:00
marwin
04818c939e Fix PDF zoom in scroll and paginated mode
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
- Remove max-width:100% from .pdf-page so canvas can exceed container width
- Override max-width:65ch on .pdf-page-wrapper (inherited from reader-content > *)
- Apply pdfZoom factor in pdfSmartZoomPage so paginated mode respects the zoom slider

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 20:02:42 +01:00
Marwin Schulz
b0ce463cca Debug books: show visible status at each load stage, bump SW to v7
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
Each step in loadBookList now updates the visible UI so the exact
failure point is obvious without opening DevTools.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 12:28:00 +01:00
Marwin Schulz
1649eb27a0 Fix ebooks: show wrong-key warning, close overlay on open failure
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
- renderBookList now shows a ⚠️ warning and disables the Open button
  for books that couldn't be decrypted (keyOk: false), telling the user
  to import the correct encryption key
- openBook catch block now hides the reader overlay and shows an alert
  instead of leaving the overlay open with a cryptic error message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 09:45:39 +01:00
Marwin Schulz
4f413c673e Add 'Refresh all' button to podcast toolbar
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
Shows live progress counter (↻ 3/42) while fetching feeds sequentially,
then reloads the current view when done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 09:18:38 +01:00
Marwin Schulz
f049c6ae66 Inbox/queue: clickable feed titles and episode titles
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 14s
- Feed title in inbox and queue is now a link that opens the feed's episode list
- Episode title in inbox is now clickable and opens the show notes sidebar
- Backend: include description in inbox API response so sidebar has content

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 09:12:36 +01:00
Marwin Schulz
afcbe087bb Replace 'recently refreshed' sort with 'most recent episode' in feed list
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Annotates feed queryset with Max(episodes__pub_date) so feeds are sorted
by when their latest episode was published, not when the feed was last fetched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 09:07:01 +01:00
Marwin Schulz
92801c9bbf Add podcast enhancements: AntennaPod parity features + inbox management
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
- 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
marwin
fe5dd3e58a Debug: show specific error in book list instead of generic message
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 06:43:36 +01:00
marwin
2fad4a726c Fix Books tab: auto-generate encryption key, remove password prompt
All checks were successful
Build and push Docker image / build (push) Successful in 11s
Test / test (push) Successful in 16s
- getOrCreateEncKey() now generates a random AES-GCM-256 key if none
  found in localStorage, instead of throwing an error
- Removed enc-key-prompt div from player.html entirely
- Simplified initBookDropZone() — removed prompt show/hide logic
- book-upload-area always visible, no longer hidden behind prompt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:16:22 +01:00
marwin
b9c5f835f4 Add password prompt in Books tab to derive encryption key on-device
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 16s
Bypasses unreliable login-form interception; user enters password once
per device to derive the same PBKDF2 key cross-device.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:29:51 +01:00
marwin
bbd920d75e Revert random key fallback, rely on PBKDF2 login-derived key
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:16:54 +01:00
marwin
2321b80127 Auto-generate encryption key if none exists instead of throwing
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:14:16 +01:00
marwin
c965da6891 Fix USER_ID TDZ error in Firefox by using window.USER_ID
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:59:12 +01:00
marwin
93dcae84d3 Prevent Firefox from opening dragged files outside drop zone
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:55:55 +01:00
marwin
d5db882e30 Default radio tab to Saved instead of Search
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:43:23 +01:00
Marwin Schulz
6d391587c8 Add ebook reader features: highlights, bookmarks, search, settings, PDF paginated mode
All checks were successful
Build and push Docker image / build (push) Successful in 11s
Test / test (push) Successful in 11s
- 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
marwin
0d5ab9a177 Ambient-Chip sucht nur nach "ambient" statt "ambient drone"
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 13s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 21:58:32 +01:00
marwin
cb3b27f0c6 Scrollrad steuert Lautstärke in 4er-Schritten
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 13s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 21:35:27 +01:00
marwin
5c7ab8fb8f Remove volume spinner buttons, select all on click
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 13s
2026-03-16 21:20:31 +01:00
marwin
6c1d95ea90 Show featured stations in search tab empty state
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 13s
2026-03-16 21:16:28 +01:00
marwin
35d979a06a Fix volume slider, add 0-255 number input
All checks were successful
Build and push Docker image / build (push) Successful in 11s
Test / test (push) Successful in 13s
2026-03-16 21:07:12 +01:00