openvibers/openvibe.live Commits

Setup progress: refresh every surface when a task is completed

OP OpenVibers committed 16 Sept 2026 · 067888baf2 · 3 files, +30 −3

Reported by Maticus: set up a donation goal, get the confetti, and the home page banner still
reads 7/12 until you reload. The setup hub rendered from a snapshot taken when it was first
opened, and nothing told the home banner that anything had changed.

The hub now re-reads progress on every render rather than reusing the snapshot, and closing any
journey fires an event that repaints anything showing setup state. The endpoint is cheap and
cached server-side, so re-reading after something that could have moved the needle costs nothing
and keeps the banner and the hub in step.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CMxJm1dB8rdsaMSgNjVa82

Changes

ddiff --git a/public/index.html b/public/index.html
iindex 8dabf2a0..f2191106 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -5215,8 +5215,8 @@ curl -s https://openvibe.media/live/@Goosely/chat-insight.json | jq ".chat_insig
<script src="/js/footer-live.js?v=1" defer></script>
<script src="/js/home-fx.js?v=9" defer></script>
<script src="/js/home-tour.js?v=6" defer></script>
--<script src="/js/ov-guide.js?v=1" defer></script>
--<script src="/js/guides-live.js?v=5" defer></script>
++<script src="/js/ov-guide.js?v=2" defer></script>
++<script src="/js/guides-live.js?v=6" defer></script>
<!-- ── OpenVibe shared libs (notifications, account sync, themes) ── -->
<script src="/shared/theme-loader.js?v=1" defer></script>
ddiff --git a/public/js/guides-live.js b/public/js/guides-live.js
iindex 15fa2c8b..ae963860 100644
---- a/public/js/guides-live.js
++++ b/public/js/guides-live.js
@@@ -243,13 +243,32 @@
// ── Journey: the setup hub (checklist) ────────────────────
let PROG = null;
async function loadProgress() { try { PROG = await api('/streams/setup-progress'); } catch { PROG = null; } return PROG; }
++
++ /**
++ * Re-read progress and repaint anything that shows it.
++ *
++ * Finishing a task inside a journey changes the answer, but nothing told the rest of the page.
++ * A streamer would set up a donation goal, get the confetti, and still see 7/12 on the home
++ * page banner until they reloaded — reported by Maticus. The setup endpoint is cheap and
++ * cached server-side, so re-reading it after anything that could have moved the needle costs
++ * nothing and keeps every surface honest.
++ */
++ async function refreshSetupProgress() {
++ await loadProgress();
++ try {
++ const slot = document.getElementById('tour-next-up');
++ if (slot && typeof window.setupNextUp === 'function') await window.setupNextUp(slot);
++ } catch { /* */ }
++ }
++ window.refreshSetupProgress = refreshSetupProgress;
G.register('setup-hub', {
title: 'Streamer setup', kicker: 'Streamer setup', noStepBar: true, onOpen: loadProgress,
steps: [{
id: 'hub', title: 'Streamer setup', icon: 'fa-list-check',
heading: 'Your streaming setup',
render: async (ctx) => {
-- const p = PROG || await loadProgress();
++ // Always fresh: the hub is usually reopened straight after finishing something.
++ const p = await loadProgress();
if (!p) return ui.lead('Could not load your setup right now.');
const pct = Math.round((p.done / p.total) * 100);
const groups = {}; p.tasks.forEach(t => { (groups[t.group] = groups[t.group] || []).push(t); });
@@@ -277,6 +296,10 @@
onClose: (ctx, finished) => { if (finished && me()) G.open('setup-hub'); },
});
++ // Any journey finishing may have completed a setup task, so repaint the surfaces that
++ // display progress. Cheap, cached, and it keeps the home banner in step with the hub.
++ document.addEventListener('ovguide:closed', () => { if (me()) refreshSetupProgress(); });
++
// ── Entry points ───────────────────────────────────────────
window.openGoLiveWizard = (o = {}) => { const step = o.step || 'stream'; if (onBroadcast()) return G.open('golive', { step }); G.cfg.navigate(`/broadcast?guide=golive:${step}`); };
window.startGoLiveWizard = () => openGoLiveWizard({ step: 'stream' });
ddiff --git a/public/js/ov-guide.js b/public/js/ov-guide.js
iindex ac63222a..294c60ec 100644
---- a/public/js/ov-guide.js
++++ b/public/js/ov-guide.js
@@@ -141,7 +141,11 @@
S.open = false; root.classList.remove('is-open'); document.body.classList.remove('ovg-lock');
const j = S.journey;
if (j) { store(j.id, { ...(store(j.id) || {}), seen: true, finished: !!finished || !!(store(j.id) || {}).finished, dismissed: !finished, when: Date.now() }); try { if (typeof j.onClose === 'function') j.onClose(S.ctx, !!finished); } catch { /* */ } }
++ const closedId = j ? j.id : null;
S.journey = null; S.step = null;
++ // Anything that watches setup state (the home page banner, the setup hub's own counter)
++ // needs to know a journey just ended — a task may have been completed inside it.
++ try { document.dispatchEvent(new CustomEvent('ovguide:closed', { detail: { journey: closedId, finished: !!finished } })); } catch { /* */ }
}
// ── Spotlight: point at something real on the page ─────────