From b5fb8b9c031262723a35dacf77a031fe0d2b8709 Mon Sep 17 00:00:00 2001 From: nmemmert <67961292+nmemmert@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:33:09 -0400 Subject: [PATCH] Keep the audiobooks frame alive when switching tabs The frame was rebuilt with the page content on every route change, which stopped playback. It now lives outside the view and is only shown or hidden. Co-Authored-By: Claude Sonnet 5.5 --- public/app.js | 16 ++++++++++++---- public/index.html | 2 +- public/style.css | 7 +++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/public/app.js b/public/app.js index ec69e4d..775707b 100644 --- a/public/app.js +++ b/public/app.js @@ -128,7 +128,8 @@ function route() { try { editor?.destroyEditor(); } catch {} editor = null; document.body.classList.toggle('editing', name === 'edit'); - document.body.classList.remove('inedit'); + document.body.classList.remove('inedit', 'onaudio'); + const aw = $('#audiowrap'); if (aw) aw.className = 'off'; // hide (not destroy) the audiobooks frame renderNav(name === 'edit' ? 'files' : name); routes[name](rest.map(decodeURIComponent)); $('#view').scrollTop = 0; @@ -465,11 +466,18 @@ function viewAudio() { const url = cfg.audiobooks, c = abCreds(); $('#view').innerHTML = `

Audio

${esc(new URL(url).host)}

-
Open in new tab +
Open in new tab ${c.u ? `` : ''} ${c.p ? `` : ''} - ${c.u || c.p ? '' : 'Save sign-in'}
-
`; + ${c.u || c.p ? '' : 'Save sign-in'}
`; + // Create the frame once and keep it: it is only shown/hidden, never rebuilt, so playback carries on across tabs. + const wrap = $('#audiowrap'); + if (!wrap.firstChild) { + const f = document.createElement('iframe'); + f.src = url; f.title = 'Audiobooks'; f.allow = 'autoplay; fullscreen; picture-in-picture; clipboard-write'; + wrap.appendChild(f); + } + wrap.className = 'on'; document.body.classList.add('onaudio'); const copy = async (v, what) => { try { await navigator.clipboard.writeText(v); toast(what + ' copied. Paste it into the sign-in box.'); } catch { toast('Could not copy'); } }; const cu = $('#cu'), cp = $('#cp'); if (cu) cu.onclick = () => copy(c.u, 'Username'); diff --git a/public/index.html b/public/index.html index d1428d1..f2cb97e 100644 --- a/public/index.html +++ b/public/index.html @@ -17,7 +17,7 @@
-
+
diff --git a/public/style.css b/public/style.css index c6f40f8..2aaab09 100644 --- a/public/style.css +++ b/public/style.css @@ -194,3 +194,10 @@ input[type=search] { width: 100%; min-height: 44px; padding: 0 14px; border-radi /* Editor inside the Office tab: keep the nav, drop the page padding so the editor fills the space */ body.inedit #view { padding: 0; display: flex; flex-direction: column; } + +/* Audiobooks frame lives outside #view so it keeps playing when you change tabs */ +#audiowrap.off { position: fixed; left: -9999px; top: 0; width: 360px; height: 480px; overflow: hidden; } +#audiowrap.on { flex: 1; min-height: 0; padding: 0 calc(var(--sar) + 16px) 16px calc(var(--sal) + 16px); } +#audiowrap iframe { width: 100%; height: 100%; border: 1px solid var(--line); border-radius: 16px; background: var(--panel); } +body.onaudio #view { flex: none; overflow: visible; padding-bottom: 8px; } +@media (min-width: 768px) { #audiowrap.on { padding-right: 32px; padding-left: 32px; padding-bottom: 24px; } }