- Watchdog connectivite toutes les 60s (check TCP 1.1.1.1:53) - Si offline : scan WiFi et reconnexion auto aux reseaux enregistres - Si internet restaure : flush immediat des spools (email + galerie) - Surprise : capture declenchee 500ms apres affichage (au lieu de 1.7s apres) pour capturer la reaction naturelle des gens Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
584 lines
19 KiB
JavaScript
584 lines
19 KiB
JavaScript
/* Module capture photo - Preview live, compte a rebours, declenchement */
|
|
|
|
let previewActif = false;
|
|
let previewTimeoutId = null;
|
|
let previewInterval = null;
|
|
const PREVIEW_TIMEOUT_MS = 3000;
|
|
let captureAbortee = false;
|
|
let captureEnCours = false; // true pendant tout le flux lancerCapture()
|
|
|
|
const EMOJI_CAR = { 3: '🤪', 2: '😱', 1: '🔥' };
|
|
|
|
// --- Surprise avant capture ---
|
|
|
|
let _surprisePreloaded = null;
|
|
|
|
function prechargerSurprise() {
|
|
const surprise = (config || {}).surprise;
|
|
if (!surprise || !surprise.actif || !surprise.fichier) return;
|
|
if (surprise.type === 'video') return;
|
|
const img = new Image();
|
|
img.src = '/api/surprise/media?t=' + Date.now();
|
|
_surprisePreloaded = img;
|
|
}
|
|
|
|
function montrerSurprise() {
|
|
const surprise = (config || {}).surprise;
|
|
if (!surprise || !surprise.actif || !surprise.fichier) return false;
|
|
|
|
const overlay = document.getElementById('surprise-overlay');
|
|
if (!overlay) return false;
|
|
|
|
if (surprise.type === 'video') {
|
|
overlay.innerHTML = '<video src="/api/surprise/media" autoplay muted playsinline style="max-width:100%;max-height:100%;object-fit:contain"></video>';
|
|
} else {
|
|
if (_surprisePreloaded && _surprisePreloaded.complete) {
|
|
_surprisePreloaded.style.cssText = 'max-width:100%;max-height:100%;object-fit:contain';
|
|
overlay.innerHTML = '';
|
|
overlay.appendChild(_surprisePreloaded);
|
|
} else {
|
|
overlay.innerHTML = '<img src="/api/surprise/media" style="max-width:100%;max-height:100%;object-fit:contain">';
|
|
}
|
|
}
|
|
overlay.style.opacity = '0';
|
|
overlay.classList.remove('cache');
|
|
overlay.style.transition = 'opacity 0.15s';
|
|
overlay.style.opacity = '1';
|
|
return true;
|
|
}
|
|
|
|
function cacherSurprise() {
|
|
const overlay = document.getElementById('surprise-overlay');
|
|
if (!overlay) return;
|
|
overlay.style.opacity = '0';
|
|
setTimeout(() => {
|
|
overlay.classList.add('cache');
|
|
overlay.style.transition = '';
|
|
overlay.style.opacity = '';
|
|
}, 200);
|
|
}
|
|
|
|
// --- Preview live ---
|
|
|
|
function afficherErreurCapture(titre, detail = '') {
|
|
arreterPreview();
|
|
document.getElementById('capture-en-cours')?.classList.add('cache');
|
|
const el = document.getElementById('preview-erreur-camera');
|
|
if (!el) { allerA('accueil'); return; }
|
|
el.querySelector('p').textContent = titre;
|
|
el.querySelector('span').textContent = detail || 'Retour dans 4 secondes...';
|
|
el.classList.remove('cache');
|
|
setTimeout(() => {
|
|
el.classList.add('cache');
|
|
allerA('accueil');
|
|
}, 4000);
|
|
}
|
|
|
|
function afficherErreurPreview(visible) {
|
|
const el = document.getElementById('preview-erreur-camera');
|
|
if (!el) return;
|
|
if (visible) {
|
|
el.querySelector('p').textContent = 'Un instant...';
|
|
el.querySelector('span').textContent = 'L\'appareil photo se reconnecte';
|
|
el.classList.remove('cache');
|
|
} else {
|
|
el.classList.add('cache');
|
|
}
|
|
}
|
|
|
|
function resetPreviewTimeout() {
|
|
if (previewTimeoutId) clearTimeout(previewTimeoutId);
|
|
previewTimeoutId = setTimeout(() => {
|
|
if (previewActif) afficherErreurPreview(true);
|
|
}, PREVIEW_TIMEOUT_MS);
|
|
}
|
|
|
|
function lancerPreview() {
|
|
if (previewActif) return;
|
|
previewActif = true;
|
|
afficherErreurPreview(false);
|
|
document.getElementById('img-preview')?.classList.add('preview-chargement');
|
|
wsEnvoyer({ type: 'preview_start' });
|
|
resetPreviewTimeout();
|
|
}
|
|
|
|
function demarrerEclairageLive() {
|
|
if (!previewActif) {
|
|
previewActif = true;
|
|
wsEnvoyer({ type: 'preview_start' });
|
|
resetPreviewTimeout();
|
|
}
|
|
}
|
|
|
|
function arreterPreview() {
|
|
if (!previewActif) return;
|
|
previewActif = false;
|
|
wsEnvoyer({ type: 'preview_stop' });
|
|
if (previewInterval) {
|
|
clearInterval(previewInterval);
|
|
previewInterval = null;
|
|
}
|
|
if (previewTimeoutId) {
|
|
clearTimeout(previewTimeoutId);
|
|
previewTimeoutId = null;
|
|
}
|
|
afficherErreurPreview(false);
|
|
document.getElementById('cadre-guide-recadrage')?.classList.add('cache');
|
|
}
|
|
|
|
wsOnMessage('preview', (msg) => {
|
|
if (!previewActif) return;
|
|
const img = document.getElementById('img-preview');
|
|
if (img) {
|
|
img.onload = () => {
|
|
img.classList.remove('preview-chargement');
|
|
positionnerGuideRecadrage();
|
|
};
|
|
img.src = msg.image;
|
|
}
|
|
const adminPrev = document.getElementById('eclairage-preview');
|
|
if (adminPrev && document.getElementById('panneau-eclairage')?.classList.contains('actif')) {
|
|
adminPrev.src = msg.image;
|
|
}
|
|
afficherErreurPreview(false);
|
|
resetPreviewTimeout();
|
|
});
|
|
|
|
// --- Cadre de visee : montre en live la zone qui sera gardee apres recadrage ---
|
|
// (la pellicule/le collage recadrent chaque photo au centre selon un ratio different du plein cadre camera)
|
|
|
|
function getRatioCelluleAttendu() {
|
|
if (modeActuel !== 'multi') return null;
|
|
const nb = getNombrePhotos();
|
|
const mode = config.multi_shot?.mode || 'strip';
|
|
if (mode === 'strip') {
|
|
// Reproduit creer_strip() dans backend/collage.py (bande portrait 600x1800, photos empilees)
|
|
const bandeLargeur = 600, bandeHauteur = 1800, marge = 10, sep = 12, perfLargeur = 55;
|
|
const zonePhotosLargeur = bandeLargeur - perfLargeur * 2;
|
|
const espacePhotos = bandeHauteur - marge * 2 - sep * (nb - 1);
|
|
const hauteurCellule = Math.floor(espacePhotos / nb);
|
|
return zonePhotosLargeur / hauteurCellule;
|
|
} else {
|
|
// Reproduit creer_collage() dans backend/collage.py
|
|
const colonnes = 2;
|
|
const largeurPage = 1200, hauteurPage = 1800, margeC = 25;
|
|
const lignes = Math.ceil(nb / colonnes);
|
|
const largeurCellule = Math.floor((largeurPage - margeC * (colonnes + 1)) / colonnes);
|
|
const hauteurCellule = Math.floor((hauteurPage - margeC * (lignes + 1)) / lignes);
|
|
return largeurCellule / hauteurCellule;
|
|
}
|
|
}
|
|
|
|
function positionnerGuideRecadrage() {
|
|
const guide = document.getElementById('cadre-guide-recadrage');
|
|
const img = document.getElementById('img-preview');
|
|
const container = document.getElementById('preview-live');
|
|
if (!guide || !img || !container) return;
|
|
|
|
const ratioCible = getRatioCelluleAttendu();
|
|
if (!ratioCible || !img.naturalWidth || !img.naturalHeight) {
|
|
guide.classList.add('cache');
|
|
return;
|
|
}
|
|
|
|
const cw = container.clientWidth, ch = container.clientHeight;
|
|
const ratioImg = img.naturalWidth / img.naturalHeight;
|
|
const ratioContainer = cw / ch;
|
|
|
|
// Boite affichee de l'image dans le conteneur (object-fit: contain)
|
|
let imgW, imgH, imgTop, imgLeft;
|
|
if (ratioImg > ratioContainer) {
|
|
imgW = cw; imgH = cw / ratioImg;
|
|
imgLeft = 0; imgTop = (ch - imgH) / 2;
|
|
} else {
|
|
imgH = ch; imgW = ch * ratioImg;
|
|
imgTop = 0; imgLeft = (cw - imgW) / 2;
|
|
}
|
|
|
|
// Boite du recadrage final, centree dans l'image affichee (meme logique que _crop_center cote backend)
|
|
let guideW, guideH;
|
|
if (ratioImg > ratioCible) {
|
|
guideH = imgH;
|
|
guideW = imgH * ratioCible;
|
|
} else {
|
|
guideW = imgW;
|
|
guideH = imgW / ratioCible;
|
|
}
|
|
|
|
guide.style.left = `${imgLeft + (imgW - guideW) / 2}px`;
|
|
guide.style.top = `${imgTop + (imgH - guideH) / 2}px`;
|
|
guide.style.width = `${guideW}px`;
|
|
guide.style.height = `${guideH}px`;
|
|
guide.classList.remove('cache');
|
|
}
|
|
|
|
window.addEventListener('resize', positionnerGuideRecadrage);
|
|
|
|
// Erreur camera pendant preview idle : retour accueil
|
|
// Si on est en cours de capture (compte à rebours ou attente API), on ignore :
|
|
// l'API /api/capturer retournera elle-même une erreur si le DSLR est vraiment mort.
|
|
wsOnMessage('camera_erreur', () => {
|
|
arreterPreview();
|
|
if (!captureEnCours) {
|
|
captureAbortee = true;
|
|
if (ecranActuel === 'capture') {
|
|
afficherErreurCapture('Un instant...', 'L\'appareil photo se prepare');
|
|
}
|
|
}
|
|
});
|
|
|
|
wsOnMessage('camera_ok', () => {
|
|
captureAbortee = false;
|
|
afficherErreurPreview(false);
|
|
});
|
|
|
|
wsOnMessage('eclairage', (msg) => {
|
|
if (captureEnCours) return;
|
|
// Admin panel eclairage
|
|
const scoreBox = document.getElementById('eclairage-score-box');
|
|
const actionEl = document.getElementById('eclairage-action');
|
|
const visagesEl = document.getElementById('eclairage-visages');
|
|
if (scoreBox) {
|
|
const score = msg.score >= 0 ? msg.score : '--';
|
|
scoreBox.textContent = score;
|
|
if (msg.action === 'allumer') {
|
|
scoreBox.style.background = '#dc2626'; scoreBox.style.color = '#fff';
|
|
actionEl.textContent = 'ALLUMER LA LUMIERE';
|
|
actionEl.style.color = '#f87171';
|
|
} else if (msg.action === 'attention') {
|
|
scoreBox.style.background = '#d97706'; scoreBox.style.color = '#fff';
|
|
actionEl.textContent = 'Eclairage faible';
|
|
actionEl.style.color = '#fbbf24';
|
|
} else if (msg.action === 'ok') {
|
|
scoreBox.style.background = '#16a34a'; scoreBox.style.color = '#fff';
|
|
actionEl.textContent = 'Eclairage OK';
|
|
actionEl.style.color = '#4ade80';
|
|
} else {
|
|
scoreBox.style.background = '#222'; scoreBox.style.color = '#888';
|
|
actionEl.textContent = 'Aucun visage';
|
|
actionEl.style.color = '#888';
|
|
}
|
|
visagesEl.textContent = msg.visages > 0 ? msg.visages + ' visage' + (msg.visages > 1 ? 's' : '') + ' detecte' + (msg.visages > 1 ? 's' : '') : '';
|
|
}
|
|
});
|
|
|
|
// --- Capture ---
|
|
|
|
async function lancerCapture() {
|
|
captureEnCours = true;
|
|
captureAbortee = false;
|
|
photosSession = [];
|
|
photoImpression = null;
|
|
formatImpression = null;
|
|
|
|
document.getElementById('photo-resultat').src = '';
|
|
document.getElementById('photo-partage').src = '';
|
|
|
|
await chargerCadreImpose();
|
|
majCompteurAccueil();
|
|
|
|
// Verifier l'etat de la camera — attendre si pas prete ou reveil en cours
|
|
try {
|
|
let statut = await apiGet('/api/camera/statut');
|
|
if (!statut.connectee || statut.mode === 'erreur') {
|
|
afficherStatut('Preparation de l\'appareil photo...', 'succes');
|
|
// Attendre jusqu'a 40s que le Canon soit pret (reveil ou reconnexion)
|
|
for (let att = 0; att < 20; att++) {
|
|
await pause(2000);
|
|
statut = await apiGet('/api/camera/statut');
|
|
if (statut.connectee && statut.mode !== 'erreur') break;
|
|
}
|
|
afficherStatut('', '');
|
|
}
|
|
if (!statut.connectee || statut.mode === 'erreur') {
|
|
captureEnCours = false;
|
|
afficherErreurCapture('Appareil photo indisponible', 'Touchez l\'ecran et reessayez');
|
|
return;
|
|
}
|
|
} catch (e) {
|
|
captureEnCours = false;
|
|
afficherErreurCapture('Preparation en cours', 'Touchez l\'ecran et reessayez');
|
|
return;
|
|
}
|
|
|
|
const nbPhotos = getNombrePhotos();
|
|
const compteurEl = document.getElementById('capture-compteur');
|
|
|
|
for (let i = 0; i < nbPhotos; i++) {
|
|
if (nbPhotos > 1) {
|
|
compteurEl.textContent = `Photo ${i + 1} / ${nbPhotos}`;
|
|
} else {
|
|
compteurEl.textContent = '';
|
|
}
|
|
|
|
lancerPreview(); // Miroir live pendant le compte à rebours
|
|
wsEnvoyer({type: 'prepare_capture'});
|
|
const avecPreMessages = (i === 0);
|
|
await compteARebours(avecPreMessages);
|
|
|
|
// Surprise : seulement en photo simple (pas strip/multi)
|
|
// Affiche la surprise PUIS capture pendant que les gens reagissent
|
|
const aSurprise = (modeActuel === 'simple') && montrerSurprise();
|
|
if (aSurprise) await pause(500);
|
|
|
|
// Flash blanc immédiat + lancer capture en parallèle
|
|
const flash = document.getElementById('flash-blanc');
|
|
flash.classList.remove('cache');
|
|
flash.style.animation = 'none';
|
|
flash.offsetHeight;
|
|
flash.style.animation = '';
|
|
|
|
arreterPreview();
|
|
let resultat = await apiPost('/api/capturer').catch(() => null);
|
|
if (aSurprise) { cacherSurprise(); prechargerSurprise(); }
|
|
|
|
if (!resultat && !resultat?.erreur) {
|
|
flash.classList.add('cache');
|
|
document.getElementById('capture-en-cours').classList.add('cache');
|
|
captureEnCours = false;
|
|
afficherErreurCapture('Oups !', 'La photo n\'a pas pu etre prise, reessayez');
|
|
return;
|
|
}
|
|
|
|
if (resultat?.erreur) {
|
|
flash.classList.add('cache');
|
|
document.getElementById('capture-en-cours').classList.add('cache');
|
|
captureEnCours = false;
|
|
const msg = resultat.erreur;
|
|
afficherErreurCapture('Oups !', 'La photo n\'a pas pu etre prise, reessayez');
|
|
return;
|
|
}
|
|
|
|
flash.classList.add('cache');
|
|
document.getElementById('capture-en-cours').classList.add('cache');
|
|
|
|
if (resultat.nom) {
|
|
photosSession.push(resultat.nom);
|
|
}
|
|
}
|
|
|
|
captureEnCours = false;
|
|
await traiterCapture();
|
|
}
|
|
|
|
function getNombrePhotos() {
|
|
if (modeActuel === 'simple') return 1;
|
|
if (modeActuel === 'multi') return config.multi_shot?.nombre_photos || 4;
|
|
return 1;
|
|
}
|
|
|
|
function choisirAnimationAleatoire() {
|
|
// Construire la liste de toutes les animations actives (CSS + custom)
|
|
const cssActives = config.camera?.animations_css_actives || ['classique'];
|
|
const customActives = config.animations_custom?.actives || [];
|
|
|
|
const pool = [
|
|
...cssActives.map(id => ({ type: 'css', id })),
|
|
...customActives.map(nom => ({ type: 'custom', nom })),
|
|
];
|
|
|
|
if (pool.length === 0) return { type: 'css', id: 'classique' };
|
|
return pool[Math.floor(Math.random() * pool.length)];
|
|
}
|
|
|
|
async function compteARebours(avecPreMessages = true) {
|
|
const conteneur = document.getElementById('compte-a-rebours');
|
|
const chiffre = document.getElementById('chiffre-car');
|
|
const duree = config.camera?.compte_a_rebours || 3;
|
|
|
|
// Choisir une animation au hasard parmi les actives
|
|
const anim = choisirAnimationAleatoire();
|
|
|
|
if (anim.type === 'custom') {
|
|
// Jouer la video/gif en plein ecran, shoot des qu'elle finit
|
|
await jouerAnimationCustom(anim.nom);
|
|
return; // pas de compte a rebours CSS
|
|
} else {
|
|
// Animation CSS classique
|
|
conteneur.classList.remove('cache');
|
|
|
|
if (avecPreMessages) {
|
|
const preMessages = ['Attention !', 'Préparez-vous !'];
|
|
for (const msg of preMessages) {
|
|
chiffre.textContent = msg;
|
|
chiffre.className = 'anim-chiffre anim-texte';
|
|
void chiffre.offsetWidth;
|
|
chiffre.classList.add('anim-' + anim.id);
|
|
await pause(1000);
|
|
}
|
|
}
|
|
|
|
for (let i = duree; i > 0; i--) {
|
|
if (anim.id === 'emoji') {
|
|
chiffre.textContent = EMOJI_CAR[i] || i;
|
|
} else {
|
|
chiffre.textContent = i;
|
|
}
|
|
|
|
chiffre.className = 'anim-chiffre';
|
|
void chiffre.offsetWidth;
|
|
chiffre.classList.add('anim-' + anim.id);
|
|
|
|
await pause(1000);
|
|
}
|
|
|
|
conteneur.classList.add('cache');
|
|
}
|
|
}
|
|
|
|
async function jouerAnimationCustom(nom) {
|
|
// Creer un overlay plein ecran pour la video/gif
|
|
const overlay = document.createElement('div');
|
|
overlay.className = 'video-countdown-overlay';
|
|
|
|
const ext = nom.split('.').pop().toLowerCase();
|
|
|
|
if (ext === 'gif') {
|
|
const img = document.createElement('img');
|
|
// Ajouter un timestamp pour forcer le rechargement (relancer le GIF depuis le debut)
|
|
img.src = `/assets/animations/${nom}?t=${Date.now()}`;
|
|
overlay.appendChild(img);
|
|
document.body.appendChild(overlay);
|
|
|
|
// Pour un GIF, on attend sa duree naturelle
|
|
// Comme on ne peut pas detecter la fin d'un GIF, on utilise un fallback de 3s
|
|
// L'utilisateur peut configurer la duree dans le nom du fichier (ex: countdown_5s.gif)
|
|
const match = nom.match(/(\d+)s/);
|
|
const dureeGif = match ? parseInt(match[1]) * 1000 : 3000;
|
|
await pause(dureeGif);
|
|
} else {
|
|
// Video MP4/WebM : on attend la fin exacte de la video
|
|
const video = document.createElement('video');
|
|
video.src = `/assets/animations/${nom}`;
|
|
video.muted = true;
|
|
video.playsInline = true;
|
|
overlay.appendChild(video);
|
|
document.body.appendChild(overlay);
|
|
|
|
await new Promise(resolve => {
|
|
video.onended = resolve;
|
|
video.onerror = resolve;
|
|
video.play().catch(resolve);
|
|
});
|
|
}
|
|
|
|
overlay.remove();
|
|
}
|
|
|
|
function afficherFlash() {
|
|
const flash = document.getElementById('flash-blanc');
|
|
flash.classList.remove('cache');
|
|
flash.style.animation = 'none';
|
|
flash.offsetHeight;
|
|
flash.style.animation = 'flash 0.3s ease-out forwards';
|
|
setTimeout(() => flash.classList.add('cache'), 400);
|
|
}
|
|
|
|
let photoImpression = null; // Fichier à imprimer (strip ou photo finale)
|
|
let formatImpression = null; // Format CUPS à utiliser (ex: "10x15-2up")
|
|
|
|
async function traiterCapture() {
|
|
if (photosSession.length === 0) {
|
|
afficherErreurCapture('Oups !', 'La photo n\'a pas pu etre prise, reessayez');
|
|
return;
|
|
}
|
|
|
|
photoImpression = null;
|
|
formatImpression = null;
|
|
|
|
try {
|
|
if (modeActuel === 'multi') {
|
|
const mode = config.multi_shot?.mode || 'strip';
|
|
let resultat;
|
|
if (mode === 'strip') {
|
|
resultat = await apiPost('/api/strip', { photos: photosSession });
|
|
if (resultat.erreur) {
|
|
afficherErreurCapture('Oups !', 'La planche n\'a pas pu etre creee, reessayez');
|
|
return;
|
|
}
|
|
if (resultat.impression) photoImpression = resultat.impression;
|
|
if (resultat.format_impression) formatImpression = resultat.format_impression;
|
|
} else {
|
|
resultat = await apiPost('/api/collage', { photos: photosSession });
|
|
if (resultat.erreur) {
|
|
afficherErreurCapture('Oups !', 'Le collage n\'a pas pu etre cree, reessayez');
|
|
return;
|
|
}
|
|
}
|
|
if (!resultat.nom) {
|
|
afficherErreurCapture('Oups !', 'Un probleme est survenu, reessayez');
|
|
return;
|
|
}
|
|
photoFinale = resultat.nom;
|
|
afficherPreviewPhoto('/data/exports/' + resultat.nom);
|
|
} else {
|
|
photoFinale = photosSession[0];
|
|
afficherPreviewPhoto('/data/photos/' + photosSession[0]);
|
|
}
|
|
} catch (e) {
|
|
afficherErreurCapture('Erreur reseau', 'Impossible de traiter les photos');
|
|
return;
|
|
}
|
|
|
|
allerA('preview');
|
|
}
|
|
|
|
function afficherPreviewPhoto(chemin) {
|
|
document.getElementById('photo-resultat').src = chemin;
|
|
document.getElementById('photo-partage').src = chemin;
|
|
afficherCadreOverlay(cadreChoisi);
|
|
|
|
if (config.fonctionnalites?.filtres) {
|
|
chargerFiltres();
|
|
}
|
|
if (config.fonctionnalites?.overlays) {
|
|
chargerOverlays();
|
|
}
|
|
if (config.fonctionnalites?.chroma_key) {
|
|
chargerFonds();
|
|
}
|
|
}
|
|
|
|
// --- Compteur accueil ---
|
|
|
|
async function majCompteurAccueil() {
|
|
const etat = await apiGet('/api/compteur');
|
|
const el = document.getElementById('compteur-accueil');
|
|
el.classList.remove('cache');
|
|
document.getElementById('compteur-restant').textContent = etat.restantes;
|
|
document.getElementById('compteur-limite').textContent =
|
|
(etat.actif && etat.limite > 0) ? etat.limite : etat.capacite;
|
|
}
|
|
|
|
async function majBoutonImprimerCompteur() {
|
|
const etat = await apiGet('/api/compteur');
|
|
const btn = document.getElementById('btn-imprimer');
|
|
if (!btn) return;
|
|
if (etat.restantes <= 0) {
|
|
btn.classList.add('cache');
|
|
}
|
|
}
|
|
|
|
async function chargerCadreImpose() {
|
|
if (modeActuel === 'multi') {
|
|
afficherCadreOverlay(null);
|
|
return;
|
|
}
|
|
const fmt = (config.impression?.format || '15x20').replace('-2up', '');
|
|
const data = await apiGet(`/api/cadres-impression/${fmt}`).catch(() => null);
|
|
if (!data) { afficherCadreOverlay(null); return; }
|
|
if (data.event_mode === 'impose' && data.event_cadre) {
|
|
cadreChoisi = data.event_cadre;
|
|
afficherCadreOverlay(cadreChoisi);
|
|
} else if (data.event_mode === 'defaut' && data.event_cadre) {
|
|
cadreChoisi = data.event_cadre;
|
|
afficherCadreOverlay(cadreChoisi);
|
|
} else {
|
|
afficherCadreOverlay(null);
|
|
}
|
|
}
|
|
|
|
function pause(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|