diff --git a/static/css/app.css b/static/css/app.css index 3162ee4..4625ee2 100644 --- a/static/css/app.css +++ b/static/css/app.css @@ -1574,23 +1574,13 @@ body.dnd-mode .timer-display { } /* --- Focus station sidebar --- */ -.focus-preset-list { - list-style: none; - display: flex; - flex-direction: column; - gap: 6px; - margin: 10px 0; -} -.focus-preset-list li.focus-preset-active button { - border-color: var(--accent); - color: var(--accent); -} -.focus-custom-input { - display: flex; - flex-direction: column; - gap: 6px; - margin-top: 12px; -} +/* --- Radio sidebar --- */ +.rsb-nowplaying { margin-bottom: 12px; } +.rsb-station-name { font-weight: 600; } +.rsb-track { font-size: 0.85rem; margin-top: 2px; } +.rsb-controls { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; } +.rsb-vol { display: flex; align-items: center; gap: 6px; font-size: 0.85rem; color: var(--muted, #888); } +.rsb-station-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; } /* --- Table of contents sidebar --- */ .toc-list { diff --git a/static/js/app.js b/static/js/app.js index 19b5dc6..b4474f5 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -2733,10 +2733,6 @@ let _isPinching = false; if (typeof pdfjsLib !== 'undefined') { pdfjsLib.GlobalWorkerOptions.workerSrc = '/static/js/pdf.worker.min.js'; } -const DEFAULT_FOCUS_STATION = { - url: 'https://ice5.somafm.com/groovesalad-128-aac', - name: 'SomaFM Groove Salad', -}; async function loadBookList() { if (!IS_AUTHENTICATED) return; @@ -3277,31 +3273,6 @@ async function openBook(bookId) { _resizeObserver.observe(contentEl); } - // Determine which station to play (null = use default, {url:''} = disabled) - const focusStation = USER_FOCUS_STATION === null ? DEFAULT_FOCUS_STATION - : (USER_FOCUS_STATION.url ? USER_FOCUS_STATION : null); - - if (focusStation) { - if (isPlaying) { - // Don't interrupt — highlight button, play on click instead - const btn = $('focus-station-btn'); - if (btn) { - btn.classList.add('focus-pending'); - btn.title = `Click to play focus station: ${focusStation.name}`; - btn._pendingFocusStation = focusStation; - btn.onclick = function () { - playStation(focusStation.url, focusStation.name, null); - btn.classList.remove('focus-pending'); - btn.title = 'Focus station'; - btn._pendingFocusStation = null; - btn.onclick = openFocusStationSidebar; - }; - } - } else { - playStation(focusStation.url, focusStation.name, null); - } - } - enterReaderImmersiveMode(); } catch (e) { @@ -3464,14 +3435,6 @@ function closeReader() { // Remove PDF invert class if (overlay) overlay.classList.remove('pdf-inverted'); - // Clear any pending focus station highlight - const btn = $('focus-station-btn'); - if (btn && btn._pendingFocusStation) { - btn.classList.remove('focus-pending'); - btn.title = 'Focus station'; - btn._pendingFocusStation = null; - btn.onclick = openFocusStationSidebar; - } } function openTocSidebar() { @@ -4570,86 +4533,37 @@ function dismissHighlightPopover() { } // --------------------------------------------------------------------------- -// Focus station sidebar +// Radio sidebar (compact player) // --------------------------------------------------------------------------- -const FOCUS_STATION_PRESETS = [ - {name: 'None (no station)', url: ''}, - {name: 'SomaFM Groove Salad', url: 'https://ice5.somafm.com/groovesalad-128-aac'}, - {name: 'SomaFM Deep Space One', url: 'https://ice5.somafm.com/deepspaceone-128-aac'}, - {name: 'SomaFM Drone Zone', url: 'https://ice5.somafm.com/dronezone-128-aac'}, - {name: 'SomaFM Space Station', url: 'https://ice5.somafm.com/spacestation-128-aac'}, - {name: 'Linn Jazz', url: 'http://radio.linnrecords.com/linnjazz.pls'}, -]; +function openRadioSidebar() { + const stationName = currentStation ? escapeHtml(currentStation.name) : '— no station —'; + const track = currentTrack ? escapeHtml(currentTrack) : ''; + const vol = document.getElementById('volume')?.value ?? 204; -function openFocusStationSidebar() { - // null = never saved (default active); {url:''} = disabled; {url:'...'} = custom - const effectiveUrl = USER_FOCUS_STATION === null ? DEFAULT_FOCUS_STATION.url : (USER_FOCUS_STATION.url || ''); - const currentName = USER_FOCUS_STATION === null ? DEFAULT_FOCUS_STATION.name - : (USER_FOCUS_STATION.name || 'None (no station)'); - - let presetsHtml = FOCUS_STATION_PRESETS.map((p, i) => { - const active = p.url === effectiveUrl ? ' class="focus-preset-active"' : ''; - return ``; - }).join(''); + const rows = [...document.querySelectorAll('#saved-tbody tr[data-id]')]; + const stationsHtml = rows.length + ? rows.map(r => { + const url = JSON.stringify(r.dataset.url || ''); + const name = JSON.stringify(r.dataset.name || ''); + return `
  • `; + }).join('') + : `
  • No saved stations.
  • `; const html = ` -

    Station played when opening a book.

    -

    Current: ${escapeHtml(currentName)}

    - -
    - - - - +
    +
    ${stationName}
    + ${track ? `
    ${track}
    ` : ''}
    +
    + + +
    + `; - openSidebar('Focus Station', html); - - const body = $('sidebar-body'); - body.addEventListener('click', function _focusClick(e) { - const presetBtn = e.target.closest('[data-focus-preset]'); - const saveBtn = e.target.closest('[data-focus-save]'); - const playBtn = e.target.closest('[data-focus-play]'); - if (presetBtn) { - const preset = FOCUS_STATION_PRESETS[parseInt(presetBtn.dataset.focusPreset, 10)]; - if (preset) saveFocusStation(preset.url, preset.name); - body.removeEventListener('click', _focusClick); - } else if (saveBtn) { - const url = (body.querySelector('#focus-custom-url')?.value || '').trim(); - const name = (body.querySelector('#focus-custom-name')?.value || '').trim(); - saveFocusStation(url, name); - body.removeEventListener('click', _focusClick); - } else if (playBtn) { - const url = (body.querySelector('#focus-custom-url')?.value || '').trim(); - const name = (body.querySelector('#focus-custom-name')?.value || '').trim(); - if (url) playStation(url, name, null); - } - }); -} - - -async function saveFocusStation(url, name) { - url = (url || '').trim(); - name = (name || '').trim(); - if (!IS_AUTHENTICATED) { - USER_FOCUS_STATION = {url, name}; - closeSidebar(); - return; - } - try { - const res = await fetch('/accounts/focus-station/', { - method: 'POST', - headers: {'Content-Type': 'application/json', 'X-CSRFToken': getCsrfToken()}, - body: JSON.stringify({url, name}), - }); - const data = await res.json(); - if (data.ok) { - USER_FOCUS_STATION = {url, name}; - closeSidebar(); - } - } catch (e) {} + openSidebar('Radio', html); } // --------------------------------------------------------------------------- diff --git a/templates/radio/player.html b/templates/radio/player.html index ebda44d..79d6d24 100644 --- a/templates/radio/player.html +++ b/templates/radio/player.html @@ -18,7 +18,7 @@ - +