This commit is contained in:
pporcheret
2026-10-30 22:10:03 +01:00
parent 7f26f9b015
commit 90ffa635a0
161 changed files with 19042 additions and 111 deletions
+53
View File
@@ -0,0 +1,53 @@
/* DONA_V7_FACE — capture ponctuelle, aucun flux continu ni enrôlement. */
(() => {
'use strict';
if (document.getElementById('donaFaceButton')) return;
function init() {
const camera = document.getElementById('avTopCamera') || document.getElementById('cameraPopupButton');
if (!camera) return;
const button = document.createElement('button');
button.id = 'donaFaceButton';
button.className = camera.className;
button.type = 'button';
button.title = 'Reconnaître la personne devant la caméra';
button.setAttribute('aria-label', button.title);
button.innerHTML = '<svg aria-hidden="true" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m13-5h3a2 2 0 0 1 2 2v3M3 16v3a2 2 0 0 0 2 2h3m13-5v3a2 2 0 0 1-2 2h-3"/><circle cx="12" cy="10" r="3"/><path d="M6.7 18c.7-2.8 3-4.2 5.3-4.2s4.6 1.4 5.3 4.2"/></svg>';
camera.after(button);
const box = document.createElement('div');
box.id = 'donaFacePanel'; box.className = 'dona-face-panel';
box.hidden = true;box.setAttribute('role','dialog');
box.setAttribute('aria-label','Reconnaissance faciale Dona');
box.innerHTML = '<div class="dona-face-card"><div class="dona-face-head"><strong>Reconnaissance faciale</strong><button type="button" id="donaFaceClose" aria-label="Fermer">×</button></div><p id="donaFaceText" role="status" aria-live="polite"></p></div>';
document.body.append(box);
const text = box.querySelector('#donaFaceText');
let pending = false;
const close = () => {box.hidden = true;};
box.querySelector('#donaFaceClose').addEventListener('click',close);
box.addEventListener('click',e=>{if(e.target===box)close();});
document.addEventListener('keydown',e=>{if(e.key==='Escape'&&!box.hidden)close();});
button.addEventListener('click',async()=>{
if(pending)return;
pending = true;button.disabled = true;
const preview=document.getElementById('cameraPopup');
if(preview && !preview.hidden){document.getElementById('cameraPopupClose')?.click();await new Promise(resolve=>setTimeout(resolve,300));}
box.hidden = false;text.textContent = 'Capture et identification en cours…';
try {
const r = await fetch('/api/dona/face/identify',{
method:'POST',credentials:'same-origin',headers:{'X-Alfred-Request':'1'},cache:'no-store'
});
const data = await r.json();
if(!r.ok)throw new Error(data.error||`Erreur HTTP ${r.status}`);
} catch(err) { pending=false;button.disabled=false;text.textContent=err.message||'Identification indisponible.'; }
});
window.alfredSocket?.on('dona_face_status',data=>{
if(pending && !box.hidden) text.textContent=String(data?.message||'Analyse en cours…');
});
window.alfredSocket?.on('dona_face_result',data=>{
if(!pending)return;
pending=false;button.disabled=false;
text.textContent=String(data?.text||'Aucun résultat exploitable.');
});
}
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init,{once:true});
else init();
})();