diff --git a/apps/web/app.js b/apps/web/app.js index 85a0ad3..6beee3f 100644 --- a/apps/web/app.js +++ b/apps/web/app.js @@ -57,6 +57,14 @@ function clearPlayerSignals() { function bindPlayerSignals(watch, name) { const cleanup = []; + let offlineTimer = null; + + const clearOfflineTimer = () => { + if (offlineTimer) { + window.clearTimeout(offlineTimer); + offlineTimer = null; + } + }; const maybeWatch = (signal, onValue) => { if (!signal || typeof signal.watch !== "function") return; @@ -67,16 +75,23 @@ function bindPlayerSignals(watch, name) { let sawLoading = false; maybeWatch(watch?.broadcast?.status, (status) => { if (status === "loading") { + clearOfflineTimer(); sawLoading = true; setHint(`Connecting to relay and subscribing: ${name}`, "ok"); return; } if (status === "live") { + clearOfflineTimer(); setHint(`Live: subscribed to ${name}`, "ok"); return; } if (status === "offline" && sawLoading) { - setHint(`Stream offline or ended: ${name}`, "warn"); + clearOfflineTimer(); + // Avoid flashing a false negative during short reconnect windows. + offlineTimer = window.setTimeout(() => { + setHint(`Connection interrupted, retrying: ${name}`, "warn"); + offlineTimer = null; + }, 8000); } }); @@ -91,6 +106,7 @@ function bindPlayerSignals(watch, name) { if (cleanup.length) { disposePlayerSignals = () => { + clearOfflineTimer(); for (const fn of cleanup) { try { fn(); @@ -111,6 +127,7 @@ function mountPlayer(relayUrl, name) { const watch = document.createElement("moq-watch"); watch.setAttribute("url", relayUrl); watch.setAttribute("path", name); + watch.setAttribute("reload", ""); // A canvas enables video rendering. Without it, only audio is played. const canvas = document.createElement("canvas");