diff --git a/src/ratatoskr/web/server.py b/src/ratatoskr/web/server.py index 72fee00..433306e 100644 --- a/src/ratatoskr/web/server.py +++ b/src/ratatoskr/web/server.py @@ -112,11 +112,16 @@ def _static_dir() -> str: def _root_endpoint(request: Request) -> FileResponse: - """GET / → index.html. Per FN root_endpoint POST-001.""" + """GET / → index.html. Per FN root_endpoint POST-001. + + no-store: this is an actively-iterated dev console — never let a browser serve a + stale cached page (which silently hid the streaming-TTS / autoplay-unlock updates + during debugging). The HTML is small; a re-fetch per load is free on the LAN.""" from pathlib import Path return FileResponse( Path(_static_dir()) / "index.html", media_type="text/html", + headers={"Cache-Control": "no-store"}, ) diff --git a/src/ratatoskr/web/static/index.html b/src/ratatoskr/web/static/index.html index 292170d..24a104b 100644 --- a/src/ratatoskr/web/static/index.html +++ b/src/ratatoskr/web/static/index.html @@ -2031,6 +2031,12 @@ function _unlockTtsAudio() { }).catch(() => {}); } catch (_) {} } +// Unlock on the FIRST user interaction ANYWHERE on the page — not just toggle/submit — +// so the element has autoplay permission before the delayed speak-on-done play(), no +// matter how the operator first touches the page. _unlockTtsAudio self-guards, so these +// are no-ops once granted. +document.addEventListener("pointerdown", _unlockTtsAudio, true); +document.addEventListener("keydown", _unlockTtsAudio, true); function cancelTts() { // Stop + drop the current