// Keeps the page fresh the way the TUI does: refresh on an interval, but only // while the page is visible, and immediately when it becomes visible again — // which is the moment a phone is picked up after a page. const INTERVAL = 20 * 1000; let refreshFn = null; let timer = 0; let running = false; let inFlight = null; export function start(fn) { refreshFn = fn; running = true; schedule(); } export function stop() { running = false; clearInterval(timer); } // now refreshes straight away and restarts the interval, after an action. export function now() { if (!running) return Promise.resolve(); schedule(); return tick(); } function tick() { if (!refreshFn) return Promise.resolve(); // Collapse overlapping refreshes into the one already under way. if (!inFlight) { inFlight = Promise.resolve() .then(refreshFn) .catch(() => {}) .finally(() => { inFlight = null; }); } return inFlight; } function schedule() { clearInterval(timer); if (running && !document.hidden) timer = setInterval(tick, INTERVAL); } document.addEventListener('visibilitychange', () => { if (!running) return; if (!document.hidden) tick(); schedule(); }); window.addEventListener('online', () => { if (running) tick(); });