// ---------- Action "video" — lecture d'une vidéo de "Mes assets" ---------- // Voir screens/rendering/collision_rules.py::"video" — bloque la suite de // la chaîne "then" jusqu'à la fin de la vidéo (ou un clic sur "Passer"), // même esprit qu'un dialogue (voir dialogue-box-controller.js). Un seul // overlay posé sur
, réutilisé pour chaque lecture (pas la peine // d'en recréer un par appel). let forgeVideoOverlayEl = null; function forgeVideoOverlayRoot() { if (forgeVideoOverlayEl) return forgeVideoOverlayEl; const el = document.createElement('div'); el.className = 'forgeVideoOverlay'; el.innerHTML = '' + ''; document.body.appendChild(el); forgeVideoOverlayEl = el; return el; } // `onDone` : appelé une fois (fin naturelle OU "Passer") — jamais les // deux, `finished` protège contre un double appel (l'événement 'ended' // pouvant encore se déclencher juste après un clic sur "Passer"). function forgeShowVideoOverlay(url, mode, onDone) { if (!url) { if (onDone) onDone(); return; } const root = forgeVideoOverlayRoot(); root.className = `forgeVideoOverlay ${mode === 'incrustation' ? 'forgeVideoOverlay-incrustation' : 'forgeVideoOverlay-pleinEcran'}`; root.style.display = 'flex'; const player = root.querySelector('.forgeVideoOverlayPlayer'); const skipBtn = root.querySelector('.forgeVideoOverlaySkip'); let finished = false; function finish() { if (finished) return; finished = true; root.style.display = 'none'; player.pause(); player.removeAttribute('src'); player.onended = null; skipBtn.onclick = null; if (onDone) onDone(); } player.src = url; player.onended = finish; skipBtn.onclick = finish; // lecture bloquée par le navigateur (pas d'interaction récente) : reste // affichée, "Passer" fonctionne toujours. player.play().catch(() => {}); } // static/js/play/__tests__/ (node:test) — même garde que le reste de // static/js/play/. if (typeof module !== 'undefined' && module.exports) { module.exports = { forgeShowVideoOverlay }; }