From f607994a5d6ebc8124ee8fe060f45cf3ceb9a87e Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 14 Oct 2026 15:36:43 +0200 Subject: [PATCH] Reset stale reading challenges after navigation --- public/reader.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/public/reader.js b/public/reader.js index 83b9043..67df4ad 100644 --- a/public/reader.js +++ b/public/reader.js @@ -43,7 +43,10 @@ if (result.complete) { message.textContent = 'Unlocked. Opening your chapter…'; location.reload(); return; } message.textContent = 'Correct.'; showQuestion(result); - } catch (error) { message.textContent = error.message; } + } catch (error) { + message.textContent = error.message; + if (/challenge expired/i.test(error.message)) { challenge = null; question.textContent = ''; start.hidden = false; } + } }); question.append(form); input.focus(); }; @@ -55,6 +58,7 @@ window.addEventListener('pagehide', () => { if (challenge) navigator.sendBeacon('api/reading-quiz/abandon', new Blob([JSON.stringify({ challenge })], { type: 'application/json' })); }); + window.addEventListener('pageshow', event => { if (event.persisted) location.reload(); }); setInterval(async () => { try { if ((await api('api/reading-access?' + qsa({ m: P.get('m') }))).allowed) location.reload(); } catch { /* keep the gate visible */ } }, 15000); @@ -67,9 +71,11 @@ catch (e) { canvas.textContent = ''; canvas.append(h('p', { class: 'loading' }, e.message + ' · ', h('a', { href: './' }, 'Library'))); return; } // An already-open chapter also closes when a window ends or an unlock expires. - setInterval(async () => { + const checkReadingAccess = async () => { try { if (!(await api('api/reading-access?' + qsa({ m: P.get('m') }))).allowed) location.reload(); } catch { /* transient check failure */ } - }, 15000); + }; + setInterval(checkReadingAccess, 15000); + document.addEventListener('visibilitychange', () => { if (!document.hidden) checkReadingAccess(); }); const S = me.settings, rtl = D.direction === 'rtl', ttb = D.direction === 'ttb'; const GAP = ttb || S.flowPageGap === false ? 0 : 8, END_H = 280;